mirror of
https://github.com/lihop/godot-xterm.git
synced 2024-11-10 04:40:25 +01:00
parent
a55a05d3a4
commit
9bd17ec8dc
31 changed files with 5058 additions and 1031 deletions
|
@ -1,64 +0,0 @@
|
||||||
tool
|
|
||||||
extends EditorPlugin
|
|
||||||
|
|
||||||
const Label3D = preload("label_3d.gd")
|
|
||||||
|
|
||||||
var converter_button : Button
|
|
||||||
var edited_node : Label3D
|
|
||||||
|
|
||||||
func _enter_tree():
|
|
||||||
yield(get_tree(), "idle_frame")
|
|
||||||
|
|
||||||
add_custom_type(
|
|
||||||
"Label3D", "Spatial",
|
|
||||||
Label3D,
|
|
||||||
preload("icon_label_3d.svg")
|
|
||||||
)
|
|
||||||
|
|
||||||
if not converter_button:
|
|
||||||
converter_button = preload("label_3d_converter.tscn").instance()
|
|
||||||
add_control_to_container(EditorPlugin.CONTAINER_SPATIAL_EDITOR_MENU, converter_button)
|
|
||||||
converter_button.connect("mesh_generated", self, "generate_mesh")
|
|
||||||
converter_button.hide()
|
|
||||||
|
|
||||||
print("3d text plugin added to project.")
|
|
||||||
|
|
||||||
|
|
||||||
func _exit_tree():
|
|
||||||
remove_custom_type("Label3D")
|
|
||||||
remove_control_from_container(EditorPlugin.CONTAINER_SPATIAL_EDITOR_MENU, converter_button)
|
|
||||||
|
|
||||||
print("3d text plugin removed from project.")
|
|
||||||
|
|
||||||
|
|
||||||
func handles(object : Object) -> bool:
|
|
||||||
var handle = object is Label3D
|
|
||||||
|
|
||||||
if not handle:
|
|
||||||
converter_button.hide()
|
|
||||||
|
|
||||||
return handle
|
|
||||||
|
|
||||||
|
|
||||||
func edit(object):
|
|
||||||
edited_node = object
|
|
||||||
if edited_node is Label3D:
|
|
||||||
converter_button.show()
|
|
||||||
converter_button.label3d = object
|
|
||||||
else:
|
|
||||||
converter_button.hide()
|
|
||||||
|
|
||||||
|
|
||||||
func clear():
|
|
||||||
edited_node = null
|
|
||||||
converter_button.hide()
|
|
||||||
|
|
||||||
func generate_mesh(mesh_inst):
|
|
||||||
var undo_redo = get_undo_redo()
|
|
||||||
undo_redo.create_action("Convert Text")
|
|
||||||
|
|
||||||
undo_redo.add_do_method(edited_node.get_parent(), "add_child", mesh_inst)
|
|
||||||
undo_redo.add_undo_method(edited_node.get_parent(), "remove_child", mesh_inst)
|
|
||||||
undo_redo.commit_action()
|
|
||||||
|
|
||||||
mesh_inst.set_owner(get_editor_interface().get_edited_scene_root())
|
|
|
@ -1,21 +0,0 @@
|
||||||
MIT License
|
|
||||||
|
|
||||||
Copyright (c) 2019 Roujel Williams
|
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
|
||||||
in the Software without restriction, including without limitation the rights
|
|
||||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
copies of the Software, and to permit persons to whom the Software is
|
|
||||||
furnished to do so, subject to the following conditions:
|
|
||||||
|
|
||||||
The above copyright notice and this permission notice shall be included in all
|
|
||||||
copies or substantial portions of the Software.
|
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
||||||
SOFTWARE.
|
|
|
@ -1,47 +0,0 @@
|
||||||
class_name ArrayUtils
|
|
||||||
|
|
||||||
# Shifts the array's values by a specified amount.
|
|
||||||
# Positive amount shifts right while negative shifts left.
|
|
||||||
static func shift_array(array : Array, amount : int):
|
|
||||||
var right = bool(sign(amount) * 0.5 + 0.5)
|
|
||||||
for i in abs(amount):
|
|
||||||
var value
|
|
||||||
if right:
|
|
||||||
value = array.pop_back()
|
|
||||||
array.push_front(value)
|
|
||||||
else:
|
|
||||||
value = array.pop_front()
|
|
||||||
array.push_back(value)
|
|
||||||
|
|
||||||
# Combines the array with the other array.
|
|
||||||
static func append_array(array : Array, other : Array):
|
|
||||||
for i in other:
|
|
||||||
array.append(i)
|
|
||||||
|
|
||||||
# Splits the array between a and b at index.
|
|
||||||
static func split_array(array : Array, index : int, a : Array, b : Array):
|
|
||||||
for i in range(0, index):
|
|
||||||
a.append(array[i])
|
|
||||||
|
|
||||||
for i in range(index, array.size()):
|
|
||||||
b.append(array[i])
|
|
||||||
|
|
||||||
# Converts array to dictionary
|
|
||||||
static func to_dictionary(array : Array) -> Dictionary:
|
|
||||||
var dict = {}
|
|
||||||
for i in array.size():
|
|
||||||
dict[i] = array[i]
|
|
||||||
return dict
|
|
||||||
|
|
||||||
# Calls a function per object in the array with variable arguments.
|
|
||||||
static func call_per_element(array : Array, function : String, vars = null):
|
|
||||||
match typeof(vars):
|
|
||||||
TYPE_NIL:
|
|
||||||
for e in array:
|
|
||||||
e.call(function)
|
|
||||||
TYPE_ARRAY:
|
|
||||||
for e in array:
|
|
||||||
e.callv(function, vars)
|
|
||||||
_:
|
|
||||||
for e in array:
|
|
||||||
e.call(function, vars)
|
|
|
@ -1,8 +0,0 @@
|
||||||
[gd_resource type="DynamicFont" load_steps=2 format=2]
|
|
||||||
|
|
||||||
[ext_resource path="res://addons/SIsilicon.3d.text/default_font.ttf" type="DynamicFontData" id=1]
|
|
||||||
|
|
||||||
[resource]
|
|
||||||
size = 100
|
|
||||||
use_filter = true
|
|
||||||
font_data = ExtResource( 1 )
|
|
Binary file not shown.
|
@ -1 +0,0 @@
|
||||||
<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m6 3a1.0001 1.0001 0 0 0 -.70703.29297l-4 4a1.0001 1.0001 0 0 0 0 1.4141l4 4a1.0001 1.0001 0 0 0 .70703.29297h8a1.0001 1.0001 0 0 0 1-1v-8a1.0001 1.0001 0 0 0 -1-1h-8zm-1 4a1 1 0 0 1 1 1 1 1 0 0 1 -1 1 1 1 0 0 1 -1-1 1 1 0 0 1 1-1z" fill="#fc9c9c" fill-rule="evenodd"/></svg>
|
|
Before Width: | Height: | Size: 367 B |
|
@ -1,34 +0,0 @@
|
||||||
[remap]
|
|
||||||
|
|
||||||
importer="texture"
|
|
||||||
type="StreamTexture"
|
|
||||||
path="res://.import/icon_label_3d.svg-66ebb0fa17446da110a5ed153702e3c3.stex"
|
|
||||||
metadata={
|
|
||||||
"vram_texture": false
|
|
||||||
}
|
|
||||||
|
|
||||||
[deps]
|
|
||||||
|
|
||||||
source_file="res://addons/SIsilicon.3d.text/icon_label_3d.svg"
|
|
||||||
dest_files=[ "res://.import/icon_label_3d.svg-66ebb0fa17446da110a5ed153702e3c3.stex" ]
|
|
||||||
|
|
||||||
[params]
|
|
||||||
|
|
||||||
compress/mode=0
|
|
||||||
compress/lossy_quality=0.7
|
|
||||||
compress/hdr_mode=0
|
|
||||||
compress/bptc_ldr=0
|
|
||||||
compress/normal_map=0
|
|
||||||
flags/repeat=0
|
|
||||||
flags/filter=true
|
|
||||||
flags/mipmaps=false
|
|
||||||
flags/anisotropic=false
|
|
||||||
flags/srgb=2
|
|
||||||
process/fix_alpha_border=true
|
|
||||||
process/premult_alpha=false
|
|
||||||
process/HDR_as_SRGB=false
|
|
||||||
process/invert_color=false
|
|
||||||
stream=false
|
|
||||||
size_limit=0
|
|
||||||
detect_3d=true
|
|
||||||
svg/scale=1.0
|
|
|
@ -1,148 +0,0 @@
|
||||||
tool
|
|
||||||
extends Spatial
|
|
||||||
|
|
||||||
export(String, MULTILINE) var text = "Text" setget set_text
|
|
||||||
export(float) var text_scale = 0.01 setget set_text_scale
|
|
||||||
export(float) var extrude = 0.0 setget set_extrude
|
|
||||||
export(Font) var font setget set_font;
|
|
||||||
|
|
||||||
export(int, "Left", "Right", "Center", "Fill") var align setget set_align
|
|
||||||
|
|
||||||
export(Color) var color = Color(0.6, 0.6, 0.6) setget set_color
|
|
||||||
export(float, 0, 1) var metallic = 0.0 setget set_metallic
|
|
||||||
export(float, 0, 1) var roughness = 0.5 setget set_roughness
|
|
||||||
|
|
||||||
export(int) var max_steps = 256 setget set_max_steps
|
|
||||||
export(float) var step_size = 1.0 setget set_step_size
|
|
||||||
|
|
||||||
var label
|
|
||||||
var viewport
|
|
||||||
var proxy
|
|
||||||
var material
|
|
||||||
|
|
||||||
func _ready():
|
|
||||||
for i in range(get_child_count()):
|
|
||||||
remove_child(get_child(0))
|
|
||||||
|
|
||||||
viewport = preload("text_viewport.tscn").instance()
|
|
||||||
label = viewport.get_node("Label")
|
|
||||||
add_child(viewport)
|
|
||||||
|
|
||||||
proxy = MeshInstance.new()
|
|
||||||
proxy.mesh = CubeMesh.new()
|
|
||||||
proxy.material_override = preload("label_3d.material").duplicate()
|
|
||||||
material = proxy.material_override
|
|
||||||
|
|
||||||
var view_texture = viewport.get_texture()
|
|
||||||
view_texture.flags = Texture.FLAG_FILTER
|
|
||||||
material.set_shader_param("text", view_texture)
|
|
||||||
add_child(proxy)
|
|
||||||
|
|
||||||
set_align(align)
|
|
||||||
set_font(font)
|
|
||||||
set_text(text)
|
|
||||||
set_text_scale(text_scale)
|
|
||||||
set_extrude(extrude)
|
|
||||||
|
|
||||||
set_color(color)
|
|
||||||
set_metallic(metallic)
|
|
||||||
set_roughness(roughness)
|
|
||||||
|
|
||||||
set_max_steps(max_steps)
|
|
||||||
set_step_size(step_size)
|
|
||||||
|
|
||||||
|
|
||||||
func set_text(string):
|
|
||||||
text = string;
|
|
||||||
if label:
|
|
||||||
label.text = text
|
|
||||||
label.rect_size = Vector2()
|
|
||||||
label.force_update_transform()
|
|
||||||
|
|
||||||
var size = label.rect_size
|
|
||||||
viewport.size = size
|
|
||||||
|
|
||||||
viewport.render_target_update_mode = Viewport.UPDATE_ALWAYS
|
|
||||||
yield(get_tree(), "idle_frame")
|
|
||||||
|
|
||||||
label.rect_size = Vector2()
|
|
||||||
label.force_update_transform()
|
|
||||||
|
|
||||||
size = label.rect_size
|
|
||||||
viewport.size = size
|
|
||||||
|
|
||||||
yield(get_tree(), "idle_frame")
|
|
||||||
viewport.render_target_update_mode = Viewport.UPDATE_DISABLED
|
|
||||||
|
|
||||||
proxy.scale.x = size.x * text_scale
|
|
||||||
proxy.scale.y = size.y * text_scale
|
|
||||||
|
|
||||||
func set_text_scale(scale):
|
|
||||||
text_scale = scale
|
|
||||||
if label:
|
|
||||||
var size = label.rect_size
|
|
||||||
if proxy:
|
|
||||||
proxy.scale.x = size.x * text_scale
|
|
||||||
proxy.scale.y = size.y * text_scale
|
|
||||||
|
|
||||||
func set_extrude(ext):
|
|
||||||
extrude = ext
|
|
||||||
|
|
||||||
if proxy:
|
|
||||||
proxy.scale.z = extrude if extrude != 0 else 1
|
|
||||||
material.set_shader_param("extrude", extrude != 0)
|
|
||||||
|
|
||||||
if extrude == 0 and proxy.mesh is CubeMesh:
|
|
||||||
proxy.mesh = QuadMesh.new()
|
|
||||||
proxy.mesh.size = Vector2(2, 2)
|
|
||||||
elif proxy.mesh is QuadMesh:
|
|
||||||
proxy.mesh = CubeMesh.new()
|
|
||||||
|
|
||||||
func set_font(f):
|
|
||||||
font = f
|
|
||||||
if label:
|
|
||||||
if font:
|
|
||||||
label.add_font_override("font", font)
|
|
||||||
else:
|
|
||||||
label.add_font_override("font", preload("default_font.tres"))
|
|
||||||
set_text(text)
|
|
||||||
|
|
||||||
func set_align(al):
|
|
||||||
align = al
|
|
||||||
if label:
|
|
||||||
match align:
|
|
||||||
0:
|
|
||||||
label.align = Label.ALIGN_LEFT
|
|
||||||
1:
|
|
||||||
label.align = Label.ALIGN_RIGHT
|
|
||||||
2:
|
|
||||||
label.align = Label.ALIGN_CENTER
|
|
||||||
3:
|
|
||||||
label.align = Label.ALIGN_FILL
|
|
||||||
|
|
||||||
set_text(text)
|
|
||||||
|
|
||||||
func set_color(col):
|
|
||||||
color = col
|
|
||||||
if material:
|
|
||||||
material.set_shader_param("albedo", color)
|
|
||||||
|
|
||||||
func set_metallic(metal):
|
|
||||||
metallic = metal
|
|
||||||
if material:
|
|
||||||
material.set_shader_param("metallic", metallic)
|
|
||||||
|
|
||||||
func set_roughness(rough):
|
|
||||||
roughness = rough
|
|
||||||
if material:
|
|
||||||
material.set_shader_param("roughness", roughness)
|
|
||||||
|
|
||||||
func set_max_steps(max_s):
|
|
||||||
max_steps = max(max_s, 8)
|
|
||||||
if material:
|
|
||||||
material.set_shader_param("maxSteps", max_steps)
|
|
||||||
|
|
||||||
func set_step_size(step_s):
|
|
||||||
step_size = max(step_s, 0)
|
|
||||||
if material:
|
|
||||||
material.set_shader_param("stepSize", step_size)
|
|
Binary file not shown.
|
@ -1,461 +0,0 @@
|
||||||
tool
|
|
||||||
extends Button
|
|
||||||
|
|
||||||
signal mesh_generated(mesh_inst)
|
|
||||||
|
|
||||||
const Label3D = preload("label_3d.gd")
|
|
||||||
|
|
||||||
var label3d : Label3D
|
|
||||||
|
|
||||||
var image_cache = PoolRealArray()
|
|
||||||
|
|
||||||
# These variables are used to spread the marching_square function
|
|
||||||
# across multiple frames.
|
|
||||||
var finished_marching = false
|
|
||||||
var os_time
|
|
||||||
|
|
||||||
func _on_Button_pressed():
|
|
||||||
generate_geometry()
|
|
||||||
|
|
||||||
func generate_geometry():
|
|
||||||
$PopupDialog.popup_centered()
|
|
||||||
var text_scale = label3d.text_scale
|
|
||||||
var extrude = label3d.extrude
|
|
||||||
var viewport = label3d.get_node("Viewport")
|
|
||||||
|
|
||||||
viewport.render_target_update_mode = Viewport.UPDATE_ALWAYS
|
|
||||||
yield(get_tree(), "idle_frame")
|
|
||||||
yield(get_tree(), "idle_frame")
|
|
||||||
viewport.render_target_update_mode = Viewport.UPDATE_DISABLED
|
|
||||||
|
|
||||||
var image = viewport.get_texture().get_data()
|
|
||||||
image.lock()
|
|
||||||
|
|
||||||
var edges = Dictionary()
|
|
||||||
finished_marching = false
|
|
||||||
os_time = OS.get_ticks_msec()
|
|
||||||
do_marching_squares(image, edges)
|
|
||||||
while not finished_marching:
|
|
||||||
yield(get_tree(), "idle_frame")
|
|
||||||
|
|
||||||
# Contours are the edges and holes of the text.
|
|
||||||
# The paths are said edges combined with the holes for easier triangulation.
|
|
||||||
var contours = []
|
|
||||||
collect_contours(edges.duplicate(), contours)
|
|
||||||
var paths = contours.duplicate(true)
|
|
||||||
decimate_holes(edges, paths, Rect2(0, 0, image.get_width(), image.get_height()))
|
|
||||||
|
|
||||||
var triangle_data = []
|
|
||||||
var vertex_data = []
|
|
||||||
for path in paths:
|
|
||||||
path.points = douglas_peucker(path.points, 0.125)
|
|
||||||
# Edge data beyond this point will no longer be valid
|
|
||||||
|
|
||||||
var triangles = []
|
|
||||||
ear_clipping(path, triangles)
|
|
||||||
|
|
||||||
# points are converted into vector3 here.
|
|
||||||
for p in path.points.size():
|
|
||||||
var point = path.points[p]
|
|
||||||
point -= Vector2(image.get_width(), image.get_height()) / 2.0
|
|
||||||
point *= text_scale * 2.0
|
|
||||||
path.points[p] = Vector3(point.x, point.y, extrude)
|
|
||||||
|
|
||||||
ArrayUtils.call_per_element(triangles, "offset_indices", vertex_data.size())
|
|
||||||
|
|
||||||
ArrayUtils.append_array(vertex_data, path.points)
|
|
||||||
ArrayUtils.append_array(triangle_data, triangles)
|
|
||||||
|
|
||||||
if extrude != 0:
|
|
||||||
# Generate the back triangles
|
|
||||||
var original_vert_size = vertex_data.size()
|
|
||||||
for v in original_vert_size:
|
|
||||||
var vertex = vertex_data[v]
|
|
||||||
vertex_data.append(vertex * Vector3(1, 1, -1))
|
|
||||||
|
|
||||||
var tri_size = triangle_data.size()
|
|
||||||
for t in tri_size:
|
|
||||||
var triangle = triangle_data[t].duplicate()
|
|
||||||
triangle.offset_indices(original_vert_size)
|
|
||||||
triangle.reverse_order()
|
|
||||||
triangle_data.append(triangle)
|
|
||||||
|
|
||||||
# And now the triangles inbetween
|
|
||||||
for path in paths:
|
|
||||||
var vertices = path.points.duplicate()
|
|
||||||
var points_size = path.points.size()
|
|
||||||
for vert in points_size:
|
|
||||||
var back_vertex = path.points[vert] * Vector3(1, 1, -1)
|
|
||||||
vertices.append(back_vertex)
|
|
||||||
|
|
||||||
var triangles = []
|
|
||||||
for i in points_size:
|
|
||||||
var index = i + vertex_data.size()
|
|
||||||
var a = index
|
|
||||||
var b = (index + 1) if i != points_size - 1 else vertex_data.size()
|
|
||||||
var c = index + points_size
|
|
||||||
var d = ((index + 1) if i != points_size - 1 else vertex_data.size()) + points_size
|
|
||||||
|
|
||||||
triangles.append(Triangle.new(c, b, a))
|
|
||||||
triangles.append(Triangle.new(d, b, c))
|
|
||||||
|
|
||||||
ArrayUtils.append_array(vertex_data, vertices)
|
|
||||||
ArrayUtils.append_array(triangle_data, triangles)
|
|
||||||
|
|
||||||
var geom = SurfaceTool.new()
|
|
||||||
geom.clear()
|
|
||||||
|
|
||||||
geom.begin(Mesh.PRIMITIVE_TRIANGLES)
|
|
||||||
for vert in vertex_data:
|
|
||||||
geom.add_vertex(vert)
|
|
||||||
for tri in triangle_data:
|
|
||||||
geom.add_index(tri.a)
|
|
||||||
geom.add_index(tri.b)
|
|
||||||
geom.add_index(tri.c)
|
|
||||||
geom.generate_normals()
|
|
||||||
|
|
||||||
var material = SpatialMaterial.new()
|
|
||||||
material.albedo_color = label3d.color
|
|
||||||
material.metallic = label3d.metallic
|
|
||||||
material.roughness = label3d.roughness
|
|
||||||
|
|
||||||
var mesh_inst = MeshInstance.new()
|
|
||||||
mesh_inst.mesh = geom.commit()
|
|
||||||
mesh_inst.material_override = material
|
|
||||||
mesh_inst.transform = label3d.transform
|
|
||||||
mesh_inst.name = label3d.name + "-mesh"
|
|
||||||
|
|
||||||
emit_signal("mesh_generated", mesh_inst)
|
|
||||||
|
|
||||||
image_cache.resize(0)
|
|
||||||
image.unlock()
|
|
||||||
$PopupDialog.hide()
|
|
||||||
|
|
||||||
|
|
||||||
func do_marching_squares(image, edges):
|
|
||||||
for y in image.get_height() - 1:
|
|
||||||
for x in image.get_width() - 1:
|
|
||||||
var i = Vector2(x, y)
|
|
||||||
|
|
||||||
var p_ul = get_pixel(image, x, y)
|
|
||||||
var p_ll = get_pixel(image, x, y+1)
|
|
||||||
var p_ur = get_pixel(image, x+1, y)
|
|
||||||
var p_lr = get_pixel(image, x+1, y+1)
|
|
||||||
|
|
||||||
var top = inverse_lerp(p_ul, p_ur, 1)
|
|
||||||
var bottom = inverse_lerp(p_ll, p_lr, 1)
|
|
||||||
var left = inverse_lerp(p_ul, p_ll, 1)
|
|
||||||
var right = inverse_lerp(p_ur, p_lr, 1)
|
|
||||||
|
|
||||||
var ul = int(p_ul > 1) * 1
|
|
||||||
var ll = int(p_ll > 1) * 2
|
|
||||||
var ur = int(p_ur > 1) * 4
|
|
||||||
var lr = int(p_lr > 1) * 8
|
|
||||||
|
|
||||||
var bit = ul | ll | ur | lr
|
|
||||||
|
|
||||||
# Notice: cases 6 and 9 have not been implemented.
|
|
||||||
match bit:
|
|
||||||
# Corner Cases
|
|
||||||
1:
|
|
||||||
create_edge(edges, i, x, y + left, x + top, y, Vector2.UP)
|
|
||||||
2:
|
|
||||||
create_edge(edges, i, x + bottom, y + 1, x, y + left, Vector2.LEFT)
|
|
||||||
4:
|
|
||||||
create_edge(edges, i, x + top, y, x + 1, y + right, Vector2.RIGHT)
|
|
||||||
8:
|
|
||||||
create_edge(edges, i, x + 1, y + right, x + bottom, y + 1, Vector2.DOWN)
|
|
||||||
|
|
||||||
# Edge Cases
|
|
||||||
3:
|
|
||||||
create_edge(edges, i, x + bottom, y + 1, x + top, y, Vector2.UP)
|
|
||||||
5:
|
|
||||||
create_edge(edges, i, x, y + left, x + 1, y + right, Vector2.RIGHT)
|
|
||||||
10:
|
|
||||||
create_edge(edges, i, x + 1, y + right, x, y + left, Vector2.LEFT)
|
|
||||||
12:
|
|
||||||
create_edge(edges, i, x + top, y, x + bottom, y + 1, Vector2.DOWN)
|
|
||||||
|
|
||||||
# Inner Corner cases
|
|
||||||
14:
|
|
||||||
create_edge(edges, i, x + top, y, x, y + left, Vector2.LEFT)
|
|
||||||
13:
|
|
||||||
create_edge(edges, i, x, y + left, x + bottom, y + 1, Vector2.DOWN)
|
|
||||||
11:
|
|
||||||
create_edge(edges, i, x + 1, y + right, x + top, y, Vector2.UP)
|
|
||||||
7:
|
|
||||||
create_edge(edges, i, x + bottom, y + 1, x + 1, y + right, Vector2.RIGHT)
|
|
||||||
|
|
||||||
if OS.get_ticks_msec() - os_time > 20:
|
|
||||||
var max_i = (image.get_width() - 1) * (image.get_height() - 1)
|
|
||||||
var curr_i = x + (y * image.get_width() - 1)
|
|
||||||
$PopupDialog/VBoxContainer/ProgressBar.value = float(curr_i) / max_i * 100
|
|
||||||
|
|
||||||
yield(get_tree(), "idle_frame")
|
|
||||||
os_time = OS.get_ticks_msec()
|
|
||||||
|
|
||||||
finished_marching = true
|
|
||||||
|
|
||||||
func collect_contours(edges, contours):
|
|
||||||
|
|
||||||
var directions = [Vector2.UP, Vector2.DOWN, Vector2.LEFT, Vector2.RIGHT]
|
|
||||||
var coord = edges.keys()[0]
|
|
||||||
|
|
||||||
var start_edge = edges[coord]
|
|
||||||
var contour = Contour.new(start_edge.direction == Vector2.UP || \
|
|
||||||
start_edge.direction == Vector2.RIGHT)
|
|
||||||
contours.append(contour)
|
|
||||||
|
|
||||||
contour.points.append(edges[coord].end)
|
|
||||||
contour.edges.append(edges[coord])
|
|
||||||
var edge = edges[coord]
|
|
||||||
|
|
||||||
edges.erase(coord)
|
|
||||||
|
|
||||||
var loop_started = true
|
|
||||||
while loop_started or edge != start_edge:
|
|
||||||
var edge_found = false
|
|
||||||
|
|
||||||
for dir in directions:
|
|
||||||
if edges.has(coord + dir) and edges[coord + dir].begin == edge.end:
|
|
||||||
edge_found = true
|
|
||||||
|
|
||||||
coord += dir
|
|
||||||
contour.points.append(edges[coord].end)
|
|
||||||
contour.edges.append(edges[coord])
|
|
||||||
edge = edges[coord]
|
|
||||||
edges.erase(coord)
|
|
||||||
|
|
||||||
break
|
|
||||||
|
|
||||||
if not edge_found:
|
|
||||||
break
|
|
||||||
|
|
||||||
loop_started = false
|
|
||||||
|
|
||||||
if not edges.empty():
|
|
||||||
collect_contours(edges, contours)
|
|
||||||
|
|
||||||
func decimate_holes(edges, contours, bounds):
|
|
||||||
for c in range(contours.size()-1, -1, -1):
|
|
||||||
var contour = contours[c]
|
|
||||||
if contour.is_hole:
|
|
||||||
for i in contour.edges.size():
|
|
||||||
var edge = contour.edges[i]
|
|
||||||
var edge_found = false
|
|
||||||
|
|
||||||
var dir = edge.direction
|
|
||||||
dir = Vector2(dir.y, -dir.x)
|
|
||||||
var pos = ((edge.begin + edge.end) / 2.0).floor()
|
|
||||||
var other_edge
|
|
||||||
|
|
||||||
while not other_edge and bounds.has_point(pos):
|
|
||||||
pos += dir
|
|
||||||
if edges.has(pos):
|
|
||||||
other_edge = edges[pos]
|
|
||||||
|
|
||||||
if other_edge:
|
|
||||||
|
|
||||||
for other_contour in contours:
|
|
||||||
if other_contour == contour:
|
|
||||||
continue
|
|
||||||
|
|
||||||
for j in other_contour.edges.size():
|
|
||||||
var other_point = other_contour.edges[j]
|
|
||||||
if other_edge == other_point:
|
|
||||||
edge_found = true
|
|
||||||
other_contour.fuse_with(contour, j, i + 1)
|
|
||||||
break
|
|
||||||
|
|
||||||
if edge_found:
|
|
||||||
break
|
|
||||||
|
|
||||||
if edge_found:
|
|
||||||
break
|
|
||||||
|
|
||||||
contours.remove(c)
|
|
||||||
|
|
||||||
func douglas_peucker(points, tolerance):
|
|
||||||
var farthest = farthest_point(points)
|
|
||||||
|
|
||||||
|
|
||||||
# Farthest point not existing must mean the points only made of two,
|
|
||||||
# and cannot be simplified any further.
|
|
||||||
if not farthest:
|
|
||||||
return points
|
|
||||||
|
|
||||||
if farthest.distance < tolerance:
|
|
||||||
return [points[0], points[-1]]
|
|
||||||
else:
|
|
||||||
var left = []
|
|
||||||
var right = []
|
|
||||||
ArrayUtils.split_array(points, farthest.index, left, right)
|
|
||||||
|
|
||||||
left = douglas_peucker(left, tolerance)
|
|
||||||
right = douglas_peucker(right, tolerance)
|
|
||||||
|
|
||||||
ArrayUtils.append_array(left, right)
|
|
||||||
return left
|
|
||||||
|
|
||||||
func ear_clipping(contour, triangles):
|
|
||||||
var points = ArrayUtils.to_dictionary(contour.points)
|
|
||||||
|
|
||||||
var i = 0
|
|
||||||
var counter = 0
|
|
||||||
while points.size() > 3:
|
|
||||||
counter += 1
|
|
||||||
if(counter > 4000):
|
|
||||||
printerr("Hmmm... Infinite loop much?")
|
|
||||||
break
|
|
||||||
|
|
||||||
var keys = points.keys()
|
|
||||||
var point_a = points[keys[i-1]]
|
|
||||||
var point_b = points[keys[i]]
|
|
||||||
var point_c = points[keys[(i+1) % keys.size()]]
|
|
||||||
|
|
||||||
if (point_b - point_a).cross(point_c - point_b) < 0:
|
|
||||||
var has_point = false
|
|
||||||
for p in points:
|
|
||||||
var point = points[p]
|
|
||||||
if point == point_a or point == point_b or point == point_c:
|
|
||||||
continue
|
|
||||||
if point_inside_triangle(point, point_a, point_b, point_c):
|
|
||||||
has_point = true
|
|
||||||
break
|
|
||||||
|
|
||||||
if not has_point:
|
|
||||||
var tri = Triangle.new(keys[i-1], keys[i], keys[(i+1) % keys.size()])
|
|
||||||
triangles.append(tri)
|
|
||||||
points.erase(keys[i])
|
|
||||||
|
|
||||||
i = wrapi(i + 1, 0, points.size())
|
|
||||||
|
|
||||||
var keys = points.keys()
|
|
||||||
triangles.append(Triangle.new(keys[0], keys[1], keys[2]))
|
|
||||||
|
|
||||||
# This returns a dictionary containing the farthest point,
|
|
||||||
# the distance associated with it, and its index in the array.
|
|
||||||
func farthest_point(points):
|
|
||||||
var first = points[0]
|
|
||||||
var last = points[-1]
|
|
||||||
|
|
||||||
if points.size() < 3:
|
|
||||||
return
|
|
||||||
|
|
||||||
var farthest
|
|
||||||
var max_dist = -1
|
|
||||||
var index
|
|
||||||
for i in range(1, points.size() - 1):
|
|
||||||
var distance = distance_to_segment(points[i], first, last)
|
|
||||||
if distance > max_dist:
|
|
||||||
farthest = points[i]
|
|
||||||
max_dist = distance
|
|
||||||
index = i
|
|
||||||
|
|
||||||
return {"point": farthest, "distance": max_dist, "index": index}
|
|
||||||
|
|
||||||
func distance_to_segment(point, a, b):
|
|
||||||
# This is because I don't know how to snap a point onto a line,
|
|
||||||
# so I'm relying on Plane in the meantime.
|
|
||||||
var plane = Plane(Vector3(a.x, a.y, 0),
|
|
||||||
Vector3(b.x, b.y, 0), Vector3(a.x, a.y, 1))
|
|
||||||
|
|
||||||
var projected = plane.project(Vector3(point.x, point.y, 0))
|
|
||||||
var t = inverse_lerp(a.x, b.x, projected.x) if a.x != b.x else \
|
|
||||||
inverse_lerp(a.y, b.y, projected.y)
|
|
||||||
|
|
||||||
var snapped = a.linear_interpolate(b, t)
|
|
||||||
return point.distance_squared_to(snapped)
|
|
||||||
|
|
||||||
func vec_sign(p1, p2, p3):
|
|
||||||
return (p1.x - p3.x) * (p2.y - p3.y) - (p2.x - p3.x) * (p1.y - p3.y)
|
|
||||||
|
|
||||||
func point_inside_triangle(point, a, b, c):
|
|
||||||
var d1 = vec_sign(point, a, b)
|
|
||||||
var d2 = vec_sign(point, b, c)
|
|
||||||
var d3 = vec_sign(point, c, a)
|
|
||||||
|
|
||||||
var has_neg = (d1 < 0) or (d2 < 0) or (d3 < 0)
|
|
||||||
var has_pos = (d1 > 0) or (d2 > 0) or (d3 > 0)
|
|
||||||
return not (has_neg and has_pos)
|
|
||||||
|
|
||||||
func create_edge(edges, offset, p1x, p1y, p2x, p2y, dir):
|
|
||||||
edges[offset] = MSEdge.new(Vector2(p1x, p1y), Vector2(p2x, p2y), dir)
|
|
||||||
|
|
||||||
func get_pixel(image : Image, x : int, y : int):
|
|
||||||
if x < 1 || y < 1 || x > image.get_width()-1 || y > image.get_height()-1:
|
|
||||||
return 0
|
|
||||||
|
|
||||||
var i = x + y * image.get_width()
|
|
||||||
if image_cache.size() > i and image_cache[i] != null:
|
|
||||||
return image_cache[i]
|
|
||||||
else:
|
|
||||||
var real = image.get_pixel(x, y).r;
|
|
||||||
if image_cache.size() <= i:
|
|
||||||
image_cache.resize(i+1)
|
|
||||||
image_cache[i] = real
|
|
||||||
return real
|
|
||||||
|
|
||||||
|
|
||||||
class MSEdge:
|
|
||||||
var begin : Vector2
|
|
||||||
var end : Vector2
|
|
||||||
|
|
||||||
var coordinate : Vector2
|
|
||||||
|
|
||||||
# One of the four cardinal directions
|
|
||||||
var direction : Vector2
|
|
||||||
|
|
||||||
func _init(begin, end, direction):
|
|
||||||
self.begin = begin
|
|
||||||
self.end = end
|
|
||||||
self.direction = direction
|
|
||||||
|
|
||||||
|
|
||||||
class Contour:
|
|
||||||
var points := []
|
|
||||||
var edges := []
|
|
||||||
var is_hole : bool
|
|
||||||
|
|
||||||
func _init(is_hole):
|
|
||||||
self.is_hole = is_hole
|
|
||||||
|
|
||||||
func fuse_with(contour, self_point, other_point):
|
|
||||||
var points_behind = []
|
|
||||||
var points_after = []
|
|
||||||
|
|
||||||
ArrayUtils.split_array(points, self_point + 1, points_behind, points_after)
|
|
||||||
|
|
||||||
var shifted_contour = contour.points.duplicate()
|
|
||||||
ArrayUtils.shift_array(shifted_contour, other_point)
|
|
||||||
|
|
||||||
ArrayUtils.append_array(points_behind, shifted_contour)
|
|
||||||
points_behind.append(shifted_contour[0])
|
|
||||||
points_behind.append(points[self_point])
|
|
||||||
ArrayUtils.append_array(points_behind, points_after)
|
|
||||||
|
|
||||||
points = points_behind
|
|
||||||
|
|
||||||
|
|
||||||
class Triangle:
|
|
||||||
var a : int
|
|
||||||
var b : int
|
|
||||||
var c : int
|
|
||||||
|
|
||||||
func _init(a, b, c):
|
|
||||||
self.a = a
|
|
||||||
self.b = b
|
|
||||||
self.c = c
|
|
||||||
|
|
||||||
func offset_indices(offset):
|
|
||||||
a += offset
|
|
||||||
b += offset
|
|
||||||
c += offset
|
|
||||||
|
|
||||||
func reverse_order():
|
|
||||||
var temp = a
|
|
||||||
a = b
|
|
||||||
b = temp
|
|
||||||
|
|
||||||
func duplicate():
|
|
||||||
return Triangle.new(a, b, c)
|
|
|
@ -1,40 +0,0 @@
|
||||||
[gd_scene load_steps=2 format=2]
|
|
||||||
|
|
||||||
[ext_resource path="res://addons/SIsilicon.3d.text/label_3d_converter.gd" type="Script" id=1]
|
|
||||||
|
|
||||||
[node name="Button" type="Button"]
|
|
||||||
margin_right = 172.0
|
|
||||||
margin_bottom = 20.0
|
|
||||||
text = "Convert to MeshInstance"
|
|
||||||
flat = true
|
|
||||||
script = ExtResource( 1 )
|
|
||||||
|
|
||||||
[node name="PopupDialog" type="PopupDialog" parent="."]
|
|
||||||
visible = true
|
|
||||||
margin_left = 340.0
|
|
||||||
margin_top = 200.0
|
|
||||||
margin_right = 610.0
|
|
||||||
margin_bottom = 268.0
|
|
||||||
mouse_default_cursor_shape = 5
|
|
||||||
popup_exclusive = true
|
|
||||||
|
|
||||||
[node name="VBoxContainer" type="VBoxContainer" parent="PopupDialog"]
|
|
||||||
anchor_right = 1.0
|
|
||||||
anchor_bottom = 1.0
|
|
||||||
margin_left = 6.0
|
|
||||||
margin_top = 6.0
|
|
||||||
margin_right = -6.0
|
|
||||||
margin_bottom = -6.0
|
|
||||||
|
|
||||||
[node name="Label" type="Label" parent="PopupDialog/VBoxContainer"]
|
|
||||||
margin_right = 258.0
|
|
||||||
margin_bottom = 14.0
|
|
||||||
text = "Generating geometry"
|
|
||||||
align = 1
|
|
||||||
|
|
||||||
[node name="ProgressBar" type="ProgressBar" parent="PopupDialog/VBoxContainer"]
|
|
||||||
margin_top = 18.0
|
|
||||||
margin_right = 258.0
|
|
||||||
margin_bottom = 32.0
|
|
||||||
step = 1.0
|
|
||||||
[connection signal="pressed" from="." to="." method="_on_Button_pressed"]
|
|
|
@ -1,7 +0,0 @@
|
||||||
[plugin]
|
|
||||||
|
|
||||||
name="3D Text"
|
|
||||||
description="This plugin allows you to make 3D text within the Godot engine."
|
|
||||||
author="SIsilicon"
|
|
||||||
version="0.6.1"
|
|
||||||
script="3d_text_plugin.gd"
|
|
|
@ -1,74 +0,0 @@
|
||||||
[gd_scene load_steps=7 format=2]
|
|
||||||
|
|
||||||
[ext_resource path="res://addons/SIsilicon.3d.text/default_font.ttf" type="DynamicFontData" id=1]
|
|
||||||
|
|
||||||
[sub_resource type="Environment" id=1]
|
|
||||||
background_mode = 1
|
|
||||||
background_energy = 0.0
|
|
||||||
|
|
||||||
[sub_resource type="World" id=2]
|
|
||||||
environment = SubResource( 1 )
|
|
||||||
|
|
||||||
[sub_resource type="DynamicFont" id=3]
|
|
||||||
size = 100
|
|
||||||
font_data = ExtResource( 1 )
|
|
||||||
|
|
||||||
[sub_resource type="Shader" id=4]
|
|
||||||
code = "shader_type canvas_item;
|
|
||||||
|
|
||||||
uniform int Max = 3;
|
|
||||||
|
|
||||||
float getAlpha(sampler2D tex, ivec2 coord) {
|
|
||||||
return texelFetch(tex, coord, 0).r;
|
|
||||||
}
|
|
||||||
|
|
||||||
void fragment() {
|
|
||||||
ivec2 coord = ivec2(FRAGCOORD.xy);
|
|
||||||
bool inside = getAlpha(SCREEN_TEXTURE, coord) > 0.5;
|
|
||||||
|
|
||||||
float dist = float((Max+1) * (Max+1));
|
|
||||||
for(int y = -Max; y <= Max; y++) {
|
|
||||||
for(int x = -Max; x <= Max; x++) {
|
|
||||||
if(x == 0 && y == 0) continue;
|
|
||||||
ivec2 delta = ivec2(x,y);
|
|
||||||
|
|
||||||
if(inside) {
|
|
||||||
if(getAlpha(SCREEN_TEXTURE, coord + delta) < 0.5) {
|
|
||||||
dist = min(dist, float(x*x + y*y));
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if(getAlpha(SCREEN_TEXTURE, coord + delta) > 0.5) {
|
|
||||||
dist = min(dist, float(x*x + y*y));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
dist = sqrt(dist) * (float(!inside) * 2.0 - 1.0);
|
|
||||||
|
|
||||||
COLOR = vec4(dist / float(Max+1));
|
|
||||||
}"
|
|
||||||
|
|
||||||
[sub_resource type="ShaderMaterial" id=5]
|
|
||||||
shader = SubResource( 4 )
|
|
||||||
shader_param/Max = 10
|
|
||||||
|
|
||||||
[node name="Viewport" type="Viewport"]
|
|
||||||
size = Vector2( 190, 114 )
|
|
||||||
own_world = true
|
|
||||||
world = SubResource( 2 )
|
|
||||||
transparent_bg = true
|
|
||||||
handle_input_locally = false
|
|
||||||
render_target_update_mode = 1
|
|
||||||
gui_disable_input = true
|
|
||||||
|
|
||||||
[node name="Label" type="Label" parent="."]
|
|
||||||
margin_right = 190.0
|
|
||||||
margin_bottom = 114.0
|
|
||||||
size_flags_horizontal = 4
|
|
||||||
custom_fonts/font = SubResource( 3 )
|
|
||||||
text = "Text"
|
|
||||||
|
|
||||||
[node name="ColorRect" type="ColorRect" parent="Label"]
|
|
||||||
material = SubResource( 5 )
|
|
||||||
anchor_right = 1.0
|
|
||||||
anchor_bottom = 1.0
|
|
|
@ -45,7 +45,13 @@ func import(source_file, save_path, options, r_platform_variant, r_gen_files):
|
||||||
asciicast.add_track(Animation.TYPE_METHOD, 0)
|
asciicast.add_track(Animation.TYPE_METHOD, 0)
|
||||||
asciicast.track_set_path(0, ".")
|
asciicast.track_set_path(0, ".")
|
||||||
|
|
||||||
var time: float
|
var frame = {
|
||||||
|
"time": 0.0,
|
||||||
|
"data": {
|
||||||
|
"method": "write",
|
||||||
|
"args": [PoolByteArray()]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
while not file.eof_reached():
|
while not file.eof_reached():
|
||||||
var line = file.get_line()
|
var line = file.get_line()
|
||||||
|
@ -56,14 +62,25 @@ func import(source_file, save_path, options, r_platform_variant, r_gen_files):
|
||||||
if typeof(p.result) != TYPE_ARRAY:
|
if typeof(p.result) != TYPE_ARRAY:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
time = p.result[0]
|
|
||||||
var event_type: String = p.result[1]
|
var event_type: String = p.result[1]
|
||||||
var event_data: PoolByteArray = p.result[2].to_utf8()
|
var event_data: PoolByteArray = p.result[2].to_utf8()
|
||||||
|
|
||||||
if event_type == "o":
|
# Asciicast recordings have a resolution of 0.000001, however animation
|
||||||
asciicast.track_insert_key(0, time, {"method": "write",
|
# track keys only have a resolution of 0.01, therefore we must combine
|
||||||
"args": [event_data]})
|
# events that would occur in the same keyframe, otherwise only the last
|
||||||
|
# event is inserted and the previous events are overwritten.
|
||||||
|
var time = stepify(p.result[0], 0.01)
|
||||||
|
|
||||||
asciicast.length = time
|
if event_type == "o":
|
||||||
|
if time == frame.time:
|
||||||
|
asciicast.track_remove_key_at_position(0, time)
|
||||||
|
frame.data.args[0] = frame.data.args[0] + event_data
|
||||||
|
else:
|
||||||
|
frame.time = time
|
||||||
|
frame.data.args = [event_data]
|
||||||
|
|
||||||
|
asciicast.track_insert_key(0, frame.time, frame.data)
|
||||||
|
|
||||||
|
asciicast.length = frame.time
|
||||||
|
|
||||||
return ResourceSaver.save("%s.%s" % [save_path, get_save_extension()], asciicast)
|
return ResourceSaver.save("%s.%s" % [save_path, get_save_extension()], asciicast)
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
#include "pseudoterminal.h"
|
#include "pseudoterminal.h"
|
||||||
#include <pty.h>
|
#include <pty.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
#include <sys/wait.h>
|
||||||
#include <termios.h>
|
#include <termios.h>
|
||||||
|
|
||||||
using namespace godot;
|
using namespace godot;
|
||||||
|
@ -11,9 +12,11 @@ void Pseudoterminal::_register_methods()
|
||||||
register_method("_init", &Pseudoterminal::_init);
|
register_method("_init", &Pseudoterminal::_init);
|
||||||
register_method("_ready", &Pseudoterminal::_ready);
|
register_method("_ready", &Pseudoterminal::_ready);
|
||||||
|
|
||||||
register_method("put_data", &Pseudoterminal::put_data);
|
register_method("write", &Pseudoterminal::write);
|
||||||
|
register_method("resize", &Pseudoterminal::resize);
|
||||||
|
|
||||||
register_signal<Pseudoterminal>((char *)"data_received", "data", GODOT_VARIANT_TYPE_POOL_BYTE_ARRAY);
|
register_signal<Pseudoterminal>((char *)"data_sent", "data", GODOT_VARIANT_TYPE_POOL_BYTE_ARRAY);
|
||||||
|
register_signal<Pseudoterminal>((char *)"exited", "status", GODOT_VARIANT_TYPE_INT);
|
||||||
}
|
}
|
||||||
|
|
||||||
Pseudoterminal::Pseudoterminal()
|
Pseudoterminal::Pseudoterminal()
|
||||||
|
@ -22,18 +25,20 @@ Pseudoterminal::Pseudoterminal()
|
||||||
|
|
||||||
Pseudoterminal::~Pseudoterminal()
|
Pseudoterminal::~Pseudoterminal()
|
||||||
{
|
{
|
||||||
|
pty_thread.join();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Pseudoterminal::_init()
|
void Pseudoterminal::_init()
|
||||||
{
|
{
|
||||||
pty_thread = std::thread(&Pseudoterminal::process_pty, this);
|
|
||||||
bytes_to_write = 0;
|
bytes_to_write = 0;
|
||||||
|
pty_thread = std::thread(&Pseudoterminal::process_pty, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Pseudoterminal::process_pty()
|
void Pseudoterminal::process_pty()
|
||||||
{
|
{
|
||||||
int fd;
|
int fd;
|
||||||
char *name;
|
char *name;
|
||||||
|
int status;
|
||||||
|
|
||||||
should_process_pty = true;
|
should_process_pty = true;
|
||||||
|
|
||||||
|
@ -68,9 +73,30 @@ void Pseudoterminal::process_pty()
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
Vector2 zero = Vector2(0, 0);
|
||||||
|
|
||||||
/* Parent */
|
/* Parent */
|
||||||
while (1)
|
while (1)
|
||||||
{
|
{
|
||||||
|
{
|
||||||
|
std::lock_guard<std::mutex> guard(size_mutex);
|
||||||
|
if (size != zero)
|
||||||
|
{
|
||||||
|
struct winsize ws;
|
||||||
|
memset(&ws, 0, sizeof(ws));
|
||||||
|
ws.ws_col = size.x;
|
||||||
|
ws.ws_row = size.y;
|
||||||
|
|
||||||
|
ioctl(fd, TIOCSWINSZ, &ws);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (waitpid(pty_pid, &status, WNOHANG))
|
||||||
|
{
|
||||||
|
emit_signal("exited", status);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
int ready = -1;
|
int ready = -1;
|
||||||
fd_set read_fds;
|
fd_set read_fds;
|
||||||
fd_set write_fds;
|
fd_set write_fds;
|
||||||
|
@ -93,10 +119,7 @@ void Pseudoterminal::process_pty()
|
||||||
|
|
||||||
if (bytes_to_write > 0)
|
if (bytes_to_write > 0)
|
||||||
{
|
{
|
||||||
write(fd, write_buffer, bytes_to_write);
|
::write(fd, write_buffer, bytes_to_write);
|
||||||
|
|
||||||
Godot::print(String("wrote {0} bytes").format(Array::make(bytes_to_write)));
|
|
||||||
|
|
||||||
bytes_to_write = 0;
|
bytes_to_write = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -114,30 +137,11 @@ void Pseudoterminal::process_pty()
|
||||||
if (bytes_read <= 0)
|
if (bytes_read <= 0)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
//while (1)
|
|
||||||
//{
|
|
||||||
// ret = read(fd, read_buffer, 1);
|
|
||||||
|
|
||||||
// if (ret == -1 || ret == 0)
|
|
||||||
// {
|
|
||||||
// break;
|
|
||||||
// }
|
|
||||||
// else
|
|
||||||
// {
|
|
||||||
// bytes_read += ret;
|
|
||||||
// }
|
|
||||||
//}
|
|
||||||
|
|
||||||
PoolByteArray data = PoolByteArray();
|
PoolByteArray data = PoolByteArray();
|
||||||
data.resize(bytes_read);
|
data.resize(bytes_read);
|
||||||
memcpy(data.write().ptr(), read_buffer, bytes_read);
|
memcpy(data.write().ptr(), read_buffer, bytes_read);
|
||||||
|
|
||||||
emit_signal("data_received", PoolByteArray(data));
|
emit_signal("data_sent", PoolByteArray(data));
|
||||||
|
|
||||||
if (bytes_read > 0)
|
|
||||||
{
|
|
||||||
//Godot::print(String("read {0} bytes").format(Array::make(bytes_read)));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -148,9 +152,15 @@ void Pseudoterminal::_ready()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void Pseudoterminal::put_data(PoolByteArray data)
|
void Pseudoterminal::write(PoolByteArray data)
|
||||||
{
|
{
|
||||||
std::lock_guard<std::mutex> guard(write_buffer_mutex);
|
std::lock_guard<std::mutex> guard(write_buffer_mutex);
|
||||||
bytes_to_write = data.size();
|
bytes_to_write = data.size();
|
||||||
memcpy(write_buffer, data.read().ptr(), bytes_to_write);
|
memcpy(write_buffer, data.read().ptr(), bytes_to_write);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Pseudoterminal::resize(Vector2 new_size)
|
||||||
|
{
|
||||||
|
std::lock_guard<std::mutex> guard(size_mutex);
|
||||||
|
size = new_size;
|
||||||
|
}
|
|
@ -29,6 +29,9 @@ namespace godot
|
||||||
int bytes_to_read;
|
int bytes_to_read;
|
||||||
std::mutex read_buffer_mutex;
|
std::mutex read_buffer_mutex;
|
||||||
|
|
||||||
|
Vector2 size;
|
||||||
|
std::mutex size_mutex;
|
||||||
|
|
||||||
void process_pty();
|
void process_pty();
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
@ -40,7 +43,8 @@ namespace godot
|
||||||
void _init();
|
void _init();
|
||||||
void _ready();
|
void _ready();
|
||||||
|
|
||||||
void put_data(PoolByteArray data);
|
void write(PoolByteArray data);
|
||||||
|
void resize(Vector2 size);
|
||||||
};
|
};
|
||||||
} // namespace godot
|
} // namespace godot
|
||||||
|
|
||||||
|
|
|
@ -215,7 +215,17 @@ static void write_cb(struct tsm_vte *vte, const char *u8, size_t len, void *data
|
||||||
for (int i = 0; i < len; i++)
|
for (int i = 0; i < len; i++)
|
||||||
bytes.append(u8[i]);
|
bytes.append(u8[i]);
|
||||||
|
|
||||||
term->emit_signal("data_read", bytes);
|
if (len > 0)
|
||||||
|
{
|
||||||
|
if (term->input_event_key.is_valid())
|
||||||
|
{
|
||||||
|
// The callback was fired from a key press event so emit the "key_pressed" signal.
|
||||||
|
term->emit_signal("key_pressed", String(u8), term->input_event_key);
|
||||||
|
term->input_event_key.unref();
|
||||||
|
}
|
||||||
|
|
||||||
|
term->emit_signal("data_sent", bytes);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static int text_draw_cb(struct tsm_screen *con,
|
static int text_draw_cb(struct tsm_screen *con,
|
||||||
|
@ -258,7 +268,6 @@ static int text_draw_cb(struct tsm_screen *con,
|
||||||
|
|
||||||
void Terminal::_register_methods()
|
void Terminal::_register_methods()
|
||||||
{
|
{
|
||||||
|
|
||||||
register_method("_init", &Terminal::_init);
|
register_method("_init", &Terminal::_init);
|
||||||
register_method("_ready", &Terminal::_ready);
|
register_method("_ready", &Terminal::_ready);
|
||||||
register_method("_gui_input", &Terminal::_gui_input);
|
register_method("_gui_input", &Terminal::_gui_input);
|
||||||
|
@ -267,10 +276,12 @@ void Terminal::_register_methods()
|
||||||
register_method("write", &Terminal::write);
|
register_method("write", &Terminal::write);
|
||||||
register_method("update_size", &Terminal::update_size);
|
register_method("update_size", &Terminal::update_size);
|
||||||
|
|
||||||
//register_property<Terminal, int>("rows", &Terminal::rows, 24);
|
register_property<Terminal, int>("rows", &Terminal::rows, 24);
|
||||||
//register_property<Terminal, int>("cols", &Terminal::cols, 80);
|
register_property<Terminal, int>("cols", &Terminal::cols, 80);
|
||||||
|
|
||||||
register_signal<Terminal>("data_read", "data", GODOT_VARIANT_TYPE_POOL_BYTE_ARRAY);
|
register_signal<Terminal>("data_sent", "data", GODOT_VARIANT_TYPE_POOL_BYTE_ARRAY);
|
||||||
|
register_signal<Terminal>("key_pressed", "data", GODOT_VARIANT_TYPE_STRING, "event", GODOT_VARIANT_TYPE_OBJECT);
|
||||||
|
register_signal<Terminal>("size_changed", "new_size", GODOT_VARIANT_TYPE_VECTOR2);
|
||||||
}
|
}
|
||||||
|
|
||||||
Terminal::Terminal()
|
Terminal::Terminal()
|
||||||
|
@ -349,6 +360,7 @@ void Terminal::_gui_input(Variant event)
|
||||||
auto iter = keymap.find({unicode, scancode});
|
auto iter = keymap.find({unicode, scancode});
|
||||||
uint32_t keysym = (iter != keymap.end() ? iter->second : XKB_KEY_NoSymbol);
|
uint32_t keysym = (iter != keymap.end() ? iter->second : XKB_KEY_NoSymbol);
|
||||||
|
|
||||||
|
input_event_key = k;
|
||||||
tsm_vte_handle_keyboard(vte, keysym, ascii, mods, unicode ? unicode : TSM_VTE_INVALID);
|
tsm_vte_handle_keyboard(vte, keysym, ascii, mods, unicode ? unicode : TSM_VTE_INVALID);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -425,6 +437,9 @@ void Terminal::draw_foreground(int row, int col, Color fgcolor)
|
||||||
|
|
||||||
struct cell cell = cells[row][col];
|
struct cell cell = cells[row][col];
|
||||||
|
|
||||||
|
if (cell.ch == nullptr)
|
||||||
|
return; // No foreground to draw
|
||||||
|
|
||||||
/* Set the font */
|
/* Set the font */
|
||||||
|
|
||||||
Ref<Font> fontref = get_font("");
|
Ref<Font> fontref = get_font("");
|
||||||
|
@ -448,9 +463,6 @@ void Terminal::draw_foreground(int row, int col, Color fgcolor)
|
||||||
|
|
||||||
/* Draw the foreground */
|
/* Draw the foreground */
|
||||||
|
|
||||||
if (cell.ch == nullptr)
|
|
||||||
return; // No foreground to draw
|
|
||||||
|
|
||||||
if (cell.attr.blink)
|
if (cell.attr.blink)
|
||||||
; // TODO: Handle blink
|
; // TODO: Handle blink
|
||||||
|
|
||||||
|
@ -523,7 +535,7 @@ void Terminal::update_size()
|
||||||
rows = std::max(2, (int)floor(get_rect().size.y / cell_size.y));
|
rows = std::max(2, (int)floor(get_rect().size.y / cell_size.y));
|
||||||
cols = std::max(1, (int)floor(get_rect().size.x / cell_size.x));
|
cols = std::max(1, (int)floor(get_rect().size.x / cell_size.x));
|
||||||
|
|
||||||
Godot::print(String("resized_rows: {0}, resized_cols: {1}").format(Array::make(rows, cols)));
|
emit_signal("size_changed", Vector2(cols, rows));
|
||||||
|
|
||||||
Cells new_cells = {};
|
Cells new_cells = {};
|
||||||
|
|
||||||
|
|
|
@ -28,6 +28,8 @@ namespace godot
|
||||||
|
|
||||||
Cells cells;
|
Cells cells;
|
||||||
|
|
||||||
|
Ref<InputEventKey> input_event_key;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
tsm_screen *screen;
|
tsm_screen *screen;
|
||||||
tsm_vte *vte;
|
tsm_vte *vte;
|
||||||
|
|
131
addons/godot_xterm/nodes/terminal/README.md
Normal file
131
addons/godot_xterm/nodes/terminal/README.md
Normal file
|
@ -0,0 +1,131 @@
|
||||||
|
# Terminal
|
||||||
|
|
||||||
|
**Inherits:** [Control] < [CanvasItem] < [Node] < [Object]
|
||||||
|
|
||||||
|
|
||||||
|
Terminal emulator.
|
||||||
|
|
||||||
|
**IMPORTANT:**
|
||||||
|
|
||||||
|
<img align="right" src="./docs/important_properties.png"/>
|
||||||
|
|
||||||
|
- If you are not seeing anything in the terminal check that a theme has been set. If there is no theme, everything will be drawn in black by default.
|
||||||
|
- If the terminal isn't responding to keyboard or mouse input check that `focus_mode` is set to `All`, otherwise `_gui_input()` won't be called so no input will be processed.
|
||||||
|
|
||||||
|
|
||||||
|
## Description
|
||||||
|
|
||||||
|
![Flow Diagram](./docs/flow_diagram.svg)
|
||||||
|
|
||||||
|
### (1) User Input
|
||||||
|
|
||||||
|
The users enters some data into the terminal, typically by typing something on the keyboard or clicking (and possibly dragging) somewhere on the screen.
|
||||||
|
This corresponds to the `_gui_input()` method which is implemented in [terminal.cpp](../native/src/terminal.cpp).
|
||||||
|
|
||||||
|
### (2) Terminal Output
|
||||||
|
|
||||||
|
The user input from (1) is processed by the terminal and converted.
|
||||||
|
For example, if the user were to press the down key, the terminal would
|
||||||
|
and the `data_sent` signal would be emitted with the value `"\u001b[A"`.
|
||||||
|
For a full list of escape sequences ["XTerm Control Sequences"](https://invisible-island.net/xterm/ctlseqs/ctlseqs.html).
|
||||||
|
|
||||||
|
### (3) Terminal Input
|
||||||
|
|
||||||
|
In the other direction, characters can be sent to the terminal. This corresponds to the `write()` method.
|
||||||
|
|
||||||
|
### (4) Draw
|
||||||
|
|
||||||
|
The input from (3) is then intepreted by the terminal and drawn to the screen.
|
||||||
|
For example if the string "\u001b[39;m" was written to the terminal, then it would draw some colorful output to the screen.
|
||||||
|
|
||||||
|
## Properties
|
||||||
|
|
||||||
|
| Type | Name | Default |
|
||||||
|
|-------|------|---------|
|
||||||
|
| [int] | rows | 24 |
|
||||||
|
| [int] | cols | 80 |
|
||||||
|
|
||||||
|
## Methods
|
||||||
|
|
||||||
|
## Theme Properties
|
||||||
|
|
||||||
|
| Type | Name | Default |
|
||||||
|
|---------|-------------------------------|------------------------------|
|
||||||
|
| [Color] | Terminal/colors/Background | Color(0.0, 0.0, 0.0, 1.0) |
|
||||||
|
| [Color] | Terminal/colors/Black | Color(0.0, 0.0, 0.0, 1.0) |
|
||||||
|
| [Color] | Terminal/colors/Blue | Color(0.0, 0.0, 0.5, 1.0) |
|
||||||
|
| [Color] | Terminal/colors/Cyan | Color(0.0, 0.5, 0.5, 1.0) |
|
||||||
|
| [Color] | Terminal/colors/Dark Grey | Color(0.5, 0.5, 0.5, 1.0) |
|
||||||
|
| [Color] | Terminal/colors/Foreground | Color(1.0, 1.0, 1.0, 1.0) |
|
||||||
|
| [Color] | Terminal/colors/Green | Color(0.0, 0.5, 0.0, 1.0) |
|
||||||
|
| [Color] | Terminal/colors/Light Blue | Color(0.0, 0.0, 1.0, 1.0) |
|
||||||
|
| [Color] | Terminal/colors/Light Cyan | Color(0.0, 1.0, 1.0, 1.0) |
|
||||||
|
| [Color] | Terminal/colors/Light Green | Color(0.0, 1.0, 0.0, 1.0) |
|
||||||
|
| [Color] | Terminal/colors/Light Grey | Color(0.75, 0.75, 0.75, 1.0) |
|
||||||
|
| [Color] | Terminal/colors/Light Magenta | Color(1.0, 0.0, 1.0, 1.0) |
|
||||||
|
| [Color] | Terminal/colors/Light Red | Color(1.0, 0.0, 0.0, 1.0) |
|
||||||
|
| [Color] | Terminal/colors/Light Yellow | Color(1.0, 1.0, 0.0, 1.0) |
|
||||||
|
| [Color] | Terminal/colors/Magenta | Color(0.5, 0.0, 0.5, 1.0) |
|
||||||
|
| [Color] | Terminal/colors/Red | Color(0.5, 0.0, 0.0, 1.0) |
|
||||||
|
| [Color] | Terminal/colors/White | Color(1.0, 1.0, 1.0, 1.0) |
|
||||||
|
| [Color] | Terminal/colors/Yellow | Color(0.5, 0.5, 0.0, 1.0) |
|
||||||
|
| [Font] | Terminal/fonts/Bold | |
|
||||||
|
| [Font] | Terminal/fonts/Bold Italic | |
|
||||||
|
| [Font] | Terminal/fonts/Italic | |
|
||||||
|
| [Font] | Terminal/fonts/Regular | |
|
||||||
|
|
||||||
|
## Signals
|
||||||
|
|
||||||
|
- **data_sent** **(** PoolByteArray data **)**
|
||||||
|
|
||||||
|
Emitted when some data comes out of the terminal.
|
||||||
|
This typically occurs when the user interacts with the terminal by typing on the keyboard or clicking somewhere.
|
||||||
|
It might also occur.
|
||||||
|
Depending on several terminal settings can be interpreted differently, depending on modifier keys and the terminals settings/state.
|
||||||
|
In a typical setup, this data would be forwarded to the linux operating system.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
- **key_pressed** **(** int row **)**
|
||||||
|
|
||||||
|
Emitted when a key is pressed.
|
||||||
|
|
||||||
|
## Property Descriptions
|
||||||
|
|
||||||
|
- [int] **rows**
|
||||||
|
|
||||||
|
| | |
|
||||||
|
|-----------|-----------------|
|
||||||
|
| *Default* | 24 |
|
||||||
|
| *Setter* | set_rows(value) |
|
||||||
|
| *Getter* | get_rows(value) |
|
||||||
|
|
||||||
|
The number of rows in the terminal's rect.
|
||||||
|
When using a monospace font, this is typically the number of characters that can fit from one side to another.
|
||||||
|
Therefore it is affected by the things thing.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
- [int] **cols**
|
||||||
|
The number of columns in the terminal's rect.
|
||||||
|
|
||||||
|
## Method Descriptions
|
||||||
|
|
||||||
|
- void **write** **(** String|PoolByteArray data **)**
|
||||||
|
|
||||||
|
Writes data to the terminal emulator. Accepts either a String or PoolByteArray.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
```gdscript
|
||||||
|
$Terminal.write("Hello World")
|
||||||
|
$Terminal.write("Hello World".to_utf8())
|
||||||
|
$Terminal.write(PoolByteArray([0x1b, 0x9e])
|
||||||
|
```
|
||||||
|
|
||||||
|
[Control]: https://docs.godotengine.org/en/stable/classes/class_control.html#class-control
|
||||||
|
[CanvasItem]: https://docs.godotengine.org/en/stable/classes/class_canvasitem.html#class-canvasitem
|
||||||
|
[Node]: https://docs.godotengine.org/en/stable/classes/class_node.html#class-node
|
||||||
|
[Object]: https://docs.godotengine.org/en/stable/classes/class_object.html#class-object
|
||||||
|
[Color]: https://docs.godotengine.org/en/stable/classes/class_color.html#class-color
|
||||||
|
[Font]: https://docs.godotengine.org/en/stable/classes/class_font.html#class-font
|
||||||
|
[int]: https://docs.godotengine.org/en/stable/classes/class_int.html#class-int
|
0
addons/godot_xterm/nodes/terminal/docs/.gdignore
Normal file
0
addons/godot_xterm/nodes/terminal/docs/.gdignore
Normal file
3777
addons/godot_xterm/nodes/terminal/docs/flow_diagram.svg
Normal file
3777
addons/godot_xterm/nodes/terminal/docs/flow_diagram.svg
Normal file
File diff suppressed because one or more lines are too long
After Width: | Height: | Size: 360 KiB |
BIN
addons/godot_xterm/nodes/terminal/docs/important_properties.png
Normal file
BIN
addons/godot_xterm/nodes/terminal/docs/important_properties.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 11 KiB |
|
@ -17,3 +17,7 @@ func get_class() -> String:
|
||||||
|
|
||||||
func is_class(name) -> bool:
|
func is_class(name) -> bool:
|
||||||
return name == get_class() or .is_class(name)
|
return name == get_class() or .is_class(name)
|
||||||
|
|
||||||
|
|
||||||
|
func _init():
|
||||||
|
step = 0.01 # Parent override.
|
||||||
|
|
66
addons/godot_xterm/util/tput.gd
Normal file
66
addons/godot_xterm/util/tput.gd
Normal file
|
@ -0,0 +1,66 @@
|
||||||
|
extends Reference
|
||||||
|
class_name TPut
|
||||||
|
|
||||||
|
# Control Sequence Introducer
|
||||||
|
const CSI = "\u001b["
|
||||||
|
|
||||||
|
const CURSOR_UP = "\u001b[A"
|
||||||
|
const CURSOR_DOWN = "\u001b[B"
|
||||||
|
const CURSOR_RIGHT = "\u001b[C"
|
||||||
|
const CURSOR_LEFT = "\u001b[D"
|
||||||
|
|
||||||
|
const DEFAULT_FOREGROUND_COLOR = "\u001b[0m"
|
||||||
|
|
||||||
|
|
||||||
|
var terminal
|
||||||
|
|
||||||
|
|
||||||
|
func _init(p_terminal: Control) -> void:
|
||||||
|
if p_terminal:
|
||||||
|
terminal = p_terminal
|
||||||
|
|
||||||
|
|
||||||
|
func write_string(string: String, color: Color = Color.white) -> void:
|
||||||
|
if color:
|
||||||
|
var fg = "\u001b[38;2;%d;%d;%dm" % [color.r8, color.g8, color.b8]
|
||||||
|
terminal.write(fg.to_utf8())
|
||||||
|
|
||||||
|
terminal.write(string.to_utf8())
|
||||||
|
|
||||||
|
# Reset color back to default.
|
||||||
|
terminal.write("\u001b[0m".to_utf8())
|
||||||
|
|
||||||
|
# tput_* functions based on the tput command.
|
||||||
|
# See: https://man7.org/linux/man-pages/man1/tput.1.html for more info.
|
||||||
|
|
||||||
|
|
||||||
|
# Hide the cursor.
|
||||||
|
func civis():
|
||||||
|
terminal.write("%s?25l" % CSI)
|
||||||
|
|
||||||
|
|
||||||
|
# Position the cursor at the given row and col.
|
||||||
|
func cup(row: int = 0, col: int = 0) -> void:
|
||||||
|
terminal.write("\u001b[%d;%dH" % [row, col])
|
||||||
|
|
||||||
|
|
||||||
|
func setaf(color: Color) -> void:
|
||||||
|
var fg = "\u001b[38;2;%d;%d;%dm" % [color.r8, color.g8, color.b8]
|
||||||
|
terminal.write(fg)
|
||||||
|
|
||||||
|
|
||||||
|
func setab(color: Color) -> void:
|
||||||
|
var bg = "\u001b[48;2;%d;%d;%dm" % [color.r8, color.g8, color.b8]
|
||||||
|
terminal.write(bg)
|
||||||
|
|
||||||
|
|
||||||
|
func rev() -> void:
|
||||||
|
terminal.write("\u001b[7m")
|
||||||
|
|
||||||
|
|
||||||
|
func sgr0() -> void:
|
||||||
|
terminal.write("\u001b[0m")
|
||||||
|
|
||||||
|
|
||||||
|
func reset() -> void:
|
||||||
|
terminal.write("\u001bc")
|
|
@ -1,24 +1,23 @@
|
||||||
[gd_scene load_steps=5 format=2]
|
[gd_scene load_steps=4 format=2]
|
||||||
|
|
||||||
[ext_resource path="res://examples/asciicast/asciicast.gd" type="Script" id=1]
|
|
||||||
[ext_resource path="res://addons/godot_xterm/themes/default.theme" type="Theme" id=2]
|
[ext_resource path="res://addons/godot_xterm/themes/default.theme" type="Theme" id=2]
|
||||||
[ext_resource path="res://addons/godot_xterm/nodes/terminal/terminal.gdns" type="Script" id=4]
|
[ext_resource path="res://addons/godot_xterm/nodes/terminal/terminal.gdns" type="Script" id=4]
|
||||||
[ext_resource path="res://examples/asciicast/example.cast" type="Animation" id=6]
|
[ext_resource path="res://examples/asciicast/example.cast" type="Animation" id=6]
|
||||||
|
|
||||||
[node name="Container" type="Container"]
|
[node name="Terminal" type="Control"]
|
||||||
margin_right = 40.0
|
anchor_right = 1.0
|
||||||
margin_bottom = 40.0
|
anchor_bottom = 1.0
|
||||||
script = ExtResource( 1 )
|
focus_mode = 2
|
||||||
|
theme = ExtResource( 2 )
|
||||||
|
script = ExtResource( 4 )
|
||||||
__meta__ = {
|
__meta__ = {
|
||||||
"_edit_use_anchors_": false
|
"_edit_use_anchors_": false
|
||||||
}
|
}
|
||||||
|
rows = 31
|
||||||
|
cols = 102
|
||||||
|
|
||||||
[node name="Terminal" type="Control" parent="."]
|
[node name="AnimationPlayer" type="AnimationPlayer" parent="."]
|
||||||
margin_right = 40.0
|
autoplay = "example"
|
||||||
margin_bottom = 40.0
|
playback_speed = 2.0
|
||||||
theme = ExtResource( 2 )
|
|
||||||
script = ExtResource( 4 )
|
|
||||||
|
|
||||||
[node name="AnimationPlayer" type="AnimationPlayer" parent="Terminal"]
|
|
||||||
method_call_mode = 1
|
method_call_mode = 1
|
||||||
anims/a = ExtResource( 6 )
|
anims/example = ExtResource( 6 )
|
||||||
|
|
|
@ -1,61 +1,779 @@
|
||||||
{"version": 2, "width": 86, "height": 29, "timestamp": 1589772748, "env": {"SHELL": "/run/current-system/sw/bin/bash", "TERM": "xterm"}}
|
{"version": 2, "width": 95, "height": 56, "timestamp": 1601879053, "env": {"SHELL": "/run/current-system/sw/bin/bash", "TERM": "xterm"}}
|
||||||
[0.082961, "o", "> "]
|
[0.009015, "o", "sh-4.4$ "]
|
||||||
[0.798002, "o", "e"]
|
[0.768572, "o", "#"]
|
||||||
[0.893414, "o", "c"]
|
[0.994511, "o", " "]
|
||||||
[0.956255, "o", "h"]
|
[1.251891, "o", "P"]
|
||||||
[1.008677, "o", "o"]
|
[1.390056, "o", "r"]
|
||||||
[1.089472, "o", " "]
|
[1.556055, "o", "e"]
|
||||||
[1.189602, "o", "h"]
|
[1.633343, "o", "s"]
|
||||||
[1.266892, "o", "e"]
|
[1.758128, "o", "s"]
|
||||||
[1.347483, "o", "l"]
|
[1.837416, "o", " "]
|
||||||
[1.46568, "o", "l"]
|
[2.082763, "o", "E"]
|
||||||
[1.541039, "o", "o"]
|
[2.15487, "o", "S"]
|
||||||
[1.726772, "o", "\r\n"]
|
[2.206575, "o", "C"]
|
||||||
[1.727475, "o", "hello\r\n> "]
|
[2.535156, "o", " "]
|
||||||
[2.060109, "o", "#"]
|
[2.675284, "o", "t"]
|
||||||
[2.179668, "o", " "]
|
[2.764107, "o", "o"]
|
||||||
[2.471941, "o", "T"]
|
[2.826769, "o", " "]
|
||||||
[2.652735, "o", "h"]
|
[2.95468, "o", "e"]
|
||||||
[2.746515, "o", "i"]
|
[3.107351, "o", "x"]
|
||||||
[2.810578, "o", "s"]
|
[3.236995, "o", "i"]
|
||||||
[2.921342, "o", " "]
|
[3.315722, "o", "t"]
|
||||||
[2.98886, "o", "i"]
|
[3.363186, "o", " "]
|
||||||
[3.069095, "o", "s"]
|
[3.464495, "o", "t"]
|
||||||
[3.31728, "o", " "]
|
[3.502985, "o", "h"]
|
||||||
[3.399615, "o", "a"]
|
[3.561326, "o", "i"]
|
||||||
[3.513605, "o", " "]
|
[3.637971, "o", "s"]
|
||||||
[3.72609, "o", "d"]
|
[3.696915, "o", " "]
|
||||||
[3.811197, "o", "e"]
|
[3.828476, "o", "d"]
|
||||||
[3.94649, "o", "m"]
|
[3.920953, "o", "e"]
|
||||||
[4.047162, "o", "o"]
|
[3.977016, "o", "m"]
|
||||||
[4.225042, "o", "\r\n"]
|
[4.080181, "o", "o"]
|
||||||
[4.225402, "o", "> "]
|
[4.183719, "o", " "]
|
||||||
[4.935288, "o", "t"]
|
[4.411889, "o", "a"]
|
||||||
[5.163552, "o", "o"]
|
[4.505969, "o", "t"]
|
||||||
[5.323205, "o", "i"]
|
[4.602301, "o", " "]
|
||||||
[5.46746, "o", "l"]
|
[4.738613, "o", "a"]
|
||||||
[5.561098, "o", "et "]
|
[4.815285, "o", "n"]
|
||||||
[6.064937, "o", "-"]
|
[4.970011, "o", "y"]
|
||||||
[6.41563, "o", "-"]
|
[5.048946, "o", " "]
|
||||||
[6.60443, "o", "g"]
|
[5.140987, "o", "t"]
|
||||||
[6.666621, "o", "a"]
|
[5.22994, "o", "i"]
|
||||||
[6.768317, "o", "y"]
|
[5.300908, "o", "m"]
|
||||||
[6.848917, "o", " "]
|
[5.391697, "o", "e"]
|
||||||
[7.076406, "o", "H"]
|
[5.833247, "o", "\r\n"]
|
||||||
[7.250067, "o", "E"]
|
[5.833292, "o", "sh-4.4$ "]
|
||||||
[7.410878, "o", "L"]
|
[6.497175, "o", "#"]
|
||||||
[7.537016, "o", "L"]
|
[6.584674, "o", " "]
|
||||||
[7.604155, "o", "O"]
|
[6.783908, "o", "T"]
|
||||||
[7.888992, "o", " "]
|
[6.982053, "o", "h"]
|
||||||
[8.193437, "o", "W"]
|
[7.075839, "o", "i"]
|
||||||
[8.365871, "o", "O"]
|
[7.121841, "o", "s"]
|
||||||
[8.454678, "o", "R"]
|
[7.207194, "o", " "]
|
||||||
[8.525163, "o", "L"]
|
[7.472273, "o", "t"]
|
||||||
[8.60286, "o", "D"]
|
[7.56542, "o", "e"]
|
||||||
[8.873053, "o", "!"]
|
[7.633672, "o", "r"]
|
||||||
[9.216434, "o", "\r\n"]
|
[7.708612, "o", "m"]
|
||||||
[9.251462, "o", " \r\n \u001b[0;1;31;91mm\u001b[0m \u001b[0;1;36;96mm\u001b[0m \u001b[0;1;34;94mmm\u001b[0;1;35;95mmm\u001b[0;1;31;91mmm\u001b[0m \u001b[0;1;33;93mm\u001b[0m \u001b[0;1;35;95mm\u001b[0m \u001b[0;1;36;96mmm\u001b[0;1;34;94mmm\u001b[0m \u001b[0;1;36;96mm\u001b[0m \u001b[0;1;31;91mm\u001b[0m \u001b[0;1;33;93mm\u001b[0;1;32;92mmm\u001b[0;1;36;96mm\u001b[0m \u001b[0;1;34;94mm\u001b[0;1;35;95mmm\u001b[0;1;31;91mmm\u001b[0m \u001b[0;1;32;92mm\u001b[0m \u001b[0;1;35;95mm\u001b[0;1;31;91mmm\u001b[0;1;33;93mm\u001b[0m \r\n \u001b[0;1;33;93m#\u001b[0m \u001b[0;1;34;94m#\u001b[0m \u001b[0;1;35;95m#\u001b[0m \u001b[0;1;32;92m#\u001b[0m \u001b[0;1;31;91m#\u001b[0m \u001b[0;1;36;96mm\u001b[0;1;34;94m\"\u001b[0m \u001b[0;1;35;95m\"\u001b[0;1;31;91mm\u001b[0m \u001b[0;1;34;94m#\u001b[0m \u001b[0;1;35;95m#\u001b[0m \u001b[0;1;33;93m#\u001b[0m \u001b[0;1;32;92mm\"\u001b[0m \u001b[0;1;34;94m\"m\u001b[0m \u001b[0;1;35;95m#\u001b[0m \u001b[0;1;33;93m\"\u001b[0;1;32;92m#\u001b[0m \u001b[0;1;36;96m#\u001b[0m \u001b[0;1;31;91m#\u001b[0m \u001b[0;1;32;92m\"\u001b[0;1;36;96mm\u001b[0m\r\n \u001b[0;1;32;92m#\u001b[0;1;36;96mmm\u001b[0;1;34;94mmm\u001b[0;1;35;95m#\u001b[0m \u001b[0;1;31;91m#m\u001b[0;1;33;93mmm\u001b[0;1;32;92mmm\u001b[0m \u001b[0;1;36;96m#\u001b[0m \u001b[0;1;33;93m#\u001b[0m \u001b[0;1;34;94m#\u001b"]
|
[7.794029, "o", "i"]
|
||||||
[9.251901, "o", "[0m \u001b[0;1;33;93m#\u001b[0m \u001b[0;1;35;95m\"\u001b[0m \u001b[0;1;31;91m#\"\u001b[0;1;33;93m#\u001b[0m \u001b[0;1;32;92m#\u001b[0m \u001b[0;1;36;96m#\u001b[0m \u001b[0;1;35;95m#\u001b[0m \u001b[0;1;31;91m#\u001b[0;1;33;93mmm\u001b[0;1;32;92mmm\u001b[0;1;36;96m\"\u001b[0m \u001b[0;1;34;94m#\u001b[0m \u001b[0;1;33;93m#\u001b[0m \u001b[0;1;34;94m#\u001b[0m\r\n \u001b[0;1;36;96m#\u001b[0m \u001b[0;1;31;91m#\u001b[0m \u001b[0;1;33;93m#\u001b[0m \u001b[0;1;34;94m#\u001b[0m \u001b[0;1;32;92m#\u001b[0m \u001b[0;1;35;95m#\u001b[0m \u001b[0;1;32;92m#\u001b[0m \u001b[0;1;31;91m#\u001b[0;1;33;93m#\u001b[0m \u001b[0;1;32;92m##\u001b[0;1;36;96m\"\u001b[0m \u001b[0;1;34;94m#\u001b[0m \u001b[0;1;31;91m#\u001b[0m \u001b[0;1;33;93m#\u001b[0m \u001b[0;1;36;96m\"\u001b[0;1;34;94mm\u001b[0m \u001b[0;1;35;95m#\u001b[0m \u001b[0;1;32;92m#\u001b[0m \u001b[0;1;35;95m#\u001b[0m\r\n \u001b[0;1;34;94m#\u001b[0m \u001b[0;1;33;93m#\u001b[0m \u001b[0;1;32;92m#m\u001b[0;1;36;96mmm\u001b[0;1;34;94mmm\u001b[0m \u001b[0;1;35;95m#\u001b[0;1;31;91mmm\u001b[0;1;33;93mmm\u001b[0;1;32;92mm\u001b[0m \u001b[0;1;36;96m#m\u001b[0;1;34;94mmm\u001b[0;1;35;95mmm\u001b[0m \u001b[0;1;33;93m#m\u001b[0;1;32;92mm#\u001b[0m \u001b[0;1;33;93m#\u001b[0m \u001b[0;1;36;96m#\u001b[0m \u001b[0;1;35;95m#\u001b[0;1;31;91mmm\u001b[0;1;33;93m#\u001b[0m \u001b[0;1;32;92m#\u001b[0m \u001b[0;1;35;95m\"\u001b[0m \u001b[0;1;31;91m#m\u001b[0;1;33;93mmm\u001b[0;1"]
|
[7.852906, "o", "n"]
|
||||||
[9.251944, "o", ";32;92mmm\u001b[0m \u001b[0;1;36;96m#\u001b[0;1;34;94mmm\u001b[0;1;35;95mm\"\u001b[0m \r\n \r\n \r\n \r\n \u001b[0;1;36;96mm\u001b[0m \r\n \u001b[0;1;34;94m#\u001b[0m \r\n \u001b[0;1;35;95m#\u001b[0m \r\n \u001b[0;1;31;91m\"\u001b[0m \r\n \u001b[0;1;33;93m#\u001b[0m \r\n \r\n \r\n"]
|
[7.960908, "o", "a"]
|
||||||
[9.252259, "o", "> "]
|
[8.034148, "o", "l"]
|
||||||
[12.56287, "o", "exit\r\n"]
|
[8.1316, "o", " "]
|
||||||
|
[8.2592, "o", "s"]
|
||||||
|
[8.376712, "o", "e"]
|
||||||
|
[8.453216, "o", "s"]
|
||||||
|
[8.583006, "o", "s"]
|
||||||
|
[8.64767, "o", "i"]
|
||||||
|
[8.711495, "o", "o"]
|
||||||
|
[8.779941, "o", "n"]
|
||||||
|
[8.862385, "o", " "]
|
||||||
|
[9.112564, "o", "w"]
|
||||||
|
[9.236889, "o", "a"]
|
||||||
|
[9.29605, "o", "s"]
|
||||||
|
[9.376424, "o", " "]
|
||||||
|
[9.672264, "o", "r"]
|
||||||
|
[9.768395, "o", "e"]
|
||||||
|
[9.875859, "o", "c"]
|
||||||
|
[10.360921, "o", "o"]
|
||||||
|
[10.48178, "o", "r"]
|
||||||
|
[10.573511, "o", "d"]
|
||||||
|
[10.70553, "o", "e"]
|
||||||
|
[10.772014, "o", "d"]
|
||||||
|
[10.901859, "o", " "]
|
||||||
|
[11.222266, "o", "u"]
|
||||||
|
[11.314773, "o", "s"]
|
||||||
|
[11.388137, "o", "i"]
|
||||||
|
[11.462257, "o", "n"]
|
||||||
|
[11.508588, "o", "g"]
|
||||||
|
[11.610203, "o", " "]
|
||||||
|
[11.704458, "o", "t"]
|
||||||
|
[11.769386, "o", "h"]
|
||||||
|
[11.829674, "o", "e"]
|
||||||
|
[11.920249, "o", " "]
|
||||||
|
[12.057327, "o", "a"]
|
||||||
|
[12.150311, "o", "s"]
|
||||||
|
[12.221965, "o", "c"]
|
||||||
|
[12.335971, "o", "i"]
|
||||||
|
[12.461568, "o", "i"]
|
||||||
|
[12.659298, "o", "n"]
|
||||||
|
[12.787306, "o", "e"]
|
||||||
|
[12.861305, "o", "m"]
|
||||||
|
[13.243252, "o", "a"]
|
||||||
|
[13.415869, "o", " "]
|
||||||
|
[13.640678, "o", "p"]
|
||||||
|
[13.727956, "o", "r"]
|
||||||
|
[13.79999, "o", "o"]
|
||||||
|
[13.869981, "o", "g"]
|
||||||
|
[13.932686, "o", "r"]
|
||||||
|
[14.120489, "o", "a"]
|
||||||
|
[14.563155, "o", "m"]
|
||||||
|
[14.950597, "o", "\r\n"]
|
||||||
|
[14.950636, "o", "sh-4.4$ "]
|
||||||
|
[15.25787, "o", "#"]
|
||||||
|
[15.357041, "o", " "]
|
||||||
|
[15.549955, "o", "F"]
|
||||||
|
[15.69595, "o", "o"]
|
||||||
|
[15.742517, "o", "r"]
|
||||||
|
[15.816029, "o", " "]
|
||||||
|
[16.017346, "o", "m"]
|
||||||
|
[16.134482, "o", "o"]
|
||||||
|
[16.214998, "o", "r"]
|
||||||
|
[16.287911, "o", "e"]
|
||||||
|
[16.341746, "o", " "]
|
||||||
|
[16.536357, "o", "i"]
|
||||||
|
[16.63003, "o", "n"]
|
||||||
|
[16.757694, "o", "f"]
|
||||||
|
[16.840006, "o", "o"]
|
||||||
|
[16.955199, "o", " "]
|
||||||
|
[17.10089, "o", "v"]
|
||||||
|
[17.212207, "o", "i"]
|
||||||
|
[17.310707, "o", "s"]
|
||||||
|
[17.433414, "o", "i"]
|
||||||
|
[17.504056, "o", "t"]
|
||||||
|
[17.639282, "o", " "]
|
||||||
|
[18.027938, "o", "h"]
|
||||||
|
[18.148473, "o", "t"]
|
||||||
|
[18.254587, "o", "t"]
|
||||||
|
[18.365992, "o", "p"]
|
||||||
|
[18.422981, "o", "s"]
|
||||||
|
[18.69077, "o", ":"]
|
||||||
|
[18.981756, "o", "/"]
|
||||||
|
[19.072248, "o", "/"]
|
||||||
|
[19.451925, "o", "a"]
|
||||||
|
[19.52595, "o", "s"]
|
||||||
|
[19.590197, "o", "c"]
|
||||||
|
[19.690475, "o", "i"]
|
||||||
|
[19.812762, "o", "i"]
|
||||||
|
[20.002006, "o", "n"]
|
||||||
|
[20.285781, "o", "e"]
|
||||||
|
[20.436427, "o", "m"]
|
||||||
|
[20.528716, "o", "a"]
|
||||||
|
[20.763135, "o", "."]
|
||||||
|
[20.903967, "o", "o"]
|
||||||
|
[20.975119, "o", "r"]
|
||||||
|
[20.985324, "o", "g"]
|
||||||
|
[20.99331, "o", "\r\nsh-4.4$ "]
|
||||||
|
[21.605944, "o", "#"]
|
||||||
|
[21.807285, "o", " "]
|
||||||
|
[22.010063, "o", "L"]
|
||||||
|
[22.188024, "o", "e"]
|
||||||
|
[22.279903, "o", "t"]
|
||||||
|
[22.361474, "o", "'"]
|
||||||
|
[22.486357, "o", "s"]
|
||||||
|
[22.57465, "o", " "]
|
||||||
|
[22.740959, "o", "i"]
|
||||||
|
[22.813009, "o", "n"]
|
||||||
|
[22.857842, "o", "s"]
|
||||||
|
[22.954863, "o", "t"]
|
||||||
|
[23.066967, "o", "a"]
|
||||||
|
[23.150687, "o", "l"]
|
||||||
|
[23.263568, "o", "l"]
|
||||||
|
[23.34495, "o", " "]
|
||||||
|
[24.24858, "o", "a"]
|
||||||
|
[24.339416, "o", "s"]
|
||||||
|
[24.418355, "o", "c"]
|
||||||
|
[24.541209, "o", "i"]
|
||||||
|
[24.697872, "o", "i"]
|
||||||
|
[24.872434, "o", "n"]
|
||||||
|
[24.964613, "o", "e"]
|
||||||
|
[25.07858, "o", "m"]
|
||||||
|
[25.153616, "o", "a"]
|
||||||
|
[26.123044, "o", "\r\n"]
|
||||||
|
[26.123082, "o", "sh-4.4$ "]
|
||||||
|
[26.610637, "o", "n"]
|
||||||
|
[26.731314, "o", "i"]
|
||||||
|
[26.840493, "o", "x"]
|
||||||
|
[26.950531, "o", "-"]
|
||||||
|
[27.030416, "o", "e"]
|
||||||
|
[27.143202, "o", "nv "]
|
||||||
|
[27.380791, "o", "-"]
|
||||||
|
[27.494532, "o", "i"]
|
||||||
|
[27.766916, "o", "A"]
|
||||||
|
[27.947392, "o", " "]
|
||||||
|
[28.069982, "o", "n"]
|
||||||
|
[28.153264, "o", "i"]
|
||||||
|
[28.285577, "o", "x"]
|
||||||
|
[28.398953, "o", "o"]
|
||||||
|
[28.528587, "o", "s"]
|
||||||
|
[28.714452, "o", "."]
|
||||||
|
[29.066201, "o", "a"]
|
||||||
|
[29.178501, "o", "s"]
|
||||||
|
[29.257687, "o", "c"]
|
||||||
|
[29.36677, "o", "i"]
|
||||||
|
[29.487456, "o", "i"]
|
||||||
|
[29.617427, "o", "n"]
|
||||||
|
[29.708982, "o", "e"]
|
||||||
|
[29.793394, "o", "m"]
|
||||||
|
[29.885927, "o", "a"]
|
||||||
|
[30.166746, "o", "\r\n"]
|
||||||
|
[30.269591, "o", "installing 'asciinema-2.0.2'\r\n"]
|
||||||
|
[30.442995, "o", "these paths will be fetched (0.05 MiB download, 0.19 MiB unpacked):\r\n /nix/store/jn1kalsv6g21rzhr46wsmb33rlbnxbp2-asciinema-2.0.2\r\n"]
|
||||||
|
[30.443793, "o", "copying path '/nix/store/jn1kalsv6g21rzhr46wsmb33rlbnxbp2-asciinema-2.0.2' from 'https://aseipp-nix-cache.global.ssl.fastly.net'...\r\n"]
|
||||||
|
[30.772997, "o", "building '/nix/store/j8zk1ixrzz8ffl2r8bfcblrbp8jib14n-user-environment.drv'...\r\n"]
|
||||||
|
[30.827776, "o", "created 2238 symlinks in user environment\r\n"]
|
||||||
|
[30.837521, "o", "\r\nsh-4.4$ "]
|
||||||
|
[31.439756, "o", "#"]
|
||||||
|
[31.531759, "o", " "]
|
||||||
|
[31.733672, "o", "N"]
|
||||||
|
[31.885784, "o", "o"]
|
||||||
|
[31.969473, "o", "w"]
|
||||||
|
[32.04399, "o", " "]
|
||||||
|
[32.184525, "o", "t"]
|
||||||
|
[32.498387, "o", "\b\u001b[K"]
|
||||||
|
[32.674218, "o", "w"]
|
||||||
|
[32.780078, "o", "e"]
|
||||||
|
[32.869318, "o", " "]
|
||||||
|
[33.015693, "o", "c"]
|
||||||
|
[33.131168, "o", "a"]
|
||||||
|
[33.215492, "o", "n"]
|
||||||
|
[33.277638, "o", " "]
|
||||||
|
[33.435631, "o", "r"]
|
||||||
|
[33.491613, "o", "e"]
|
||||||
|
[33.769703, "o", "c"]
|
||||||
|
[33.878877, "o", "o"]
|
||||||
|
[33.964167, "o", "r"]
|
||||||
|
[34.051787, "o", "d"]
|
||||||
|
[34.231502, "o", " "]
|
||||||
|
[34.38911, "o", "a"]
|
||||||
|
[34.517173, "o", " "]
|
||||||
|
[34.660129, "o", "n"]
|
||||||
|
[34.75175, "o", "e"]
|
||||||
|
[34.83474, "o", "w"]
|
||||||
|
[34.908203, "o", " "]
|
||||||
|
[36.304364, "o", "s"]
|
||||||
|
[36.387211, "o", "e"]
|
||||||
|
[36.465211, "o", "s"]
|
||||||
|
[36.596101, "o", "s"]
|
||||||
|
[36.695781, "o", "i"]
|
||||||
|
[36.762876, "o", "o"]
|
||||||
|
[36.824392, "o", "n"]
|
||||||
|
[36.922221, "o", " "]
|
||||||
|
[37.108339, "o", "t"]
|
||||||
|
[37.264521, "o", "o"]
|
||||||
|
[37.361574, "o", " "]
|
||||||
|
[37.490987, "o", "a"]
|
||||||
|
[37.578879, "o", " "]
|
||||||
|
[38.018804, "o", "."]
|
||||||
|
[38.110959, "o", "c"]
|
||||||
|
[38.210231, "o", "a"]
|
||||||
|
[38.270978, "o", "s"]
|
||||||
|
[38.3198, "o", "t"]
|
||||||
|
[38.402376, "o", " "]
|
||||||
|
[38.566701, "o", "f"]
|
||||||
|
[38.660991, "o", "i"]
|
||||||
|
[38.73289, "o", "l"]
|
||||||
|
[38.813984, "o", "e"]
|
||||||
|
[39.342188, "o", "\r\n"]
|
||||||
|
[39.342365, "o", "sh-4.4$ "]
|
||||||
|
[39.885874, "o", "a"]
|
||||||
|
[39.959473, "o", "s"]
|
||||||
|
[40.034948, "o", "c"]
|
||||||
|
[40.133815, "o", "i"]
|
||||||
|
[40.215169, "o", "inema "]
|
||||||
|
[40.590943, "o", "r"]
|
||||||
|
[40.672976, "o", "e"]
|
||||||
|
[40.752245, "o", "c"]
|
||||||
|
[40.83314, "o", " "]
|
||||||
|
[41.861795, "o", "n"]
|
||||||
|
[41.938138, "o", "e"]
|
||||||
|
[42.032994, "o", "w"]
|
||||||
|
[42.144281, "o", "."]
|
||||||
|
[42.250499, "o", "c"]
|
||||||
|
[42.323403, "o", "a"]
|
||||||
|
[42.407712, "o", "s"]
|
||||||
|
[42.470832, "o", "t"]
|
||||||
|
[42.814799, "o", "\r\n"]
|
||||||
|
[42.90735, "o", "\u001b[0;32masciinema: recording asciicast to new.cast\u001b[0m\r\n\u001b[0;32masciinema: press <ctrl-d> or type \"exit\" when you're done\u001b[0m\r\n"]
|
||||||
|
[42.951473, "o", "\u001b]2;laptop:leroy:~/projects/godot-xterm\u0007\r\r\n\u001b[1;32m[\u001b]0;leroy@laptop: ~/projects/godot-xterm\u0007leroy@laptop:~/projects/godot-xterm]$\u001b[0m "]
|
||||||
|
[45.647452, "o", "l"]
|
||||||
|
[45.943288, "o", "s"]
|
||||||
|
[46.286881, "o", "\r\n"]
|
||||||
|
[46.288383, "o", "\u001b[0m\u001b[01;34maddons\u001b[0m docker-compose.yml example.cast \u001b[01;35micon.png\u001b[0m new.cast\r\nCHANGELOG.md \u001b[01;34mdockerfiles\u001b[0m example.cast.import icon.png.import project.godot\r\ndefault_env.tres \u001b[01;34mdocs\u001b[0m \u001b[01;34mexamples\u001b[0m LICENSE README.md\r\n"]
|
||||||
|
[46.288974, "o", "\u001b]2;laptop:leroy:~/projects/godot-xterm\u0007\r\r\n\u001b[1;32m[\u001b]0;leroy@laptop: ~/projects/godot-xterm\u0007leroy@laptop:~/projects/godot-xterm]$\u001b[0m "]
|
||||||
|
[48.264058, "o", "s"]
|
||||||
|
[48.35698, "o", "h"]
|
||||||
|
[48.465218, "o", "a"]
|
||||||
|
[48.860943, "o", "1"]
|
||||||
|
[49.137467, "o", "s"]
|
||||||
|
[49.255023, "o", "u"]
|
||||||
|
[49.402646, "o", "m"]
|
||||||
|
[49.994215, "o", " "]
|
||||||
|
[50.137741, "o", "."]
|
||||||
|
[50.251377, "o", "/"]
|
||||||
|
[50.478669, "o", "*"]
|
||||||
|
[51.035519, "o", " "]
|
||||||
|
[51.587166, "o", "|"]
|
||||||
|
[51.713609, "o", " "]
|
||||||
|
[51.863023, "o", "l"]
|
||||||
|
[51.96232, "o", "o"]
|
||||||
|
[52.012303, "o", "l"]
|
||||||
|
[52.240101, "o", "c"]
|
||||||
|
[52.353223, "o", "a"]
|
||||||
|
[52.447717, "o", "t"]
|
||||||
|
[52.565175, "o", " "]
|
||||||
|
[52.947413, "o", "-"]
|
||||||
|
[53.353261, "o", "F"]
|
||||||
|
[53.634436, "o", " "]
|
||||||
|
[53.936746, "o", "0"]
|
||||||
|
[54.099132, "o", "."]
|
||||||
|
[54.364446, "o", "3"]
|
||||||
|
[54.66516, "o", "\r\n"]
|
||||||
|
[54.666593, "o", "sha1sum: ./addons: Is a directory\r\n"]
|
||||||
|
[54.66663, "o", "sha1sum: ./dockerfiles: Is a directory\r\nsha1sum: ./docs: Is a directory\r\nsha1sum: ./examples: Is a directory\r\n"]
|
||||||
|
[54.819505, "o", "\u001b[38;2;180;1;202mb\u001b[39m\u001b[38;2;168;3;211m2\u001b[39m\u001b[38;2;156;6;221mf\u001b[39m"]
|
||||||
|
[54.819607, "o", "\u001b[38;2;143;10;229m7\u001b[39m\u001b[38;2;131;16;236m9\u001b[39m\u001b[38;2;118;23;242me\u001b[39m"]
|
||||||
|
[54.819638, "o", "\u001b[38;2;105;30;247m8\u001b[39m\u001b[38;2;93;39;251mb\u001b[39m\u001b[38;2;81;48;253m2\u001b[39m\u001b[38;2;69;59;254mc\u001b[39m\u001b[38;2;58;70;254m2\u001b[39m"]
|
||||||
|
[54.819747, "o", "\u001b[38;2;48;81;253m9\u001b[39m\u001b[38;2;39;93;251m1\u001b[39m"]
|
||||||
|
[54.819806, "o", "\u001b[38;2;30;106;247ma\u001b[39m\u001b[38;2;22;118;242m7\u001b[39m"]
|
||||||
|
[54.819936, "o", "\u001b[38;2;16;131;236m9\u001b[39m\u001b[38;2;10;144;228m2\u001b[39m\u001b[38;2;6;156;220m7\u001b[39m\u001b[38;2;3;168;211m4\u001b[39m\u001b[38;2;1;180;201m3\u001b[39m"]
|
||||||
|
[54.820001, "o", "\u001b[38;2;1;191;191m2\u001b[39m\u001b[38;2;1;202;179m2\u001b[39m"]
|
||||||
|
[54.820056, "o", "\u001b[38;2;3;212;167m2\u001b[39m\u001b[38;2;6;221;155md\u001b[39m\u001b[38;2;11;229;143m8"]
|
||||||
|
[54.82013, "o", "\u001b[39m\u001b[38;2;16;236;130md\u001b[39m\u001b[38;2;23;242;117m4\u001b[39m\u001b[38;2;31;247;105m7\u001b[39m"]
|
||||||
|
[54.820187, "o", "\u001b[38;2;39;251;92me\u001b[39m\u001b[38;2;49;253;80mc\u001b[39m"]
|
||||||
|
[54.820245, "o", "\u001b[38;2;59;254;69m2\u001b[39m\u001b[38;2;70;254;58m5\u001b[39m"]
|
||||||
|
[54.820314, "o", "\u001b[38;2;82;253;48me\u001b[39m\u001b[38;2;94;250;38m8\u001b[39m\u001b[38;2;106;246;30m1"]
|
||||||
|
[54.820376, "o", "\u001b[39m\u001b[38;2;119;241;22m3\u001b[39m\u001b[38;2;132;235;15ma\u001b[39m"]
|
||||||
|
[54.820439, "o", "\u001b[38;2;144;228;10m5\u001b[39m\u001b[38;2;157;220;6m2\u001b[39m\u001b[38;2;169;211;3m3\u001b[39m"]
|
||||||
|
[54.820504, "o", "\u001b[38;2;181;201;1m \u001b[39m\u001b[38;2;192;190;1m \u001b[39m"]
|
||||||
|
[54.820559, "o", "\u001b[38;2;203;179;1m.\u001b[39m\u001b[38;2;213;167;3m/\u001b[39m"]
|
||||||
|
[54.82062, "o", "\u001b[38;2;222;154;7mC\u001b[39m\u001b[38;2;230;142;11mH\u001b[39m\u001b[38;2;237;129;17mA\u001b[39m"]
|
||||||
|
[54.820678, "o", "\u001b[38;2;243;117;23mN\u001b[39m\u001b[38;2;247;104;31mG\u001b[39m"]
|
||||||
|
[54.820738, "o", "\u001b[38;2;251;92;40mE\u001b[39m\u001b[38;2;253;80;50mL\u001b[39m"]
|
||||||
|
[54.820795, "o", "\u001b[38;2;254;68;60mO\u001b[39m\u001b[38;2;254;57;71mG\u001b[39m\u001b[38;2;253;47;83m.\u001b[39m"]
|
||||||
|
[54.820855, "o", "\u001b[38;2;250;38;95mm\u001b[39m\u001b[38;2;246;29;107md\u001b[39m"]
|
||||||
|
[54.820926, "o", "\u001b[38;2;241;22;120m\u001b[39m\r\n"]
|
||||||
|
[54.820985, "o", "\u001b[38;2;143;10;229m8\u001b[39m"]
|
||||||
|
[54.821038, "o", "\u001b[38;2;131;16;236m0\u001b[39m\u001b[38;2;118;23;242m4\u001b[39m\u001b[38;2;105;30;247m2\u001b[39m"]
|
||||||
|
[54.821094, "o", "\u001b[38;2;93;39;251m5\u001b[39m\u001b[38;2;81;48;253m3\u001b[39m"]
|
||||||
|
[54.821149, "o", "\u001b[38;2;69;59;254mf\u001b[39m\u001b[38;2;58;70;254m5\u001b[39m"]
|
||||||
|
[54.821206, "o", "\u001b[38;2;48;81;253m2\u001b[39m\u001b[38;2;39;93;251m6\u001b[39m"]
|
||||||
|
[54.821258, "o", "\u001b[38;2;30;106;247m6\u001b[39m\u001b[38;2;22;118;242m5\u001b[39m"]
|
||||||
|
[54.821311, "o", "\u001b[38;2;16;131;236mc\u001b[39m"]
|
||||||
|
[54.821381, "o", "\u001b[38;2;10;144;228m6\u001b[39m"]
|
||||||
|
[54.821436, "o", "\u001b[38;2;6;156;220m8\u001b[39m\u001b[38;2;3;168;211m7\u001b[39m\u001b[38;2;1;180;201md\u001b[39m"]
|
||||||
|
[54.821486, "o", "\u001b[38;2;1;191;191m6\u001b[39m\u001b[38;2;1;202;179m6\u001b[39m\u001b[38;2;3;212;167mb\u001b[39m"]
|
||||||
|
[54.821577, "o", "\u001b[38;2;6;221;155m4\u001b[39m\u001b[38;2;11;229;143ma\u001b[39m\u001b[38;2;16;236;130m2\u001b[39m\u001b[38;2;23;242;117m4\u001b[39m\u001b[38;2;31;247;105mb\u001b[39m"]
|
||||||
|
[54.821633, "o", "\u001b[38;2;39;251;92m3\u001b[39m\u001b[38;2;49;253;80m9\u001b[39m"]
|
||||||
|
[54.82166, "o", "\u001b[38;2;59;254;69mf\u001b[39m"]
|
||||||
|
[54.821741, "o", "\u001b[38;2;70;254;58m1\u001b[39m\u001b[38;2;82;253;48mc\u001b[39m\u001b[38;2;94;250;38m3\u001b[39m"]
|
||||||
|
[54.821906, "o", "\u001b[38;2;106;246;30m2\u001b[39m\u001b[38;2;119;241;22m8\u001b[39m\u001b[38;2;132;235;15m6\u001b[39m\u001b[38;2;144;228;10m9\u001b[39m\u001b[38;2;157;220;6m6\u001b[39m"]
|
||||||
|
[54.822031, "o", "\u001b[38;2;169;211;3m7\u001b[39m"]
|
||||||
|
[54.822114, "o", "\u001b[38;2;181;201;1mc\u001b[39m"]
|
||||||
|
[54.822971, "o", "\u001b[38;2;192;190;1m9\u001b[39m"]
|
||||||
|
[54.82305, "o", "\u001b[38;2;203;179;1md\u001b[39m\u001b[38;2;213;167;3m \u001b[39m\u001b[38;2;222;154;7m \u001b[39m\u001b[38;2;230;142;11m.\u001b[39m"]
|
||||||
|
[54.823129, "o", "\u001b[38;2;237;129;17m/\u001b[39m\u001b[38;2;243;117;23md\u001b[39m"]
|
||||||
|
[54.823188, "o", "\u001b[38;2;247;104;31me\u001b[39m"]
|
||||||
|
[54.823241, "o", "\u001b[38;2;251;92;40mf\u001b[39m"]
|
||||||
|
[54.823306, "o", "\u001b[38;2;253;80;50ma\u001b[39m\u001b[38;2;254;68;60mu\u001b[39m"]
|
||||||
|
[54.823368, "o", "\u001b[38;2;254;57;71ml\u001b[39m"]
|
||||||
|
[54.823436, "o", "\u001b[38;2;253;47;83mt\u001b[39m\u001b[38;2;250;38;95m_\u001b[39m"]
|
||||||
|
[54.823503, "o", "\u001b[38;2;246;29;107me\u001b[39m\u001b[38;2;241;22;120mn\u001b[39m"]
|
||||||
|
[54.823562, "o", "\u001b[38;2;235;15;132mv\u001b[39m\u001b[38;2;228;10;145m.\u001b[39m"]
|
||||||
|
[54.823622, "o", "\u001b[38;2;219;6;158mt\u001b[39m"]
|
||||||
|
[54.82368, "o", "\u001b[38;2;210;3;170mr\u001b[39m\u001b[38;2;200;1;182me\u001b[39m"]
|
||||||
|
[54.82374, "o", "\u001b[38;2;189;1;193ms\u001b[39m\u001b[38;2;178;1;203m\u001b[39m\r\n"]
|
||||||
|
[54.823865, "o", "\u001b[38;2;105;30;247ma\u001b[39m"]
|
||||||
|
[54.823926, "o", "\u001b[38;2;93;39;251ma\u001b[39m\u001b[38;2;81;48;253ma\u001b[39m\u001b[38;2;69;59;254m3\u001b[39m"]
|
||||||
|
[54.823989, "o", "\u001b[38;2;58;70;254md\u001b[39m\u001b[38;2;48;81;253ma\u001b[39m"]
|
||||||
|
[54.824055, "o", "\u001b[38;2;39;93;251me\u001b[39m\u001b[38;2;30;106;247m7\u001b[39m"]
|
||||||
|
[54.824148, "o", "\u001b[38;2;22;118;242ma\u001b[39m\u001b[38;2;16;131;236m2\u001b[39m"]
|
||||||
|
[54.824208, "o", "\u001b[38;2;10;144;228m9\u001b[39m\u001b[38;2;6;156;220m8\u001b[39m"]
|
||||||
|
[54.824275, "o", "\u001b[38;2;3;168;211me\u001b[39m\u001b[38;2;1;180;201m9\u001b[39m"]
|
||||||
|
[54.824347, "o", "\u001b[38;2;1;191;191m5\u001b[39m\u001b[38;2;1;202;179m8\u001b[39m"]
|
||||||
|
[54.824414, "o", "\u001b[38;2;3;212;167m4\u001b[39m\u001b[38;2;6;221;155m1\u001b[39m"]
|
||||||
|
[54.824469, "o", "\u001b[38;2;11;229;143md\u001b[39m\u001b[38;2;16;236;130m8\u001b[39m"]
|
||||||
|
[54.824557, "o", "\u001b[38;2;23;242;117m4\u001b[39m\u001b[38;2;31;247;105m7\u001b[39m\u001b[38;2;39;251;92m5\u001b[39m"]
|
||||||
|
[54.824618, "o", "\u001b[38;2;49;253;80ma\u001b[39m\u001b[38;2;59;254;69mc\u001b[39m"]
|
||||||
|
[54.824683, "o", "\u001b[38;2;70;254;58m2\u001b[39m\u001b[38;2;82;253;48m3\u001b[39m"]
|
||||||
|
[54.824738, "o", "\u001b[38;2;94;250;38mb\u001b[39m"]
|
||||||
|
[54.824796, "o", "\u001b[38;2;106;246;30m8\u001b[39m\u001b[38;2;119;241;22ma\u001b[39m"]
|
||||||
|
[54.824852, "o", "\u001b[38;2;132;235;15me\u001b[39m\u001b[38;2;144;228;10mc\u001b[39m"]
|
||||||
|
[54.82491, "o", "\u001b[38;2;157;220;6m7\u001b[39m\u001b[38;2;169;211;3ma"]
|
||||||
|
[54.825026, "o", "\u001b[39m\u001b[38;2;181;201;1mb\u001b[39m\u001b[38;2;192;190;1mb\u001b[39m\u001b[38;2;203;179;1mb\u001b[39m"]
|
||||||
|
[54.825088, "o", "\u001b[38;2;213;167;3ma\u001b[39m\u001b[38;2;222;154;7ma\u001b[39m"]
|
||||||
|
[54.825155, "o", "\u001b[38;2;230;142;11m2\u001b[39m\u001b[38;2;237;129;17m \u001b[39m\u001b[38;2;243;117;23m \u001b[39m"]
|
||||||
|
[54.825218, "o", "\u001b[38;2;247;104;31m.\u001b[39m\u001b[38;2;251;92;40m/\u001b[39m"]
|
||||||
|
[54.825294, "o", "\u001b[38;2;253;80;50md\u001b[39m"]
|
||||||
|
[54.825351, "o", "\u001b[38;2;254;68;60mo\u001b[39m\u001b[38;2;254;57;71mc\u001b[39m"]
|
||||||
|
[54.825374, "o", "\u001b[38;2;253;47;83mk\u001b[39m"]
|
||||||
|
[54.825398, "o", "\u001b[38;2;250;38;95me\u001b[39m"]
|
||||||
|
[54.825502, "o", "\u001b[38;2;246;29;107mr\u001b[39m\u001b[38;2;241;22;120m-\u001b[39m\u001b[38;2;235;15;132mc\u001b[39m"]
|
||||||
|
[54.82557, "o", "\u001b[38;2;228;10;145mo\u001b[39m\u001b[38;2;219;6;158mm\u001b[39m"]
|
||||||
|
[54.825634, "o", "\u001b[38;2;210;3;170mp\u001b[39m\u001b[38;2;200;1;182mo\u001b[39m"]
|
||||||
|
[54.825699, "o", "\u001b[38;2;189;1;193ms\u001b[39m\u001b[38;2;178;1;203me\u001b[39m"]
|
||||||
|
[54.825832, "o", "\u001b[38;2;166;3;213m.\u001b[39m"]
|
||||||
|
[54.825889, "o", "\u001b[38;2;154;7;222my\u001b[39m"]
|
||||||
|
[54.825917, "o", "\u001b[38;2;141;11;230mm\u001b[39m"]
|
||||||
|
[54.825938, "o", "\u001b[38;2;129;17;237ml\u001b[39m"]
|
||||||
|
[54.826017, "o", "\u001b[38;2;116;24;243m\u001b[39m\r\n"]
|
||||||
|
[54.826105, "o", "\u001b[38;2;69;59;254m2\u001b[39m\u001b[38;2;58;70;254m8\u001b[39m"]
|
||||||
|
[54.826172, "o", "\u001b[38;2;48;81;253m8\u001b[39m\u001b[38;2;39;93;251mb\u001b[39m"]
|
||||||
|
[54.826245, "o", "\u001b[38;2;30;106;247m0\u001b[39m\u001b[38;2;22;118;242me\u001b[39m"]
|
||||||
|
[54.826317, "o", "\u001b[38;2;16;131;236m"]
|
||||||
|
[54.826382, "o", "4\u001b[39m\u001b[38;2;10;144;228md\u001b[39m"]
|
||||||
|
[54.826442, "o", "\u001b[38;2;6;156;220mb\u001b[39m"]
|
||||||
|
[54.826501, "o", "\u001b[38;2;3;168;211m3\u001b[39m\u001b[38;2;1;180;201m2\u001b[39m\u001b[38;2;1;191;191m1\u001b[39m"]
|
||||||
|
[54.826559, "o", "\u001b[38;2;1;202;179mb\u001b[39m"]
|
||||||
|
[54.826618, "o", "\u001b[38;2;3;212;167m8\u001b[39m"]
|
||||||
|
[54.826676, "o", "\u001b[38;2;6;221;155m3\u001b[39m\u001b[38;2;11;229;143mb\u001b[39m"]
|
||||||
|
[54.826734, "o", "\u001b[38;2;16;236;130m0\u001b[39m\u001b[38;2;23;242;117m1\u001b[39m\u001b[38;2;31;247;105m2"]
|
||||||
|
[54.826792, "o", "\u001b[39m\u001b[38;2;39;251;92m6"]
|
||||||
|
[54.826849, "o", "\u001b[39m\u001b[38;2;49;253;80m3\u001b[39m\u001b[38;2;59;254;69m0\u001b[39m"]
|
||||||
|
[54.826908, "o", "\u001b[38;2;70;254;58md\u001b[39m"]
|
||||||
|
[54.826965, "o", "\u001b[38;2;82;253;48m1\u001b[39m\u001b[38;2;94;250;38md\u001b[39m"]
|
||||||
|
[54.827023, "o", "\u001b[38;2;106;246;30md\u001b[39m\u001b[38;2;119;241;22m3\u001b[39m"]
|
||||||
|
[54.827081, "o", "\u001b[38;2;132;235;15m7\u001b[39m"]
|
||||||
|
[54.82714, "o", "\u001b[38;2;144;228;10mb\u001b[39m\u001b[38;2;157;220;6me\u001b[39m"]
|
||||||
|
[54.827212, "o", "\u001b[38;2;169;211;3m2\u001b[39m"]
|
||||||
|
[54.827282, "o", "\u001b[38;2;181;201;1m3\u001b[39m"]
|
||||||
|
[54.827347, "o", "\u001b[38;2;192;190;1m9\u001b[39m\u001b[38;2;203;179;1m9\u001b[39m\u001b[38;2;213;167;3ma\u001b[39m"]
|
||||||
|
[54.827406, "o", "\u001b[38;2;222;154;7m8\u001b[39m"]
|
||||||
|
[54.827466, "o", "\u001b[38;2;230;142;11m9\u001b[39m\u001b[38;2;237;129;17m6\u001b[39m"]
|
||||||
|
[54.827525, "o", "\u001b[38;2;243;117;23m4\u001b[39m\u001b[38;2;247;104;31m7\u001b[39m"]
|
||||||
|
[54.827584, "o", "\u001b[38;2;251;92;40m \u001b[39m"]
|
||||||
|
[54.827643, "o", "\u001b[38;2;253;80;50m \u001b[39m"]
|
||||||
|
[54.827701, "o", "\u001b[38;2;254;68;60m.\u001b[39m\u001b[38;2;254;57;71m/\u001b[39m"]
|
||||||
|
[54.827762, "o", "\u001b[38;2;253;47;83me\u001b[39m\u001b[38;2;250;38;95mx\u001b[39m"]
|
||||||
|
[54.827821, "o", "\u001b[38;2;246;29;107ma\u001b[39m\u001b[38;2;241;22;120mm"]
|
||||||
|
[54.827881, "o", "\u001b[39m\u001b[38;2;235;15;132mp\u001b[39m\u001b[38;2;228;10;145m"]
|
||||||
|
[54.82794, "o", "l\u001b[39m\u001b[38;2;219;6;158m"]
|
||||||
|
[54.827998, "o", "e\u001b[39m\u001b[38;2;210;3;170m.\u001b[39m\u001b[38;2;200;1;182mc"]
|
||||||
|
[54.828058, "o", "\u001b[39m\u001b[38;2;189;1;193ma\u001b[39m"]
|
||||||
|
[54.828118, "o", "\u001b[38;2;178;1;203ms\u001b[39m"]
|
||||||
|
[54.82864, "o", "\u001b[38;2;166;3;213mt\u001b[39m"]
|
||||||
|
[54.828711, "o", "\u001b[38;2;154;7;222m\u001b[39m\r\n"]
|
||||||
|
[54.828773, "o", "\u001b[38;2;39;93;251m5\u001b[39m"]
|
||||||
|
[54.828835, "o", "\u001b[38;2;30;106;247md\u001b[39m\u001b[38;2;22;118;242m5"]
|
||||||
|
[54.828897, "o", "\u001b[39m\u001b[38;2;16;131;236m1\u001b[39m\u001b[38;2;10;144;228md\u001b[39m"]
|
||||||
|
[54.828954, "o", "\u001b[38;2;6;156;220m3\u001b[39m"]
|
||||||
|
[54.829012, "o", "\u001b[38;2;3;168;211m9\u001b[39m"]
|
||||||
|
[54.829075, "o", "\u001b[38;2;1;180;201m8\u001b[39m\u001b[38;2;1;191;191mf\u001b[39m"]
|
||||||
|
[54.829137, "o", "\u001b[38;2;1;202;179m4\u001b[39m"]
|
||||||
|
[54.829213, "o", "\u001b[38;2;3;212;167m7\u001b[39m\u001b[38;2;6;221;155m1\u001b[39m"]
|
||||||
|
[54.829279, "o", "\u001b[38;2;11;229;143md\u001b[39m"]
|
||||||
|
[54.829412, "o", "\u001b[38;2;16;236;130m8\u001b[39m"]
|
||||||
|
[54.829498, "o", "\u001b[38;2;23;242;117ma\u001b[39m"]
|
||||||
|
[54.829565, "o", "\u001b[38;2;31;247;105ma\u001b[39m"]
|
||||||
|
[54.829626, "o", "\u001b[38;2;39;251;92me\u001b[39m"]
|
||||||
|
[54.829695, "o", "\u001b[38;2;49;253;80m2\u001b[39m\u001b[38;2;59;254;69m7\u001b[39m"]
|
||||||
|
[54.829729, "o", "\u001b[38;2;70;254;58mf\u001b[39m\u001b[38;2;82;253;48m0\u001b[39m"]
|
||||||
|
[54.829814, "o", "\u001b[38;2;94;250;38m0\u001b[39m"]
|
||||||
|
[54.829875, "o", "\u001b[38;2;106;246;30m8\u001b[39m\u001b[38;2;119;241;22mf\u001b[39m\u001b[38;2;132;235;15mf\u001b[39m"]
|
||||||
|
[54.829931, "o", "\u001b[38;2;144;228;10m9\u001b[39m\u001b[38;2;157;220;6m3\u001b[39m"]
|
||||||
|
[54.829981, "o", "\u001b[38;2;169;211;3m8\u001b[39m"]
|
||||||
|
[54.830032, "o", "\u001b[38;2;181;201;1m1\u001b[39m"]
|
||||||
|
[54.830082, "o", "\u001b[38;2;192;190;1m8\u001b[39m\u001b[38;2;203;179;1md\u001b[39m"]
|
||||||
|
[54.830141, "o", "\u001b[38;2;213;167;3m2\u001b[39m\u001b[38;2;222;154;7mc"]
|
||||||
|
[54.830201, "o", "\u001b[39m\u001b[38;2;230;142;11m4\u001b[39m\u001b[38;2;237;129;17m5\u001b[39m"]
|
||||||
|
[54.830254, "o", "\u001b[38;2;243;117;23m6\u001b[39m"]
|
||||||
|
[54.830316, "o", "\u001b[38;2;247;104;31m5\u001b[39m\u001b[38;2;251;92;40md\u001b[39m"]
|
||||||
|
[54.830371, "o", "\u001b[38;2;253;80;50m6\u001b[39m"]
|
||||||
|
[54.830401, "o", "\u001b[38;2;254;68;60m9\u001b[39m"]
|
||||||
|
[54.83049, "o", "\u001b[38;2;254;57;71m \u001b[39m\u001b[38;2;253;47;83m \u001b[39m\u001b[38;2;250;38;95m."]
|
||||||
|
[54.830522, "o", "\u001b[39m"]
|
||||||
|
[54.830611, "o", "\u001b[38;2;246;29;107m/\u001b[39m\u001b[38;2;241;22;120me\u001b[39m\u001b[38;2;235;15;132mx"]
|
||||||
|
[54.830665, "o", "\u001b[39m\u001b[38;2;228;10;145ma\u001b[39m"]
|
||||||
|
[54.830719, "o", "\u001b[38;2;219;6;158mm\u001b[39m"]
|
||||||
|
[54.830767, "o", "\u001b[38;2;210;3;170mp\u001b[39m"]
|
||||||
|
[54.830816, "o", "\u001b[38;2;200;1;182ml\u001b[39m\u001b[38;2;189;1;193me"]
|
||||||
|
[54.830869, "o", "\u001b[39m\u001b[38;2;178;1;203m.\u001b[39m\u001b[38;2;166;3;213mc\u001b[39m"]
|
||||||
|
[54.830919, "o", "\u001b[38;2;154;7;222ma\u001b[39m"]
|
||||||
|
[54.830972, "o", "\u001b[38;2;141;11;230ms\u001b[39m"]
|
||||||
|
[54.831023, "o", "\u001b[38;2;129;17;237mt\u001b[39m\u001b[38;2;116;24;243m.\u001b[39m"]
|
||||||
|
[54.831079, "o", "\u001b[38;2;103;32;248mi\u001b[39m"]
|
||||||
|
[54.831107, "o", "\u001b[38;2;91;40;251mm\u001b[39m"]
|
||||||
|
[54.831169, "o", "\u001b[38;2;79;50;253mp\u001b[39m\u001b[38;2;68;61;254m"]
|
||||||
|
[54.831239, "o", "o\u001b[39m\u001b[38;2;57;72;254mr\u001b[39m\u001b[38;2;46;83;253mt\u001b[39m"]
|
||||||
|
[54.831306, "o", "\u001b[38;2;37;95;250m\u001b[39m\r\n"]
|
||||||
|
[54.831393, "o", "\u001b[38;2;16;131;236mf\u001b[39m"]
|
||||||
|
[54.83146, "o", "\u001b[38;2;10;144;228m5\u001b[39m"]
|
||||||
|
[54.831523, "o", "\u001b[38;2;6;156;220m7\u001b[39m\u001b[38;2;3;168;211ma\u001b[39m"]
|
||||||
|
[54.831583, "o", "\u001b[38;2;1;180;201m3\u001b[39m\u001b[38;2;1;191;191m5\u001b[39m"]
|
||||||
|
[54.831645, "o", "\u001b[38;2;1;202;179me\u001b[39m"]
|
||||||
|
[54.831696, "o", "\u001b[38;2;3;212;167m0\u001b[39m\u001b[38;2;6;221;155md\u001b[39m"]
|
||||||
|
[54.831747, "o", "\u001b[38;2;11;229;143ma\u001b[39m"]
|
||||||
|
[54.831797, "o", "\u001b[38;2;16;236;130m6\u001b[39m"]
|
||||||
|
[54.831848, "o", "\u001b[38;2;23;242;117m2\u001b[39m\u001b[38;2;31;247;105m5\u001b[39m"]
|
||||||
|
[54.831898, "o", "\u001b[38;2;39;251;92m9\u001b[39m"]
|
||||||
|
[54.831948, "o", "\u001b[38;2;49;253;80m2\u001b[39m"]
|
||||||
|
[54.831999, "o", "\u001b[38;2;59;254;69md\u001b[39m\u001b[38;2;70;254;58me\u001b[39m"]
|
||||||
|
[54.832049, "o", "\u001b[38;2;82;253;48m5\u001b[39m"]
|
||||||
|
[54.8321, "o", "\u001b[38;2;94;250;38ma\u001b[39m"]
|
||||||
|
[54.832149, "o", "\u001b[38;2;106;246;30m0\u001b[39m"]
|
||||||
|
[54.8322, "o", "\u001b[38;2;119;241;22m7\u001b[39m\u001b[38;2;132;235;15m6\u001b[39m\u001b[38;2;144;228;10ma\u001b[39m"]
|
||||||
|
[54.832265, "o", "\u001b[38;2;157;220;6m5\u001b[39m"]
|
||||||
|
[54.832324, "o", "\u001b[38;2;169;211;3m8\u001b[39m"]
|
||||||
|
[54.832371, "o", "\u001b[38;2;181;201;1m1\u001b[39m"]
|
||||||
|
[54.832421, "o", "\u001b[38;2;192;190;1m1\u001b[39m\u001b[38;2;203;179;1m9\u001b[39m"]
|
||||||
|
[54.832469, "o", "\u001b[38;2;213;167;3m0\u001b[39m"]
|
||||||
|
[54.832518, "o", "\u001b[38;2;222;154;7m4\u001b[39m"]
|
||||||
|
[54.832565, "o", "\u001b[38;2;230;142;11m5\u001b[39m\u001b[38;2;237;129;17md\u001b[39m"]
|
||||||
|
[54.832614, "o", "\u001b[38;2;243;117;23m2\u001b[39m"]
|
||||||
|
[54.832665, "o", "\u001b[38;2;247;104;31m4\u001b[39m\u001b[38;2;251;92;40m9\u001b[39m"]
|
||||||
|
[54.832733, "o", "\u001b[38;2;253;80;50m0\u001b[39m"]
|
||||||
|
[54.832783, "o", "\u001b[38;2;254;68;60m8\u001b[39m\u001b[38;2;254;57;71m9\u001b[39m"]
|
||||||
|
[54.832831, "o", "\u001b[38;2;253;47;83m1\u001b[39m"]
|
||||||
|
[54.83288, "o", "\u001b[38;2;250;38;95m9\u001b[39m"]
|
||||||
|
[54.832927, "o", "\u001b[38;2;246;29;107m \u001b[39m\u001b[38;2;241;22;120m \u001b[39m"]
|
||||||
|
[54.832975, "o", "\u001b[38;2;235;15;132m.\u001b[39m"]
|
||||||
|
[54.833023, "o", "\u001b[38;2;228;10;145m/\u001b[39m"]
|
||||||
|
[54.833121, "o", "\u001b[38;2;219;6;158mi\u001b[39m"]
|
||||||
|
[54.83321, "o", "\u001b[38;2;210;3;170mc\u001b[39m"]
|
||||||
|
[54.833278, "o", "\u001b[38;2;200;1;182mo\u001b[39m\u001b[38;2;189;1;193mn\u001b[39m"]
|
||||||
|
[54.83331, "o", "\u001b[38;2;178;1;203m.\u001b[39m"]
|
||||||
|
[54.833363, "o", "\u001b[38;2;166;3;213mp\u001b[39m"]
|
||||||
|
[54.833433, "o", "\u001b[38;2;154;7;222mn\u001b[39m\u001b[38;2;141;11;230mg\u001b[39m\u001b[38;2;129;17;237m\u001b[39m"]
|
||||||
|
[54.833487, "o", "\r\n"]
|
||||||
|
[54.833545, "o", "\u001b[38;2;3;168;211md\u001b[39m"]
|
||||||
|
[54.833605, "o", "\u001b[38;2;1;180;201m8\u001b[39m"]
|
||||||
|
[54.833658, "o", "\u001b[38;2;1;191;191ma\u001b[39m"]
|
||||||
|
[54.833717, "o", "\u001b[38;2;1;202;179m1\u001b[39m\u001b[38;2;3;212;167m0\u001b[39m"]
|
||||||
|
[54.833786, "o", "\u001b[38;2;6;221;155me\u001b[39m"]
|
||||||
|
[54.833864, "o", "\u001b[38;2;11;229;143m8\u001b[39m"]
|
||||||
|
[54.833928, "o", "\u001b[38;2;16;236;130m5\u001b[39m\u001b[38;2;23;242;117m7\u001b[39m"]
|
||||||
|
[54.833993, "o", "\u001b[38;2;31;247;105m1\u001b[39m"]
|
||||||
|
[54.834054, "o", "\u001b[38;2;39;251;92mb\u001b[39m\u001b[38;2;49;253;80m7\u001b[39m"]
|
||||||
|
[54.834111, "o", "\u001b[38;2;59;254;69m8\u001b[39m\u001b[38;2;70;254;58m9\u001b[39m"]
|
||||||
|
[54.834177, "o", "\u001b[38;2;82;253;48mb\u001b[39m"]
|
||||||
|
[54.834256, "o", "\u001b[38;2;94;250;38mc\u001b[39m\u001b[38;2;106;246;30m7\u001b[39m"]
|
||||||
|
[54.834328, "o", "\u001b[38;2;119;241;22ma\u001b[39m\u001b[38;2;132;235;15mc"]
|
||||||
|
[54.834387, "o", "\u001b[39m"]
|
||||||
|
[54.834938, "o", "\u001b[38;2;144;228;10m0\u001b[39m"]
|
||||||
|
[54.83501, "o", "\u001b[38;2;157;220;6m9\u001b[39m\u001b[38;2;169;211;3mb\u001b[39m"]
|
||||||
|
[54.83508, "o", "\u001b[38;2;181;201;1ma\u001b[39m\u001b[38;2;192;190;1me\u001b[39m\u001b[38;2;203;179;1m"]
|
||||||
|
[54.835137, "o", "2\u001b[39m\u001b[38;2;213;167;3mc\u001b[39m"]
|
||||||
|
[54.835222, "o", "\u001b[38;2;222;154;7m8\u001b[39m\u001b[38;2;230;142;11m"]
|
||||||
|
[54.835296, "o", "e\u001b[39m\u001b[38;2;237;129;17me\u001b[39m\u001b[38;2;243;117;23m1\u001b[39m"]
|
||||||
|
[54.835365, "o", "\u001b[38;2;247;104;31m2\u001b[39m\u001b[38;2;251;92;40m"]
|
||||||
|
[54.835432, "o", "3\u001b[39m\u001b[38;2;253;80;50m6\u001b[39m"]
|
||||||
|
[54.835485, "o", "\u001b[38;2;254;68;60ma\u001b[39m\u001b[38;2;254;57;71m2\u001b[39m"]
|
||||||
|
[54.835546, "o", "\u001b[38;2;253;47;83mf\u001b[39m\u001b[38;2;250;38;95m"]
|
||||||
|
[54.835612, "o", "a\u001b[39m\u001b[38;2;246;29;107mc\u001b[39m"]
|
||||||
|
[54.835676, "o", "\u001b[38;2;241;22;120ma\u001b[39m\u001b[38;2;235;15;132ma\u001b[39m"]
|
||||||
|
[54.835731, "o", "\u001b[38;2;228;10;145m \u001b[39m\u001b[38;2;219;6;158m \u001b[39m"]
|
||||||
|
[54.835791, "o", "\u001b[38;2;210;3;170m.\u001b[39m"]
|
||||||
|
[54.835858, "o", "\u001b[38;2;200;1;182m/\u001b[39m\u001b[38;2;189;1;193mi\u001b[39m"]
|
||||||
|
[54.835922, "o", "\u001b[38;2;178;1;203mc\u001b[39m\u001b[38;2;166;3;213mo\u001b[39m"]
|
||||||
|
[54.835974, "o", "\u001b[38;2;154;7;222mn\u001b[39m"]
|
||||||
|
[54.83603, "o", "\u001b[38;2;141;11;230m.\u001b[39m\u001b[38;2;129;17;237mp\u001b[39m"]
|
||||||
|
[54.836085, "o", "\u001b[38;2;116;24;243mn\u001b[39m"]
|
||||||
|
[54.836148, "o", "\u001b[38;2;103;32;248mg\u001b[39m\u001b[38;2;91;40;251m.\u001b[39m"]
|
||||||
|
[54.836213, "o", "\u001b[38;2;79;50;253mi\u001b[39m\u001b[38;2;68;61;254mm\u001b[39m"]
|
||||||
|
[54.83628, "o", "\u001b[38;2;57;72;254mp\u001b[39m\u001b[38;2;46;83;253mo\u001b[39m"]
|
||||||
|
[54.836353, "o", "\u001b[38;2;37;95;250mr\u001b[39m\u001b[38;2;29;108;246mt"]
|
||||||
|
[54.836421, "o", "\u001b[39m\u001b[38;2;21;120;241m"]
|
||||||
|
[54.836493, "o", "\u001b[39m\r\n"]
|
||||||
|
[54.836592, "o", "\u001b[38;2;1;202;179m5\u001b[39m"]
|
||||||
|
[54.836652, "o", "\u001b[38;2;3;212;167m2\u001b[39m"]
|
||||||
|
[54.836709, "o", "\u001b[38;2;6;221;155m0\u001b[39m\u001b[38;2;11;229;143mc\u001b[39m"]
|
||||||
|
[54.83677, "o", "\u001b[38;2;16;236;130m7\u001b[39m"]
|
||||||
|
[54.836841, "o", "\u001b[38;2;23;242;117m0\u001b[39m\u001b[38;2;31;247;105m8\u001b[39m"]
|
||||||
|
[54.836898, "o", "\u001b[38;2;39;251;92mb\u001b[39m"]
|
||||||
|
[54.836965, "o", "\u001b[38;2;49;253;80me\u001b[39m\u001b[38;2;59;254;69ma\u001b[39m"]
|
||||||
|
[54.837021, "o", "\u001b[38;2;70;254;58m1\u001b[39m"]
|
||||||
|
[54.837075, "o", "\u001b[38;2;82;253;48m5\u001b[39m"]
|
||||||
|
[54.837132, "o", "\u001b[38;2;94;250;38ma\u001b[39m"]
|
||||||
|
[54.837194, "o", "\u001b[38;2;106;246;30m1\u001b[39m\u001b[38;2;119;241;22mf\u001b[39m"]
|
||||||
|
[54.837257, "o", "\u001b[38;2;132;235;15m5\u001b[39m"]
|
||||||
|
[54.837331, "o", "\u001b[38;2;144;228;10ma\u001b[39m\u001b[38;2;157;220;6m2\u001b[39m"]
|
||||||
|
[54.837398, "o", "\u001b[38;2;169;211;3m7\u001b[39m\u001b[38;2;181;201;1mc\u001b[39m"]
|
||||||
|
[54.837465, "o", "\u001b[38;2;192;190;1ma\u001b[39m\u001b[38;2;203;179;1m0\u001b[39m"]
|
||||||
|
[54.83753, "o", "\u001b[38;2;213;167;3mb\u001b[39m\u001b[38;2;222;154;7m9"]
|
||||||
|
[54.837594, "o", "\u001b[39m\u001b[38;2;230;142;11md\u001b[39m"]
|
||||||
|
[54.83765, "o", "\u001b[38;2;237;129;17mf\u001b[39m\u001b[38;2;243;117;23ma\u001b[39m"]
|
||||||
|
[54.83771, "o", "\u001b[38;2;247;104;31m8\u001b[39m"]
|
||||||
|
[54.837767, "o", "\u001b[38;2;251;92;40m8\u001b[39m\u001b[38;2;253;80;50mc\u001b[39m"]
|
||||||
|
[54.837824, "o", "\u001b[38;2;254;68;60m7\u001b[39m\u001b[38;2;254;57;71mf\u001b[39m"]
|
||||||
|
[54.837888, "o", "\u001b[38;2;253;47;83m0\u001b[39m\u001b[38;2;250;38;95ma\u001b[39m"]
|
||||||
|
[54.837966, "o", "\u001b[38;2;246;29;107mc\u001b[39m\u001b[38;2;241;22;120m"]
|
||||||
|
[54.838041, "o", "0\u001b[39m\u001b[38;2;235;15;132m4\u001b[39m"]
|
||||||
|
[54.83811, "o", "\u001b[38;2;228;10;145me\u001b[39m"]
|
||||||
|
[54.838176, "o", "\u001b[38;2;219;6;158mb\u001b[39m\u001b[38;2;210;3;170m6\u001b[39m"]
|
||||||
|
[54.838241, "o", "\u001b[38;2;200;1;182m \u001b[39m\u001b[38;2;189;1;193m \u001b[39m"]
|
||||||
|
[54.83832, "o", "\u001b[38;2;178;1;203m.\u001b[39m\u001b[38;2;166;3;213m/\u001b[39m"]
|
||||||
|
[54.838353, "o", "\u001b[38;2;154;7;222mL\u001b[39m\u001b[38;2;141;11;230mI"]
|
||||||
|
[54.838418, "o", "\u001b[39m\u001b[38;2;129;17;237mC\u001b[39m"]
|
||||||
|
[54.838464, "o", "\u001b[38;2;116;24;243mE\u001b[39m\u001b[38;2;103;32;248mN"]
|
||||||
|
[54.838512, "o", "\u001b[39m\u001b[38;2;91;40;251mS\u001b[39m"]
|
||||||
|
[54.838572, "o", "\u001b[38;2;79;50;253mE\u001b[39m\u001b[38;2;68;61;254m\u001b[39m\r\n"]
|
||||||
|
[54.838665, "o", "\u001b[38;2;11;229;143m2\u001b[39m"]
|
||||||
|
[54.838718, "o", "\u001b[38;2;16;236;130mb\u001b[39m"]
|
||||||
|
[54.838787, "o", "\u001b[38;2;23;242;117m9\u001b[39m\u001b[38;2;31;247;105me\u001b[39m"]
|
||||||
|
[54.838987, "o", "\u001b[38;2;39;251;92m7\u001b[39m"]
|
||||||
|
[54.839081, "o", "\u001b[38;2;49;253;80mf\u001b[39m"]
|
||||||
|
[54.839181, "o", "\u001b[38;2;59;254;69m6\u001b[39m"]
|
||||||
|
[54.839246, "o", "\u001b[38;2;70;254;58m0\u001b[39m\u001b[38;2;82;253;48m6\u001b[39m"]
|
||||||
|
[54.839312, "o", "\u001b[38;2;94;250;38mf\u001b[39m\u001b[38;2;106;246;30m9\u001b[39m"]
|
||||||
|
[54.839376, "o", "\u001b[38;2;119;241;22m5\u001b[39m"]
|
||||||
|
[54.839429, "o", "\u001b[38;2;132;235;15mc\u001b[39m\u001b[38;2;144;228;10m5\u001b[39m"]
|
||||||
|
[54.839482, "o", "\u001b[38;2;157;220;6me\u001b[39m\u001b[38;2;169;211;3m"]
|
||||||
|
[54.839535, "o", "c\u001b[39m\u001b[38;2;181;201;1m6\u001b[39m"]
|
||||||
|
[54.839587, "o", "\u001b[38;2;192;190;1m9\u001b[39m"]
|
||||||
|
[54.839637, "o", "\u001b[38;2;203;179;1md\u001b[39m\u001b[38;2;213;167;3m7\u001b[39m"]
|
||||||
|
[54.839688, "o", "\u001b[38;2;222;154;7m9\u001b[39m"]
|
||||||
|
[54.839738, "o", "\u001b[38;2;230;142;11mc\u001b[39m"]
|
||||||
|
[54.839787, "o", "\u001b[38;2;237;129;17md\u001b[39m\u001b[38;2;243;117;23mc\u001b[39m"]
|
||||||
|
[54.839842, "o", "\u001b[38;2;247;104;31m4\u001b[39m"]
|
||||||
|
[54.839885, "o", "\u001b[38;2;251;92;40m1\u001b[39m"]
|
||||||
|
[54.839941, "o", "\u001b[38;2;253;80;50m3\u001b[39m\u001b[38;2;254;68;60mb\u001b[39m"]
|
||||||
|
[54.83999, "o", "\u001b[38;2;254;57;71m0\u001b[39m"]
|
||||||
|
[54.840043, "o", "\u001b[38;2;253;47;83mb\u001b[39m\u001b[38;2;250;38;95m0\u001b[39m"]
|
||||||
|
[54.840089, "o", "\u001b[38;2;246;29;107md\u001b[39m"]
|
||||||
|
[54.840151, "o", "\u001b[38;2;241;22;120m9\u001b[39m\u001b[38;2;235;15;132mf"]
|
||||||
|
[54.840196, "o", "\u001b[39m\u001b[38;2;228;10;145ma\u001b[39m"]
|
||||||
|
[54.840245, "o", "\u001b[38;2;219;6;158m0\u001b[39m"]
|
||||||
|
[54.840306, "o", "\u001b[38;2;210;3;170me\u001b[39m"]
|
||||||
|
[54.840357, "o", "\u001b[38;2;200;1;182m8\u001b[39m\u001b[38;2;189;1;193m8\u001b[39m"]
|
||||||
|
[54.840409, "o", "\u001b[38;2;178;1;203ma\u001b[39m"]
|
||||||
|
[54.840458, "o", "\u001b[38;2;166;3;213m \u001b[39m\u001b[38;2;154;7;222m \u001b[39m"]
|
||||||
|
[54.840507, "o", "\u001b[38;2;141;11;230m.\u001b[39m"]
|
||||||
|
[54.840558, "o", "\u001b[38;2;129;17;237m/\u001b[39m"]
|
||||||
|
[54.840609, "o", "\u001b[38;2;116;24;243mn\u001b[39m\u001b[38;2;103;32;248me\u001b[39m"]
|
||||||
|
[54.840662, "o", "\u001b[38;2;91;40;251mw\u001b[39m"]
|
||||||
|
[54.840709, "o", "\u001b[38;2;79;50;253m.\u001b[39m\u001b[38;2;68;61;254m"]
|
||||||
|
[54.840762, "o", "c\u001b[39m"]
|
||||||
|
[54.841327, "o", "\u001b[38;2;57;72;254ma\u001b[39m"]
|
||||||
|
[54.841424, "o", "\u001b[38;2;46;83;253ms\u001b[39m\u001b[38;2;37;95;250mt\u001b[39m\u001b[38;2;29;108;246m\u001b[39m\r\n"]
|
||||||
|
[54.841493, "o", "\u001b[38;2;31;247;105mb\u001b[39m\u001b[38;2;39;251;92mb\u001b[39m"]
|
||||||
|
[54.841552, "o", "\u001b[38;2;49;253;80m9\u001b[39m"]
|
||||||
|
[54.841607, "o", "\u001b[38;2;59;254;69me\u001b[39m\u001b[38;2;70;254;58m2\u001b[39m"]
|
||||||
|
[54.841663, "o", "\u001b[38;2;82;253;48ma\u001b[39m"]
|
||||||
|
[54.841719, "o", "\u001b[38;2;94;250;38ma\u001b[39m\u001b[38;2;106;246;30m7\u001b[39m"]
|
||||||
|
[54.841779, "o", "\u001b[38;2;119;241;22m9\u001b[39m"]
|
||||||
|
[54.841812, "o", "\u001b[38;2;132;235;15ma\u001b[39m\u001b[38;2;144;228;10m6\u001b[39m"]
|
||||||
|
[54.841885, "o", "\u001b[38;2;157;220;6ma\u001b[39m"]
|
||||||
|
[54.841945, "o", "\u001b[38;2;169;211;3m6\u001b[39m\u001b[38;2;181;201;1mc\u001b[39m"]
|
||||||
|
[54.842006, "o", "\u001b[38;2;192;190;1m9\u001b[39m"]
|
||||||
|
[54.842066, "o", "\u001b[38;2;203;179;1m4\u001b[39m\u001b[38;2;213;167;3m"]
|
||||||
|
[54.842122, "o", "d\u001b[39m\u001b[38;2;222;154;7m4\u001b[39m"]
|
||||||
|
[54.842176, "o", "\u001b[38;2;230;142;11m4\u001b[39m"]
|
||||||
|
[54.842263, "o", "\u001b[38;2;237;129;17m6\u001b[39m\u001b[38;2;243;117;23m0\u001b[39m"]
|
||||||
|
[54.842396, "o", "\u001b[38;2;247;104;31m8\u001b[39m"]
|
||||||
|
[54.842476, "o", "\u001b[38;2;251;92;40m4\u001b[39m"]
|
||||||
|
[54.842562, "o", "\u001b[38;2;253;80;50m1\u001b[39m\u001b[38;2;254;68;60me\u001b[39m"]
|
||||||
|
[54.842659, "o", "\u001b[38;2;254;57;71m0\u001b[39m\u001b[38;2;253;47;83m5\u001b[39m"]
|
||||||
|
[54.842742, "o", "\u001b[38;2;250;38;95m3\u001b[39m\u001b[38;2;246;29;107m9\u001b[39m"]
|
||||||
|
[54.842848, "o", "\u001b[38;2;241;22;120m4\u001b[39m"]
|
||||||
|
[54.842933, "o", "\u001b[38;2;235;15;132m8\u001b[39m\u001b[38;2;228;10;145m4\u001b[39m\u001b[38;2;219;6;158me\u001b[39m"]
|
||||||
|
[54.843016, "o", "\u001b[38;2;210;3;170md\u001b[39m\u001b[38;2;200;1;182mc\u001b[39m\u001b[38;2;189;1;193m0\u001b[39m"]
|
||||||
|
[54.843101, "o", "\u001b[38;2;178;1;203m5\u001b[39m\u001b[38;2;166;3;213mf\u001b[39m\u001b[38;2;154;7;222ma\u001b[39m"]
|
||||||
|
[54.843189, "o", "\u001b[38;2;141;11;230m5\u001b[39m\u001b[38;2;129;17;237m \u001b[39m\u001b[38;2;116;24;243m \u001b[39m"]
|
||||||
|
[54.843298, "o", "\u001b[38;2;103;32;248m.\u001b[39m\u001b[38;2;91;40;251m/\u001b[39m"]
|
||||||
|
[54.843338, "o", "\u001b[38;2;79;50;253mp\u001b[39m\u001b[38;2;68;61;254mr\u001b[39m"]
|
||||||
|
[54.843438, "o", "\u001b[38;2;57;72;254mo\u001b[39m\u001b[38;2;46;83;253mj\u001b[39m\u001b[38;2;37;95;250me\u001b[39m"]
|
||||||
|
[54.843511, "o", "\u001b[38;2;29;108;246mc\u001b[39m\u001b[38;2;21;120;241mt\u001b[39m\u001b[38;2;15;133;235m.\u001b[39m"]
|
||||||
|
[54.843584, "o", "\u001b[38;2;10;146;227mg\u001b[39m\u001b[38;2;5;158;219mo\u001b[39m\u001b[38;2;3;170;210md"]
|
||||||
|
[54.843652, "o", "\u001b[39m\u001b[38;2;1;182;199mo\u001b[39m\u001b[38;2;1;193;189mt\u001b[39m"]
|
||||||
|
[54.843723, "o", "\u001b[38;2;1;204;177m\u001b[39m\r\n"]
|
||||||
|
[54.843797, "o", "\u001b[38;2;59;254;69m3\u001b[39m"]
|
||||||
|
[54.84387, "o", "\u001b[38;2;70;254;58ma\u001b[39m\u001b[38;2;82;253;48m8\u001b[39m\u001b[38;2;94;250;38m3"]
|
||||||
|
[54.843944, "o", "\u001b[39m\u001b[38;2;106;246;30m0\u001b[39m\u001b[38;2;119;241;22m0\u001b[39m"]
|
||||||
|
[54.844009, "o", "\u001b[38;2;132;235;15m5\u001b[39m\u001b[38;2;144;228;10ma\u001b[39m"]
|
||||||
|
[54.844071, "o", "\u001b[38;2;157;220;6m5\u001b[39m\u001b[38;2;169;211;3md\u001b[39m"]
|
||||||
|
[54.844155, "o", "\u001b[38;2;181;201;1mc\u001b[39m\u001b[38;2;192;190;1m8\u001b[39m"]
|
||||||
|
[54.844245, "o", "\u001b[38;2;203;179;1mb\u001b[39m\u001b[38;2;213;167;3ma\u001b[39m\u001b[38;2;222;154;7m5"]
|
||||||
|
[54.844341, "o", "\u001b[39m\u001b[38;2;230;142;11md\u001b[39m\u001b[38;2;237;129;17m0\u001b[39m\u001b[38;2;243;117;23mf\u001b[39m\u001b[38;2;247;104;31m0\u001b[39m"]
|
||||||
|
[54.844424, "o", "\u001b[38;2;251;92;40ma\u001b[39m\u001b[38;2;253;80;50mb\u001b[39m"]
|
||||||
|
[54.844495, "o", "\u001b[38;2;254;68;60mb\u001b[39m\u001b[38;2;254;57;71m3\u001b[39m"]
|
||||||
|
[54.844563, "o", "\u001b[38;2;253;47;83md\u001b[39m\u001b[38;2;250;38;95me\u001b[39m"]
|
||||||
|
[54.844639, "o", "\u001b[38;2;246;29;107m8\u001b[39m\u001b[38;2;241;22;120m4\u001b[39m\u001b[38;2;235;15;132m7\u001b[39m\u001b[38;2;228;10;145md\u001b[39m"]
|
||||||
|
[54.844728, "o", "\u001b[38;2;219;6;158m2\u001b[39m\u001b[38;2;210;3;170md\u001b[39m"]
|
||||||
|
[54.844818, "o", "\u001b[38;2;200;1;182me\u001b[39m\u001b[38;2;189;1;193m0\u001b[39m\u001b[38;2;178;1;203ma\u001b[39m"]
|
||||||
|
[54.844893, "o", "\u001b[38;2;166;3;213m4\u001b[39m\u001b[38;2;154;7;222m6\u001b[39m\u001b[38;2;141;11;230md\u001b[39m\u001b[38;2;129;17;237m7\u001b[39m"]
|
||||||
|
[54.84499, "o", "\u001b[38;2;116;24;243m7\u001b[39m\u001b[38;2;103;32;248mb\u001b[39m\u001b[38;2;91;40;251m \u001b[39m"]
|
||||||
|
[54.845083, "o", "\u001b[38;2;79;50;253m \u001b[39m\u001b[38;2;68;61;254m.\u001b[39m\u001b[38;2;57;72;254m/\u001b[39m\u001b[38;2;46;83;253mR\u001b[39m\u001b[38;2;37;95;250mE\u001b[39m"]
|
||||||
|
[54.845178, "o", "\u001b[38;2;29;108;246mA\u001b[39m\u001b[38;2;21;120;241mD\u001b[39m"]
|
||||||
|
[54.845256, "o", "\u001b[38;2;15;133;235mM\u001b[39m\u001b[38;2;10;146;227mE\u001b[39m"]
|
||||||
|
[54.845343, "o", "\u001b[38;2;5;158;219m.\u001b[39m\u001b[38;2;3;170;210mm\u001b[39m\u001b[38;2;1;182;199md\u001b[39m"]
|
||||||
|
[54.845422, "o", "\u001b[38;2;1;193;189m\u001b[39m\r\n"]
|
||||||
|
[54.845491, "o", "\u001b[m\u001b[?25h\u001b[?1;5;2004l"]
|
||||||
|
[54.847349, "o", "\u001b]2;laptop:leroy:~/projects/godot-xterm\u0007\r\r\n\u001b[1;32m[\u001b]0;leroy@laptop: ~/projects/godot-xterm\u0007leroy@laptop:~/projects/godot-xterm]$\u001b[0m "]
|
||||||
|
[57.064686, "o", "e"]
|
||||||
|
[57.230802, "o", "x"]
|
||||||
|
[59.010363, "o", "\b\u001b[K"]
|
||||||
|
[59.121216, "o", "\b\u001b[K"]
|
||||||
|
[59.456844, "o", "#"]
|
||||||
|
[59.676225, "o", "/"]
|
||||||
|
[60.10367, "o", "\b\u001b[K"]
|
||||||
|
[60.18748, "o", " "]
|
||||||
|
[60.4099, "o", "w"]
|
||||||
|
[60.748895, "o", "e"]
|
||||||
|
[60.992399, "o", "\b\u001b[K"]
|
||||||
|
[61.116881, "o", "\b\u001b[K"]
|
||||||
|
[61.313248, "o", "W"]
|
||||||
|
[61.473147, "o", "h"]
|
||||||
|
[61.562029, "o", "e"]
|
||||||
|
[61.645136, "o", "n"]
|
||||||
|
[61.917431, "o", " "]
|
||||||
|
[62.093406, "o", "w"]
|
||||||
|
[62.161239, "o", "e"]
|
||||||
|
[62.248416, "o", " "]
|
||||||
|
[62.33829, "o", "a"]
|
||||||
|
[62.415246, "o", "r"]
|
||||||
|
[62.507794, "o", "e"]
|
||||||
|
[62.557211, "o", " "]
|
||||||
|
[62.753875, "o", "f"]
|
||||||
|
[62.85347, "o", "i"]
|
||||||
|
[62.921221, "o", "n"]
|
||||||
|
[63.033374, "o", "i"]
|
||||||
|
[63.094372, "o", "s"]
|
||||||
|
[63.187799, "o", "h"]
|
||||||
|
[63.483077, "o", "e"]
|
||||||
|
[63.612519, "o", "d"]
|
||||||
|
[63.792416, "o", ","]
|
||||||
|
[63.894738, "o", " "]
|
||||||
|
[64.04963, "o", "j"]
|
||||||
|
[64.202261, "o", "u"]
|
||||||
|
[64.263783, "o", "s"]
|
||||||
|
[64.307216, "o", "t"]
|
||||||
|
[64.369715, "o", " "]
|
||||||
|
[64.492205, "o", "e"]
|
||||||
|
[64.653815, "o", "x"]
|
||||||
|
[64.746695, "o", "i"]
|
||||||
|
[64.858507, "o", "t"]
|
||||||
|
[65.103114, "o", " "]
|
||||||
|
[65.664488, "o", "t"]
|
||||||
|
[65.719435, "o", "h"]
|
||||||
|
[65.782418, "o", "e"]
|
||||||
|
[65.844266, "o", " "]
|
||||||
|
[65.963151, "o", "s"]
|
||||||
|
[66.037719, "o", "h"]
|
||||||
|
[66.121665, "o", "e"]
|
||||||
|
[66.224533, "o", "l"]
|
||||||
|
[66.323957, "o", "l"]
|
||||||
|
[66.562302, "o", "\r\n"]
|
||||||
|
[66.562831, "o", "\u001b]2;laptop:leroy:~/projects/godot-xterm\u0007\r\r\n\u001b[1;32m[\u001b]0;leroy@laptop: ~/projects/godot-xterm\u0007leroy@laptop:~/projects/godot-xterm]$\u001b[0m "]
|
||||||
|
[66.844263, "o", "e"]
|
||||||
|
[66.983977, "o", "x"]
|
||||||
|
[67.104686, "o", "i"]
|
||||||
|
[67.212146, "o", "t"]
|
||||||
|
[67.515156, "o", "\r\n"]
|
||||||
|
[67.515263, "o", "exit\r\n"]
|
||||||
|
[67.516389, "o", "\u001b[0;32masciinema: recording finished\u001b[0m\r\n\u001b[0;32masciinema: asciicast saved to new.cast\u001b[0m\r\n"]
|
||||||
|
[67.526166, "o", "sh-4.4$ "]
|
||||||
|
[69.107982, "o", "c"]
|
||||||
|
[69.201795, "o", "o"]
|
||||||
|
[69.306066, "o", "w"]
|
||||||
|
[69.520215, "o", "s"]
|
||||||
|
[69.638453, "o", "a"]
|
||||||
|
[69.696601, "o", "y"]
|
||||||
|
[70.376247, "o", " "]
|
||||||
|
[70.997599, "o", "A"]
|
||||||
|
[71.148845, "o", "l"]
|
||||||
|
[71.283482, "o", "l"]
|
||||||
|
[71.322607, "o", " "]
|
||||||
|
[71.823544, "o", "d"]
|
||||||
|
[71.910819, "o", "o"]
|
||||||
|
[72.005256, "o", "n"]
|
||||||
|
[72.059912, "o", "e"]
|
||||||
|
[72.234089, "o", "!"]
|
||||||
|
[72.62946, "o", "\r\n"]
|
||||||
|
[72.64376, "o", " ___________ \r\n< All done! >\r\n ----------- \r\n \\ ^__^\r\n \\ (oo)\\_______\r\n (__)\\ )\\/\\\r\n ||----w |\r\n || ||\r\n"]
|
||||||
|
[72.644144, "o", "sh-4.4$ "]
|
||||||
|
[73.525287, "o", "\r\n"]
|
||||||
|
[73.525434, "o", "sh-4.4$ "]
|
||||||
|
[74.180823, "o", "e"]
|
||||||
|
[74.345967, "o", "x"]
|
||||||
|
[74.476496, "o", "i"]
|
||||||
|
[74.626928, "o", "t"]
|
||||||
|
[75.019672, "o", "\r\nexit\r\n"]
|
||||||
|
|
149
examples/menu/menu.gd
Normal file
149
examples/menu/menu.gd
Normal file
|
@ -0,0 +1,149 @@
|
||||||
|
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 TITLE = """
|
||||||
|
░█▀▀░█▀█░█▀▄░█▀█░▀█▀░░░█░█░▀█▀░█▀▀░█▀▄░█▄█\r
|
||||||
|
░█░█░█░█░█░█░█░█░░█░░░░▄▀▄░░█░░█▀▀░█▀▄░█░█\r
|
||||||
|
░▀▀▀░▀▀▀░▀▀░░▀▀▀░░▀░░░░▀░▀░░▀░░▀▀▀░▀░▀░▀░▀\r
|
||||||
|
"""
|
||||||
|
const TITLE_WIDTH = 42
|
||||||
|
|
||||||
|
var menu_items := [
|
||||||
|
{ "name": "Asciicast", "scene": preload("../asciicast/asciicast.tscn") },
|
||||||
|
{ "name": "Terminal", "scene": 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():
|
||||||
|
# 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.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.cup(row, 0)
|
||||||
|
|
||||||
|
for line in TITLE.split("\r"):
|
||||||
|
row += 1
|
||||||
|
tput.cup(row, offset)
|
||||||
|
$Terminal.write(line)
|
||||||
|
|
||||||
|
# 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.cols / 2) - (item.name.length() / 2)))
|
||||||
|
|
||||||
|
tput.cup(row, offset)
|
||||||
|
|
||||||
|
if selected_index == i:
|
||||||
|
tput.setab(Color("#FF7500"))
|
||||||
|
tput.setaf(Color.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])
|
||||||
|
get_tree().get_root().add_child(scene)
|
||||||
|
visible = false
|
||||||
|
scene.grab_focus()
|
||||||
|
yield(animation_player, "animation_finished")
|
||||||
|
visible = true
|
||||||
|
get_tree().get_root().remove_child(scene)
|
||||||
|
$Terminal.grab_focus()
|
||||||
|
scene.queue_free()
|
||||||
|
"Terminal":
|
||||||
|
var scene = item.scene.instance()
|
||||||
|
var pty = scene.get_node("Pseudoterminal")
|
||||||
|
get_tree().get_root().add_child(scene)
|
||||||
|
visible = false
|
||||||
|
scene.grab_focus()
|
||||||
|
yield(pty, "exited")
|
||||||
|
visible = true
|
||||||
|
$Terminal.grab_focus()
|
||||||
|
scene.queue_free()
|
||||||
|
"Exit":
|
||||||
|
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")
|
28
examples/menu/menu.tscn
Normal file
28
examples/menu/menu.tscn
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
[gd_scene load_steps=4 format=2]
|
||||||
|
|
||||||
|
[ext_resource path="res://addons/godot_xterm/nodes/terminal/terminal.gdns" type="Script" id=1]
|
||||||
|
[ext_resource path="res://examples/menu/menu.gd" type="Script" id=2]
|
||||||
|
[ext_resource path="res://addons/godot_xterm/themes/default.theme" type="Theme" id=3]
|
||||||
|
|
||||||
|
[node name="Menu" type="Control"]
|
||||||
|
anchor_right = 1.0
|
||||||
|
anchor_bottom = 1.0
|
||||||
|
script = ExtResource( 2 )
|
||||||
|
__meta__ = {
|
||||||
|
"_edit_use_anchors_": false
|
||||||
|
}
|
||||||
|
|
||||||
|
[node name="Terminal" type="Control" parent="."]
|
||||||
|
anchor_right = 1.0
|
||||||
|
anchor_bottom = 1.0
|
||||||
|
focus_mode = 2
|
||||||
|
size_flags_horizontal = 3
|
||||||
|
size_flags_vertical = 3
|
||||||
|
theme = ExtResource( 3 )
|
||||||
|
script = ExtResource( 1 )
|
||||||
|
__meta__ = {
|
||||||
|
"_edit_use_anchors_": false
|
||||||
|
}
|
||||||
|
rows = 31
|
||||||
|
cols = 102
|
||||||
|
[connection signal="key_pressed" from="Terminal" to="." method="_on_Terminal_key_pressed"]
|
7
examples/terminal/Node.gd
Normal file
7
examples/terminal/Node.gd
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
extends Node
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
func _on_Terminal_key_pressed(event: InputEventKey, data: PoolByteArray):
|
||||||
|
print(data as Array)
|
||||||
|
print(event.scancode)
|
|
@ -8,15 +8,16 @@
|
||||||
anchor_right = 1.0
|
anchor_right = 1.0
|
||||||
anchor_bottom = 1.0
|
anchor_bottom = 1.0
|
||||||
focus_mode = 2
|
focus_mode = 2
|
||||||
size_flags_horizontal = 3
|
|
||||||
size_flags_vertical = 3
|
|
||||||
theme = ExtResource( 4 )
|
theme = ExtResource( 4 )
|
||||||
script = ExtResource( 1 )
|
script = ExtResource( 1 )
|
||||||
__meta__ = {
|
__meta__ = {
|
||||||
"_edit_use_anchors_": false
|
"_edit_use_anchors_": false
|
||||||
}
|
}
|
||||||
|
rows = 31
|
||||||
|
cols = 102
|
||||||
|
|
||||||
[node name="Pseudoterminal" type="Node" parent="."]
|
[node name="Pseudoterminal" type="Node" parent="."]
|
||||||
script = ExtResource( 2 )
|
script = ExtResource( 2 )
|
||||||
[connection signal="data_read" from="." to="Pseudoterminal" method="put_data"]
|
[connection signal="data_sent" from="." to="Pseudoterminal" method="write"]
|
||||||
[connection signal="data_received" from="Pseudoterminal" to="." method="write"]
|
[connection signal="size_changed" from="." to="Pseudoterminal" method="resize"]
|
||||||
|
[connection signal="data_sent" from="Pseudoterminal" to="." method="write"]
|
|
@ -10,23 +10,30 @@ config_version=4
|
||||||
|
|
||||||
_global_script_classes=[ {
|
_global_script_classes=[ {
|
||||||
"base": "Reference",
|
"base": "Reference",
|
||||||
"class": "ArrayUtils",
|
"class": "TPut",
|
||||||
"language": "GDScript",
|
"language": "GDScript",
|
||||||
"path": "res://addons/SIsilicon.3d.text/array_utils.gd"
|
"path": "res://addons/godot_xterm/util/tput.gd"
|
||||||
} ]
|
} ]
|
||||||
_global_script_class_icons={
|
_global_script_class_icons={
|
||||||
"ArrayUtils": ""
|
"TPut": ""
|
||||||
}
|
}
|
||||||
|
|
||||||
[application]
|
[application]
|
||||||
|
|
||||||
config/name="Godot Xterm"
|
config/name="Godot Xterm"
|
||||||
|
run/main_scene="res://examples/menu/menu.tscn"
|
||||||
config/icon="res://icon.png"
|
config/icon="res://icon.png"
|
||||||
|
|
||||||
|
[display]
|
||||||
|
|
||||||
|
window/vsync/use_vsync=false
|
||||||
|
|
||||||
[editor_plugins]
|
[editor_plugins]
|
||||||
|
|
||||||
enabled=PoolStringArray( "SIsilicon.3d.text", "godot_xterm" )
|
enabled=PoolStringArray( "godot_xterm" )
|
||||||
|
|
||||||
[rendering]
|
[rendering]
|
||||||
|
|
||||||
|
quality/filters/anisotropic_filter_level=16
|
||||||
|
quality/filters/msaa=4
|
||||||
environment/default_environment="res://default_env.tres"
|
environment/default_environment="res://default_env.tres"
|
||||||
|
|
Loading…
Reference in a new issue