mirror of
https://github.com/lihop/godot-xterm.git
synced 2025-05-05 12:44:24 +02:00
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:
parent
a5951978f7
commit
d6a4adf6aa
40 changed files with 608 additions and 52 deletions
|
@ -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.
|
||||
|
|
|
@ -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="."]
|
||||
|
|
|
@ -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):
|
||||
|
|
|
@ -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"]
|
||||
|
|
|
@ -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"));
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue