feat(terminal): and stylebox support

Adds support for 'normal' and 'focus' Style Boxes to Terminal node.
Changes default background color to transparent, with background to be
set by StyleBox.

If background color is not transparent, will draw a background color
rect to cover the entire control over the top of any stylebox. This is
consistent with the behavior of the TextEdit node with regards to theme
colors and styleboxes.
This commit is contained in:
Leroy Hopson 2024-04-14 20:28:26 +12:00
parent a5951978f7
commit d6a4adf6aa
No known key found for this signature in database
GPG key ID: D2747312A6DB51AA
40 changed files with 608 additions and 52 deletions

View file

@ -27,5 +27,8 @@ test-all:
test-rendering:
{{godot}} --windowed --resolution 400x200 --position 0,0 -s addons/gut/gut_cmdln.gd -gtest=res://test/test_rendering.gd -gopacity=0 -gexit
test-visual:
{{godot}} --windowed --resolution 400x200 --position 0,0 -s addons/gut/gut_cmdln.gd -gdir=res://test/visual_regression/ -ginclude_subdirs=true -gopacity=0 -gexit
uninstall:
{{godot}} --headless -s plug.gd uninstall

View file

@ -22,6 +22,9 @@ func _ready():
if not editor_settings:
return
add_theme_stylebox_override("normal", get_theme_stylebox("normal", "Tree"))
add_theme_stylebox_override("focus", get_theme_stylebox("focus", "Tree"))
# Get colors from TextEdit theme. Created using the default (Adaptive) theme
# for reference, but will probably cause strange results if using another theme
# better to use a dedicated terminal theme, rather than relying on this.

View file

@ -1,7 +1,7 @@
[gd_scene load_steps=3 format=3 uid="uid://bkcyv0w3setep"]
[ext_resource type="Script" path="res://addons/godot_xterm/editor_plugins/terminal/editor_terminal.gd" id="1"]
[ext_resource type="Theme" uid="uid://0gk8swmcldbg" path="res://themes/demo.tres" id="1_h7osn"]
[ext_resource type="Theme" uid="uid://0gk8swmcldbg" path="res://themes/demo.tres" id="1_htj4w"]
[node name="Terminal" type="Terminal"]
anchors_preset = 15
@ -12,12 +12,12 @@ grow_vertical = 2
size_flags_horizontal = 4
size_flags_vertical = 4
focus_mode = 1
theme = ExtResource("1_h7osn")
theme = ExtResource("1_htj4w")
script = ExtResource("1")
[node name="PTY" type="PTY" parent="."]
cols = 128
rows = 32
cols = 126
rows = 31
terminal_path = NodePath("..")
[node name="Bell" type="AudioStreamPlayer" parent="."]

View file

@ -46,9 +46,6 @@ var _tab_container_min_size
func _ready():
tab_container.add_theme_stylebox_override(
"panel", get_theme_stylebox("background", "EditorStyles")
)
_update_settings()
@ -140,8 +137,9 @@ func _on_AddButton_pressed():
func _on_Tabs_tab_changed(tab_index):
tab_container.current_tab = tab_index
tab_container.get_child(tab_index).grab_focus()
tab_container.call_deferred("set_current_tab", tab_index)
await get_tree().process_frame
tab_container.get_current_tab_control().grab_focus()
func _on_Tabs_tab_close(tab_index):

View file

@ -1,8 +1,8 @@
[gd_scene load_steps=4 format=3 uid="uid://cbxovnvw5o4mo"]
[gd_scene load_steps=5 format=3 uid="uid://cbxovnvw5o4mo"]
[ext_resource type="Script" path="res://addons/godot_xterm/editor_plugins/terminal/terminal_panel.gd" id="1"]
[sub_resource type="Image" id="Image_4ja3e"]
[sub_resource type="Image" id="Image_knxas"]
data = {
"data": PackedByteArray(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 224, 224, 224, 0, 224, 224, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 224, 224, 224, 0, 224, 224, 224, 255, 224, 224, 224, 255, 224, 224, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 224, 224, 224, 0, 224, 224, 224, 255, 224, 224, 224, 255, 224, 224, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 224, 224, 224, 0, 224, 224, 224, 255, 224, 224, 224, 255, 224, 224, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 224, 224, 224, 0, 224, 224, 224, 255, 224, 224, 224, 255, 224, 224, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 224, 224, 224, 0, 224, 224, 224, 255, 224, 224, 224, 255, 224, 224, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 224, 224, 224, 0, 224, 224, 224, 0, 224, 224, 224, 0, 224, 224, 224, 0, 224, 224, 224, 0, 224, 224, 224, 0, 224, 224, 224, 255, 224, 224, 224, 255, 224, 224, 224, 0, 224, 224, 224, 0, 224, 224, 224, 0, 224, 224, 224, 0, 224, 224, 224, 0, 224, 224, 224, 0, 0, 0, 0, 0, 224, 224, 224, 0, 224, 224, 224, 255, 224, 224, 224, 255, 224, 224, 224, 255, 224, 224, 224, 255, 224, 224, 224, 255, 224, 224, 224, 255, 224, 224, 224, 255, 224, 224, 224, 255, 224, 224, 224, 255, 224, 224, 224, 255, 224, 224, 224, 255, 224, 224, 224, 255, 224, 224, 224, 255, 224, 224, 224, 255, 224, 224, 224, 0, 224, 224, 224, 0, 224, 224, 224, 255, 224, 224, 224, 255, 224, 224, 224, 255, 224, 224, 224, 255, 224, 224, 224, 255, 224, 224, 224, 255, 224, 224, 224, 255, 224, 224, 224, 255, 224, 224, 224, 255, 224, 224, 224, 255, 224, 224, 224, 255, 224, 224, 224, 255, 224, 224, 224, 255, 224, 224, 224, 255, 224, 224, 224, 0, 0, 0, 0, 0, 224, 224, 224, 0, 224, 224, 224, 0, 224, 224, 224, 0, 224, 224, 224, 0, 224, 224, 224, 0, 224, 224, 224, 0, 224, 224, 224, 255, 224, 224, 224, 255, 224, 224, 224, 0, 224, 224, 224, 0, 224, 224, 224, 0, 224, 224, 224, 0, 224, 224, 224, 0, 224, 224, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 224, 224, 224, 0, 224, 224, 224, 255, 224, 224, 224, 255, 224, 224, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 224, 224, 224, 0, 224, 224, 224, 255, 224, 224, 224, 255, 224, 224, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 224, 224, 224, 0, 224, 224, 224, 255, 224, 224, 224, 255, 224, 224, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 224, 224, 224, 0, 224, 224, 224, 255, 224, 224, 224, 255, 224, 224, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 224, 224, 224, 0, 224, 224, 224, 255, 224, 224, 224, 255, 224, 224, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 224, 224, 224, 0, 224, 224, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
"format": "RGBA8",
@ -12,7 +12,10 @@ data = {
}
[sub_resource type="ImageTexture" id="ImageTexture_q1uu0"]
image = SubResource("Image_4ja3e")
image = SubResource("Image_knxas")
[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_osmrc"]
bg_color = Color(0.113329, 0.129458, 0.156802, 1)
[node name="Panel" type="Panel"]
anchors_preset = 15
@ -59,6 +62,7 @@ item_3/id = 3
clip_contents = true
layout_mode = 2
size_flags_vertical = 3
theme_override_styles/panel = SubResource("StyleBoxFlat_osmrc")
tabs_visible = false
[node name="TerminalPopupMenu" type="PopupMenu" parent="VBoxContainer"]

View file

@ -14,6 +14,8 @@
#include <godot_cpp/classes/rendering_server.hpp>
#include <godot_cpp/classes/resource_loader.hpp>
#include <godot_cpp/classes/shader_material.hpp>
#include <godot_cpp/classes/style_box.hpp>
#include <godot_cpp/classes/style_box_flat.hpp>
#include <godot_cpp/classes/timer.hpp>
#include <godot_cpp/classes/theme.hpp>
#include <godot_cpp/classes/theme_db.hpp>
@ -204,6 +206,12 @@ void Terminal::_notification(int what)
update_sizes(true);
break;
}
case NOTIFICATION_FOCUS_ENTER:
case NOTIFICATION_FOCUS_EXIT:
{
refresh();
break;
}
case NOTIFICATION_THEME_CHANGED:
{
update_theme();
@ -277,8 +285,15 @@ int Terminal::_draw_cb(struct tsm_screen *con,
? term->palette[attr->bccode]
: Color(attr->br / 255.0f, attr->bg / 255.0f, attr->bb / 255.0f);
if (attr->inverse && term->inverse_mode == InverseMode::INVERSE_MODE_SWAP)
std::swap(fgcol, bgcol);
if (attr->inverse && term->inverse_mode == InverseMode::INVERSE_MODE_SWAP) {
std::swap(fgcol.r, bgcol.r);
std::swap(fgcol.g, bgcol.g);
std::swap(fgcol.b, bgcol.b);
bgcol.a = term->palette[TSM_COLOR_BACKGROUND].a;
}
if (bgcol == term->palette[TSM_COLOR_BACKGROUND])
bgcol.a = 0;
// Update images (accounting for ultra-wide characters).
for (int i = 0; i < width && (posx + i) < term->cols; i++) {
@ -425,6 +440,10 @@ void Terminal::update_sizes(bool force)
unsigned int prev_rows = rows;
size = get_size();
size.x -= (style_normal->get_margin(SIDE_LEFT) + style_normal->get_margin(SIDE_RIGHT));
size.y -= (style_normal->get_margin(SIDE_TOP) + style_normal->get_margin(SIDE_BOTTOM));
size.x = std::max(size.x, 1.0f);
size.y = std::max(size.y, 1.0f);
Ref<Font> font = fonts[FontType::NORMAL];
font_size = get_theme_font_size("font_size");
@ -439,6 +458,10 @@ void Terminal::update_sizes(bool force)
if (!force && size == prev_size && font_size == prev_font_size && cell_size == prev_cell_size && cols == prev_cols && rows == prev_rows)
return;
Transform2D transform = Transform2D(0, Vector2(style_normal->get_margin(SIDE_LEFT), style_normal->get_margin(SIDE_TOP)));
rs->canvas_item_set_transform(back_canvas_item, transform);
rs->canvas_item_set_transform(fore_canvas_item, transform);
tsm_screen_resize(screen, cols, rows);
rs->viewport_set_size(viewport, size.x, size.y);
@ -472,6 +495,12 @@ void Terminal::initialize_rendering() {
rs = RenderingServer::get_singleton();
attr_texture.instantiate();
// StyleBox.
style_canvas_item = rs->canvas_item_create();
rs->canvas_item_set_parent(style_canvas_item, get_canvas_item());
rs->canvas_item_set_draw_behind_parent(style_canvas_item, true);
// Background.
back_texture.instantiate();
@ -533,7 +562,6 @@ void Terminal::update_theme() {
tsm_vte_color color = static_cast<tsm_vte_color>(i);
palette[color] = get_theme_color(String(COLOR_NAMES[i]));
}
back_material->set_shader_parameter("background_color", palette[TSM_COLOR_BACKGROUND]);
// Update fonts.
for (int i = FontType::NORMAL; i <= FontType::BOLD_ITALICS; i++) {
@ -541,6 +569,17 @@ void Terminal::update_theme() {
fonts[type] = has_theme_font(FONT_TYPES[type]) ? get_theme_font(FONT_TYPES[type]) : get_theme_font(FONT_TYPES[FontType::NORMAL]);
}
// Update styles.
style_normal = get_theme_stylebox("normal");
style_focus = get_theme_stylebox("focus");
if (dynamic_cast<StyleBoxFlat*>(style_normal.ptr()) != nullptr) {
// Blend the background color with the style box's background color to get the "true" background color.
Color style_background_color = style_normal->get("bg_color");
palette[TSM_COLOR_BACKGROUND] = style_background_color.blend(palette[TSM_COLOR_BACKGROUND]);
}
back_material->set_shader_parameter("background_color", palette[TSM_COLOR_BACKGROUND]);
refresh();
}
@ -557,9 +596,18 @@ void Terminal::draw_screen() {
rs->viewport_set_clear_mode(viewport, RenderingServer::ViewportClearMode::VIEWPORT_CLEAR_ONLY_NEXT_FRAME);
Color bgcol = palette[TSM_COLOR_BACKGROUND];
rs->canvas_item_clear(style_canvas_item);
style_normal->draw(style_canvas_item, get_rect());
if (has_focus())
style_focus->draw(style_canvas_item, get_rect());
if (get_theme_color("background_color").a > 0)
rs->canvas_item_add_rect(style_canvas_item, get_rect(), bgcol);
rs->canvas_item_clear(back_canvas_item);
rs->canvas_item_add_rect(back_canvas_item, rect, palette[TSM_COLOR_BACKGROUND]);
back_image->fill(palette[TSM_COLOR_BACKGROUND]);
rs->canvas_item_add_rect(back_canvas_item, rect, bgcol);
back_image->fill(bgcol);
rs->canvas_item_clear(fore_canvas_item);
rs->canvas_item_add_texture_rect(fore_canvas_item, rect, rs->viewport_get_texture(viewport));
@ -577,6 +625,9 @@ void Terminal::refresh() {
}
void Terminal::cleanup_rendering() {
// StyleBox.
rs->free_rid(style_canvas_item);
// Background.
rs->free_rid(back_canvas_item);
@ -846,7 +897,7 @@ void Terminal::set_default_theme_items() {
// Default colors and font sizes from CodeEdit, TextEdit, et al.
// A comment on the translucency of the default background color: https://github.com/godotengine/godot/pull/51159#issuecomment-891127783.
default_theme->set_theme_item(Theme::DATA_TYPE_COLOR, "background_color", "Terminal", Color(0.1, 0.1, 0.1, 0.6));
default_theme->set_theme_item(Theme::DATA_TYPE_COLOR, "background_color", "Terminal", Color(0.0, 0.0, 0.0, 0.0));
default_theme->set_theme_item(Theme::DATA_TYPE_COLOR, "foreground_color", "Terminal", Color(0.875, 0.875, 0.875, 1));
default_theme->set_theme_item(Theme::DATA_TYPE_FONT_SIZE, "font_size", "Terminal", 16);
@ -879,4 +930,7 @@ void Terminal::set_default_theme_items() {
default_theme->set_theme_item(Theme::DATA_TYPE_FONT, FONT_TYPES[type], "Terminal", default_font);
}
}
default_theme->set_theme_item(Theme::DATA_TYPE_STYLEBOX, "normal", "Terminal", default_theme->get_theme_item(Theme::DATA_TYPE_STYLEBOX, "normal", "TextEdit"));
default_theme->set_theme_item(Theme::DATA_TYPE_STYLEBOX, "focus", "Terminal", default_theme->get_theme_item(Theme::DATA_TYPE_STYLEBOX, "focus", "TextEdit"));
}

View file

@ -13,6 +13,7 @@
#include <godot_cpp/classes/input_event_mouse_button.hpp>
#include <godot_cpp/classes/rendering_server.hpp>
#include <godot_cpp/classes/shader_material.hpp>
#include <godot_cpp/classes/style_box.hpp>
#include <godot_cpp/classes/timer.hpp>
#include <libtsm.h>
@ -133,6 +134,11 @@ namespace godot
Ref<Image> attr_image;
Ref<ImageTexture> attr_texture;
// StyleBox.
Ref<StyleBox> style_normal;
Ref<StyleBox> style_focus;
RID style_canvas_item;
// Background.
Ref<Image> back_image;
Ref<ImageTexture> back_texture;

View file

@ -18,6 +18,7 @@ uniform bool inverse_enabled = true;
#ifdef BACKGROUND
uniform vec4 background_color;
uniform sampler2D background_colors;
uniform sampler2D screen_texture : hint_screen_texture, repeat_disable, filter_nearest;
#endif
#ifdef FOREGROUND
@ -48,7 +49,15 @@ void fragment() {
#endif
if (has_attribute(sample_uv, FLAG_INVERSE) && inverse_enabled) {
color = vec4(1.0 - color.rgb, color.a);
#ifdef BACKGROUND
vec4 bg_color = textureLod(screen_texture, SCREEN_UV, 0.0);
vec4 target_color;
target_color.a = color.a + (1.0 - color.a) * bg_color.a;
target_color.rgb = 1.0 / target_color.a * (color.a * color.rgb + (1.0 - color.a) * bg_color.a * bg_color.rgb);
#else
vec4 target_color = color;
#endif
color = vec4(1.0 - target_color.rgb, target_color.a);
}
#ifdef FOREGROUND
@ -65,10 +74,6 @@ void fragment() {
COLOR = color;
#endif
} else { // Outside the grid.
#ifdef BACKGROUND
COLOR = background_color;
#elif defined(FOREGROUND)
COLOR = transparent;
#endif
}
}

View file

@ -0,0 +1,34 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://b2701o6oeug74"
path="res://.godot/imported/button_live_demo.png-c4135c006c49c133ba207164b5507208.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://docs/_static/images/button_live_demo.png"
dest_files=["res://.godot/imported/button_live_demo.png-c4135c006c49c133ba207164b5507208.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=false
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=1

View file

@ -0,0 +1,34 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://b3ng2bbvkcxqg"
path="res://.godot/imported/button_view_documentation.png-36b4e7350e1938a5364654dc5a6641e5.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://docs/_static/images/button_view_documentation.png"
dest_files=["res://.godot/imported/button_view_documentation.png-36b4e7350e1938a5364654dc5a6641e5.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=false
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=1

View file

@ -0,0 +1,34 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://c7rj0vssdtd0b"
path="res://.godot/imported/button_view_it_on_github.png-e0984ad68204453e4f7eca81ea6f9f3d.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://docs/_static/images/button_view_it_on_github.png"
dest_files=["res://.godot/imported/button_view_it_on_github.png-e0984ad68204453e4f7eca81ea6f9f3d.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=false
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=1

View file

@ -0,0 +1,37 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://bt0w1bpmrlvg6"
path="res://.godot/imported/diagram_flow.svg-deb966afe34c618af795399045a53c68.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://docs/_static/images/diagram_flow.svg"
dest_files=["res://.godot/imported/diagram_flow.svg-deb966afe34c618af795399045a53c68.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=false
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=1
svg/scale=1.0
editor/scale_with_editor_scale=false
editor/convert_colors_with_editor_theme=false

View file

@ -0,0 +1,34 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://bntcy0kljx1pk"
path="res://.godot/imported/diagram_pty.png-c8b3e1262155f7bb11780ceae74c3a89.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://docs/_static/images/diagram_pty.png"
dest_files=["res://.godot/imported/diagram_pty.png-c8b3e1262155f7bb11780ceae74c3a89.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=false
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=1

View file

@ -0,0 +1,37 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://cjdx1bbrl2dqx"
path="res://.godot/imported/diagram_pty.svg-870dd178a8c99c5215b512d2c8798749.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://docs/_static/images/diagram_pty.svg"
dest_files=["res://.godot/imported/diagram_pty.svg-870dd178a8c99c5215b512d2c8798749.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=false
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=1
svg/scale=1.0
editor/scale_with_editor_scale=false
editor/convert_colors_with_editor_theme=false

34
docs/_static/images/icon.png.import vendored Normal file
View file

@ -0,0 +1,34 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://2em8p7vcmp33"
path="res://.godot/imported/icon.png-2ad8615e0fbd4a5bd3357340a1dec3aa.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://docs/_static/images/icon.png"
dest_files=["res://.godot/imported/icon.png-2ad8615e0fbd4a5bd3357340a1dec3aa.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=false
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=1

34
docs/_static/images/logo.png.import vendored Normal file
View file

@ -0,0 +1,34 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://dx8rrrcro3wv4"
path="res://.godot/imported/logo.png-6572eef03017dd6311ce850698a2dea9.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://docs/_static/images/logo.png"
dest_files=["res://.godot/imported/logo.png-6572eef03017dd6311ce850698a2dea9.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=false
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=1

37
docs/_static/images/logo.svg.import vendored Normal file
View file

@ -0,0 +1,37 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://bx6o0qcekeeoh"
path="res://.godot/imported/logo.svg-328426fb4e56bc33b269fdd59f642f34.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://docs/_static/images/logo.svg"
dest_files=["res://.godot/imported/logo.svg-328426fb4e56bc33b269fdd59f642f34.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=false
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=1
svg/scale=1.0
editor/scale_with_editor_scale=false
editor/convert_colors_with_editor_theme=false

View file

@ -0,0 +1,34 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://d315jbwmtfwhi"
path="res://.godot/imported/screenshot_editor.png-c9da5cc4c087248bfd11d1ae567b2d56.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://docs/_static/images/screenshot_editor.png"
dest_files=["res://.godot/imported/screenshot_editor.png-c9da5cc4c087248bfd11d1ae567b2d56.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=false
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=1

View file

@ -0,0 +1,34 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://bewlk02k0excw"
path="res://.godot/imported/screenshot_retro_term.jpg-ac0139b857a49cabe0e6d99e21494eb0.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://docs/_static/images/screenshot_retro_term.jpg"
dest_files=["res://.godot/imported/screenshot_retro_term.jpg-ac0139b857a49cabe0e6d99e21494eb0.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=false
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=1

View file

@ -0,0 +1,34 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://0iq01v30huje"
path="res://.godot/imported/screenshot_the_guest.png-26bd55ff36509f34b0d3608706091443.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://docs/_static/images/screenshot_the_guest.png"
dest_files=["res://.godot/imported/screenshot_the_guest.png-26bd55ff36509f34b0d3608706091443.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=false
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=1

View file

@ -0,0 +1,34 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://i5i2woh5t4w5"
path="res://.godot/imported/screenshot_xterminate.png-195255f90e96125f75605ca3c708e423.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://docs/_static/images/screenshot_xterminate.png"
dest_files=["res://.godot/imported/screenshot_xterminate.png-195255f90e96125f75605ca3c708e423.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=false
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=1

0
docs/demo/.gdignore Normal file
View file

View file

@ -6,7 +6,7 @@ runnable=true
dedicated_server=false
custom_features=""
export_filter="resources"
export_files=PackedStringArray("res://addons/godot_xterm/shaders/foreground.gdshader", "res://addons/godot_xterm/native/godot-xterm.gdextension", "res://addons/godot_xterm/shaders/background.gdshader", "res://addons/godot_xterm/shaders/common.gdshaderinc", "res://examples/web_console/web_console.gd", "res://examples/web_console/web_console.tscn", "res://examples/menu/menu.gd", "res://examples/menu/menu.tscn", "res://examples/asciicast/asciicast.tscn", "res://examples/asciicast/example.cast", "res://addons/godot_xterm/util/tput.gd", "res://examples/terminal/terminal.tscn", "res://examples/terminal/terminal.gd", "res://addons/godot_xterm/themes/fonts/regular.tres", "res://addons/godot_xterm/themes/fonts/jet_brains_mono/jet_brains_mono_nl-regular-2.304.ttf", "res://themes/demo.tres")
export_files=PackedStringArray("res://addons/godot_xterm/shaders/foreground.gdshader", "res://addons/godot_xterm/native/godot-xterm.gdextension", "res://addons/godot_xterm/shaders/background.gdshader", "res://addons/godot_xterm/shaders/common.gdshaderinc", "res://examples/web_console/web_console.gd", "res://examples/web_console/web_console.tscn", "res://examples/menu/menu.gd", "res://examples/menu/menu.tscn", "res://examples/asciicast/asciicast.tscn", "res://examples/asciicast/example.cast", "res://addons/godot_xterm/util/tput.gd", "res://examples/terminal/terminal.tscn", "res://examples/terminal/terminal.gd", "res://addons/godot_xterm/themes/fonts/regular.tres", "res://addons/godot_xterm/themes/fonts/jet_brains_mono/jet_brains_mono_nl-regular-2.304.ttf", "res://themes/demo.tres", "res://themes/normal.stylebox")
include_filter="addons/godot_xterm/native/bin/*.wasm"
exclude_filter=""
export_path="docs/demo/index.html"

View file

@ -264,7 +264,7 @@ class TestSelect:
func before_each():
super.before_each()
text_edit = TextEdit.new()
text_edit.text = "0123456789\nABCDEFGHIJ\n)!@#$%^&*(\n\n\n\n\n\n\n"
text_edit.text = "0123456789\nABCDEFGHIJ\n)!@#$%^&*(\n\n\n\n\n\n"
add_child_autofree(text_edit)
subject.write("0123456789\r\nABCDEFGHIJ\r\n)!@#$%^&*(")
@ -306,7 +306,7 @@ class TestSelect:
assert_select_eq([-2, 0, 1, 10], "0123456789\nABCDEFGHIJ")
func test_select_exceeds_row_bounds():
assert_select_eq([1, 5, 999, 999], "FGHIJ\n)!@#$%^&*(\n\n\n\n\n\n\n")
assert_select_eq([1, 5, 999, 999], "FGHIJ\n)!@#$%^&*(\n\n\n\n\n\n")
func test_wide_bounds():
assert_select_eq([-999, -999, 999, 999], "0123456789\nABCDEFGHIJ\n)!@#$%^&*(\n\n\n\n\n\n\n")
assert_select_eq([-999, -999, 999, 999], "0123456789\nABCDEFGHIJ\n)!@#$%^&*(\n\n\n\n\n\n")

View file

@ -0,0 +1,13 @@
[gd_scene load_steps=2 format=3 uid="uid://bk450yhh0sx2f"]
[ext_resource type="Texture2D" uid="uid://2em8p7vcmp33" path="res://docs/_static/images/icon.png" id="1_osuf4"]
[node name="Background" type="TextureRect"]
z_index = -1
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
grow_horizontal = 2
grow_vertical = 2
texture = ExtResource("1_osuf4")
stretch_mode = 1

Binary file not shown.

After

Width:  |  Height:  |  Size: 479 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 822 B

After

Width:  |  Height:  |  Size: 984 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 11 KiB

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 368 B

After

Width:  |  Height:  |  Size: 503 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 548 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 560 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.9 KiB

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.4 KiB

View file

@ -88,6 +88,8 @@ class TestVisualRegression:
assert_match("default_theme")
func test_transparency():
subject.add_child(preload("./background.tscn").instantiate())
subject.add_theme_stylebox_override("normal", StyleBoxEmpty.new())
subject.add_theme_color_override("foreground_color", Color(0, 1, 0, 0.5))
subject.add_theme_color_override("background_color", Color(1, 0, 0, 0.5))
subject.write("bg red, 50% transparency\r\n")
@ -104,3 +106,39 @@ class TestVisualRegression:
subject.write("👈🤮👉💩👃😍🤥😤🙏🤟")
await wait_frames(30)
assert_match("emoji")
func test_solid_invert_selection():
subject.write("██████████\r\n██████████")
subject.add_theme_color_override("background_color", Color.ORANGE)
subject.inverse_mode = Terminal.INVERSE_MODE_INVERT
subject.select(0, 5, 1, 6)
await wait_frames(30)
assert_match("solid_invert_selection")
func test_solid_swap_selection():
subject.write("██████████\r\n██████████")
subject.add_theme_color_override("background_color", Color.ORANGE)
subject.inverse_mode = Terminal.INVERSE_MODE_SWAP
subject.select(0, 5, 1, 6)
await wait_frames(30)
assert_match("solid_swap_selection")
func test_transparent_invert_selection():
subject.add_child(preload("./background.tscn").instantiate())
subject.write("██████████\r\n██████████")
subject.add_theme_color_override("background_color", Color.TRANSPARENT)
subject.add_theme_stylebox_override("normal", StyleBoxEmpty.new())
subject.inverse_mode = Terminal.INVERSE_MODE_INVERT
subject.select(0, 5, 1, 6)
await wait_frames(30)
assert_match("transparent_invert_selection")
func test_transparent_swap_selection():
subject.add_child(preload("./background.tscn").instantiate())
subject.write("██████████\r\n██████████")
subject.add_theme_color_override("background_color", Color.TRANSPARENT)
subject.add_theme_stylebox_override("normal", StyleBoxEmpty.new())
subject.inverse_mode = Terminal.INVERSE_MODE_SWAP
subject.select(0, 5, 1, 6)
await wait_frames(30)
assert_match("transparent_swap_selection")

View file

@ -1,22 +0,0 @@
extends Node
var map = {
"background_color": "highlighting/background_color",
"foreground_color": "highlighting/text_color",
"ansi_0_color": "highlighting/caret_background_color",
"ansi_1_color": "highlighting/brace_mismatch_color",
"ansi_2_color": "gdscript/node_reference_color",
"ansi_3_color": "highlighting/executing_line_color",
"ansi_4_color": "highlighting/bookmark_color",
"ansi_5_color": "highlighting/control_flow_keyword_color",
"ansi_6_color": "highlighting/engine_type_color",
"ansi_7_color": "highlighting/comment_color",
"ansi_8_color": "highlighting/completion_background_color",
"ansi_9_color": "highlighting/keyword_color",
"ansi_10_color": "highlighting/base_type_color",
"ansi_11_color": "highlighting/string_color",
"ansi_12_color": "highlighting/function_color",
"ansi_13_color": "gdscript/global_function_color",
"ansi_14_color": "gdscript/function_definition_color",
"ansi_15_color": "highlighting/caret_color",
}

View file

@ -1,6 +1,7 @@
[gd_resource type="Theme" load_steps=2 format=3 uid="uid://0gk8swmcldbg"]
[gd_resource type="Theme" load_steps=3 format=3 uid="uid://0gk8swmcldbg"]
[ext_resource type="FontVariation" uid="uid://vmgmcu8gc6nt" path="res://addons/godot_xterm/themes/fonts/regular.tres" id="1_aigbn"]
[ext_resource type="StyleBox" uid="uid://cxaclm5pavuv6" path="res://themes/normal.stylebox" id="1_bj7pu"]
[resource]
default_font = ExtResource("1_aigbn")
@ -20,6 +21,6 @@ Terminal/colors/ansi_6_color = Color(0.560784, 1, 0.858824, 1)
Terminal/colors/ansi_7_color = Color(0.803922, 0.811765, 0.823529, 0.501961)
Terminal/colors/ansi_8_color = Color(0.211765, 0.239216, 0.290196, 1)
Terminal/colors/ansi_9_color = Color(1, 0.439216, 0.521569, 1)
Terminal/colors/background_color = Color(0.113725, 0.133333, 0.160784, 1)
Terminal/colors/foreground_color = Color(0.803922, 0.811765, 0.823529, 1)
Terminal/font_sizes/font_size = 14
Terminal/styles/normal = ExtResource("1_bj7pu")

View file

@ -1,10 +1,11 @@
[gd_resource type="Theme" load_steps=6 format=3 uid="uid://c7vj5543645y4"]
[gd_resource type="Theme" load_steps=7 format=3 uid="uid://c7vj5543645y4"]
[ext_resource type="FontVariation" uid="uid://bic8m0k54oyy5" path="res://themes/fonts/bold.tres" id="1_0fs6o"]
[ext_resource type="FontVariation" uid="uid://ddjoc6kuuq1bh" path="res://themes/fonts/bold_italic.tres" id="2_vxvx6"]
[ext_resource type="FontVariation" uid="uid://bvoyrkgr4mipq" path="res://themes/fonts/italic.tres" id="3_0wjcg"]
[ext_resource type="FontVariation" uid="uid://ckq73bs2fwsie" path="res://themes/fonts/regular.tres" id="4_ldymn"]
[ext_resource type="FontVariation" uid="uid://vmgmcu8gc6nt" path="res://addons/godot_xterm/themes/fonts/regular.tres" id="5_s2il6"]
[ext_resource type="StyleBox" uid="uid://cxaclm5pavuv6" path="res://themes/normal.stylebox" id="5_u76ir"]
[resource]
default_font = ExtResource("5_s2il6")
@ -31,3 +32,4 @@ Terminal/fonts/bold_font = ExtResource("1_0fs6o")
Terminal/fonts/bold_italics_font = ExtResource("2_vxvx6")
Terminal/fonts/italics_font = ExtResource("3_0wjcg")
Terminal/fonts/normal_font = ExtResource("4_ldymn")
Terminal/styles/normal = ExtResource("5_u76ir")

BIN
themes/normal.stylebox Normal file

Binary file not shown.