2024-02-06 12:01:14 +01:00
|
|
|
// SPDX-FileCopyrightText: 2021-2024 Leroy Hopson <godot-xterm@leroy.nix.nz>
|
2023-01-08 10:41:48 +01:00
|
|
|
// SPDX-License-Identifier: MIT
|
2021-07-02 19:04:34 +02:00
|
|
|
|
2020-07-11 12:45:21 +02:00
|
|
|
#include "terminal.h"
|
2024-02-06 12:01:14 +01:00
|
|
|
|
|
|
|
#include <godot_cpp/classes/control.hpp>
|
|
|
|
#include <godot_cpp/classes/font.hpp>
|
|
|
|
#include <godot_cpp/classes/image_texture.hpp>
|
2023-01-08 10:41:48 +01:00
|
|
|
#include <godot_cpp/classes/rendering_server.hpp>
|
2022-12-29 10:52:13 +01:00
|
|
|
#include <godot_cpp/classes/resource_loader.hpp>
|
2024-02-06 12:01:14 +01:00
|
|
|
#include <godot_cpp/classes/shader_material.hpp>
|
|
|
|
#include <libtsm.h>
|
2020-07-11 12:45:21 +02:00
|
|
|
|
2024-02-06 12:01:14 +01:00
|
|
|
#define SHADERS_DIR "res://addons/godot_xterm/shaders/"
|
|
|
|
#define FOREGROUND_SHADER_PATH SHADERS_DIR "foreground.gdshader"
|
|
|
|
#define BACKGROUND_SHADER_PATH SHADERS_DIR "background.gdshader"
|
2021-06-06 14:37:07 +02:00
|
|
|
|
2020-07-11 12:45:21 +02:00
|
|
|
using namespace godot;
|
|
|
|
|
2024-02-06 12:01:14 +01:00
|
|
|
void Terminal::_bind_methods()
|
|
|
|
{
|
|
|
|
ClassDB::bind_method(D_METHOD("get_cols"), &Terminal::get_cols);
|
|
|
|
ClassDB::bind_method(D_METHOD("set_cols", "cols"), &Terminal::set_cols);
|
|
|
|
ClassDB::add_property("Terminal", PropertyInfo(Variant::INT, "cols"), "set_cols", "get_cols");
|
2023-01-08 10:41:48 +01:00
|
|
|
|
2024-02-06 12:01:14 +01:00
|
|
|
ClassDB::bind_method(D_METHOD("get_rows"), &Terminal::get_rows);
|
|
|
|
ClassDB::bind_method(D_METHOD("set_rows", "rows"), &Terminal::set_rows);
|
|
|
|
ClassDB::add_property("Terminal", PropertyInfo(Variant::INT, "rows"), "set_rows", "get_rows");
|
2021-06-06 14:37:07 +02:00
|
|
|
|
2024-02-06 12:01:14 +01:00
|
|
|
ClassDB::bind_method(D_METHOD("get_max_scrollback"), &Terminal::get_max_scrollback);
|
|
|
|
ClassDB::bind_method(D_METHOD("set_max_scrollback", "max_scrollback"), &Terminal::set_max_scrollback);
|
|
|
|
ClassDB::add_property("Terminal", PropertyInfo(Variant::INT, "max_scrollback"), "set_max_scrollback", "get_max_scrollback");
|
2023-01-20 22:37:26 +01:00
|
|
|
|
2024-02-07 11:03:11 +01:00
|
|
|
// Inverse mode.
|
|
|
|
|
|
|
|
BIND_ENUM_CONSTANT(INVERSE_MODE_INVERT);
|
|
|
|
BIND_ENUM_CONSTANT(INVERSE_MODE_SWAP);
|
|
|
|
ClassDB::bind_method(D_METHOD("get_inverse_mode"), &Terminal::get_inverse_mode);
|
|
|
|
ClassDB::bind_method(D_METHOD("set_inverse_mode", "inverse_mode"), &Terminal::set_inverse_mode);
|
|
|
|
ClassDB::add_property("Terminal", PropertyInfo(Variant::INT, "inverse_mode", PROPERTY_HINT_ENUM, "Invert,Swap"), "set_inverse_mode", "get_inverse_mode");
|
|
|
|
|
2024-02-07 10:26:45 +01:00
|
|
|
// Blink.
|
|
|
|
|
|
|
|
ClassDB::add_property_group("Terminal", "Blink", "blink_");
|
|
|
|
ClassDB::bind_method(D_METHOD("get_blink_on_time"), &Terminal::get_blink_on_time);
|
|
|
|
ClassDB::bind_method(D_METHOD("set_blink_on_time", "time"), &Terminal::set_blink_on_time);
|
|
|
|
ClassDB::add_property("Terminal", PropertyInfo(Variant::FLOAT, "blink_on_time"), "set_blink_on_time", "get_blink_on_time");
|
|
|
|
ClassDB::bind_method(D_METHOD("get_blink_off_time"), &Terminal::get_blink_off_time);
|
|
|
|
ClassDB::bind_method(D_METHOD("set_blink_off_time", "time"), &Terminal::set_blink_off_time);
|
|
|
|
ClassDB::add_property("Terminal", PropertyInfo(Variant::FLOAT, "blink_off_time"), "set_blink_off_time", "get_blink_off_time");
|
|
|
|
|
|
|
|
// Methods.
|
|
|
|
|
2024-02-06 12:01:14 +01:00
|
|
|
ClassDB::bind_method(D_METHOD("write", "data"), &Terminal::write);
|
2024-02-07 11:14:52 +01:00
|
|
|
ClassDB::bind_method(D_METHOD("get_cursor_pos"), &Terminal::get_cursor_pos);
|
2024-02-06 12:01:14 +01:00
|
|
|
}
|
2023-01-08 10:41:48 +01:00
|
|
|
|
2024-02-06 12:01:14 +01:00
|
|
|
Terminal::Terminal()
|
|
|
|
{
|
|
|
|
max_scrollback = 1000;
|
2023-01-08 10:41:48 +01:00
|
|
|
|
2024-02-07 10:26:45 +01:00
|
|
|
blink_on_time = 0.6;
|
|
|
|
blink_off_time = 0.3;
|
2023-01-08 10:41:48 +01:00
|
|
|
|
2024-02-07 11:03:11 +01:00
|
|
|
inverse_mode = InverseMode::INVERSE_MODE_INVERT;
|
|
|
|
|
2024-02-06 12:01:14 +01:00
|
|
|
if (tsm_screen_new(&screen, NULL, NULL))
|
|
|
|
{
|
|
|
|
ERR_PRINT("Failed to create tsm screen.");
|
|
|
|
}
|
|
|
|
tsm_screen_set_max_sb(screen, max_scrollback);
|
2023-01-08 10:41:48 +01:00
|
|
|
|
2024-02-06 12:01:14 +01:00
|
|
|
if (tsm_vte_new(&vte, screen, &Terminal::_write_cb, this, NULL, NULL))
|
|
|
|
{
|
|
|
|
ERR_PRINT("Failed to create tsm vte.");
|
|
|
|
}
|
2023-01-08 10:41:48 +01:00
|
|
|
|
2024-02-06 12:01:14 +01:00
|
|
|
initialize_rendering();
|
|
|
|
update_theme();
|
|
|
|
update_sizes();
|
2023-01-08 10:41:48 +01:00
|
|
|
}
|
|
|
|
|
2024-02-06 12:01:14 +01:00
|
|
|
Terminal::~Terminal()
|
|
|
|
{
|
|
|
|
cleanup_rendering();
|
2023-01-08 10:41:48 +01:00
|
|
|
}
|
|
|
|
|
2024-02-06 12:01:14 +01:00
|
|
|
void Terminal::set_cols(const int p_cols)
|
|
|
|
{
|
|
|
|
cols = p_cols;
|
2023-01-08 10:41:48 +01:00
|
|
|
}
|
|
|
|
|
2024-02-06 12:01:14 +01:00
|
|
|
int Terminal::get_cols() const
|
|
|
|
{
|
|
|
|
return cols;
|
2023-01-08 10:41:48 +01:00
|
|
|
}
|
2020-09-24 12:29:19 +02:00
|
|
|
|
2024-02-06 12:01:14 +01:00
|
|
|
void Terminal::set_rows(const int p_rows)
|
|
|
|
{
|
|
|
|
rows = p_rows;
|
2021-06-06 14:37:07 +02:00
|
|
|
}
|
|
|
|
|
2024-02-06 12:01:14 +01:00
|
|
|
int Terminal::get_rows() const
|
|
|
|
{
|
|
|
|
return rows;
|
2023-01-08 10:41:48 +01:00
|
|
|
}
|
|
|
|
|
2024-02-07 11:14:52 +01:00
|
|
|
Vector2 Terminal::get_cursor_pos() const {
|
|
|
|
return Vector2(tsm_screen_get_cursor_x(screen), tsm_screen_get_cursor_y(screen));
|
|
|
|
}
|
|
|
|
|
2024-02-06 12:01:14 +01:00
|
|
|
void Terminal::set_max_scrollback(const int p_max_scrollback)
|
|
|
|
{
|
|
|
|
max_scrollback = std::max(0, p_max_scrollback);
|
|
|
|
tsm_screen_set_max_sb(screen, max_scrollback);
|
2023-01-08 10:41:48 +01:00
|
|
|
}
|
|
|
|
|
2024-02-06 12:01:14 +01:00
|
|
|
int Terminal::get_max_scrollback() const
|
|
|
|
{
|
|
|
|
return max_scrollback;
|
2023-01-20 22:37:26 +01:00
|
|
|
}
|
|
|
|
|
2024-02-06 12:01:14 +01:00
|
|
|
void Terminal::write(Variant data)
|
|
|
|
{
|
|
|
|
PackedByteArray bytes;
|
|
|
|
|
|
|
|
switch (data.get_type())
|
|
|
|
{
|
|
|
|
case Variant::STRING:
|
|
|
|
bytes = ((String)data).to_utf8_buffer();
|
|
|
|
break;
|
|
|
|
case Variant::PACKED_BYTE_ARRAY:
|
|
|
|
bytes = data;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
ERR_FAIL_MSG("Data must be a String or PackedByteArray.");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (bytes.is_empty())
|
|
|
|
return;
|
|
|
|
|
|
|
|
tsm_vte_input(vte, (char *)bytes.ptr(), bytes.size());
|
|
|
|
|
|
|
|
queue_redraw();
|
2023-01-20 22:37:26 +01:00
|
|
|
}
|
|
|
|
|
2024-02-06 12:01:14 +01:00
|
|
|
void Terminal::_notification(int what)
|
|
|
|
{
|
|
|
|
switch (what)
|
|
|
|
{
|
|
|
|
case NOTIFICATION_READY:
|
|
|
|
{
|
|
|
|
update_theme();
|
|
|
|
update_sizes(true);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case NOTIFICATION_THEME_CHANGED:
|
|
|
|
{
|
|
|
|
update_theme();
|
2024-02-10 04:36:48 +01:00
|
|
|
[[fallthrough]];
|
2024-02-06 12:01:14 +01:00
|
|
|
}
|
|
|
|
case NOTIFICATION_RESIZED:
|
|
|
|
{
|
|
|
|
update_sizes();
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case NOTIFICATION_DRAW:
|
|
|
|
{
|
|
|
|
draw_screen();
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2023-01-20 22:37:26 +01:00
|
|
|
}
|
|
|
|
|
2024-02-06 12:01:14 +01:00
|
|
|
void Terminal::_write_cb(tsm_vte *vte, const char *u8, size_t len, void *data)
|
|
|
|
{
|
|
|
|
Terminal *term = static_cast<Terminal *>(data);
|
2023-01-20 22:37:26 +01:00
|
|
|
}
|
|
|
|
|
2024-02-06 12:01:14 +01:00
|
|
|
int Terminal::_draw_cb(struct tsm_screen *con,
|
|
|
|
uint64_t id,
|
|
|
|
const uint32_t *ch,
|
|
|
|
size_t len,
|
|
|
|
unsigned int width,
|
|
|
|
unsigned int posx,
|
|
|
|
unsigned int posy,
|
|
|
|
const struct tsm_screen_attr *attr,
|
|
|
|
tsm_age_t age,
|
|
|
|
void *data)
|
|
|
|
{
|
|
|
|
Terminal *term = static_cast<Terminal *>(data);
|
|
|
|
|
|
|
|
if (age != 0 && age <= term->framebuffer_age) return OK;
|
|
|
|
|
|
|
|
if (width < 1)
|
|
|
|
{ // No foreground or background to draw.
|
|
|
|
return OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Update attributes.
|
|
|
|
int attr_flags = 0;
|
|
|
|
if (attr->inverse)
|
2024-02-10 03:53:03 +01:00
|
|
|
attr_flags |= AttrFlag::INVERSE;
|
2024-02-06 12:01:14 +01:00
|
|
|
if (attr->blink)
|
2024-02-10 03:53:03 +01:00
|
|
|
attr_flags |= AttrFlag::BLINK;
|
2024-02-06 12:01:14 +01:00
|
|
|
term->attr_image->set_pixel(posx, posy, Color(attr_flags / 255.0f, 0, 0, 0));
|
|
|
|
|
|
|
|
// Colors.
|
|
|
|
Color fgcol = std::min(attr->fccode, (int8_t)TSM_COLOR_FOREGROUND) >= 0
|
|
|
|
? term->palette[attr->fccode]
|
|
|
|
: Color(attr->fr / 255.0f, attr->fg / 255.0f, attr->fb / 255.0f);
|
|
|
|
|
|
|
|
Color bgcol = std::min(attr->bccode, (int8_t)TSM_COLOR_BACKGROUND) >= 0
|
|
|
|
? term->palette[attr->bccode]
|
|
|
|
: Color(attr->br / 255.0f, attr->bg / 255.0f, attr->bb / 255.0f);
|
|
|
|
|
2024-02-07 11:03:11 +01:00
|
|
|
if (attr->inverse && term->inverse_mode == InverseMode::INVERSE_MODE_SWAP)
|
|
|
|
std::swap(fgcol, bgcol);
|
|
|
|
|
2024-02-06 12:01:14 +01:00
|
|
|
// Draw background.
|
|
|
|
term->back_image->set_pixel(posx, posy, bgcol);
|
|
|
|
|
|
|
|
if (len < 1)
|
|
|
|
{ // No foreground to draw.
|
|
|
|
return OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
Vector2 cell_position = Vector2(posx * term->cell_size.x, posy * term->cell_size.y);
|
|
|
|
Rect2 cell_rect = Rect2(cell_position, term->cell_size);
|
|
|
|
|
|
|
|
// Erase any previous character in the cell.
|
|
|
|
term->rs->canvas_item_add_rect(term->char_canvas_item, cell_rect, Color(1, 1, 1, 0));
|
|
|
|
|
|
|
|
term->font->draw_char(
|
|
|
|
term->char_canvas_item,
|
|
|
|
Vector2i(cell_position.x, cell_position.y + term->font->get_height(
|
|
|
|
term->font_size /
|
|
|
|
1.25)),
|
|
|
|
String((char *)ch).unicode_at(0),
|
|
|
|
term->font_size,
|
|
|
|
fgcol
|
|
|
|
);
|
|
|
|
|
|
|
|
return OK;
|
2023-01-20 22:37:26 +01:00
|
|
|
}
|
|
|
|
|
2024-02-06 12:01:14 +01:00
|
|
|
bool Terminal::_set(const StringName &property, const Variant &value)
|
|
|
|
{
|
|
|
|
if (property.begins_with("theme_override_colors/"))
|
|
|
|
{
|
|
|
|
String color_name = property.split("/")[1];
|
|
|
|
if (_is_valid_color_name(color_name))
|
|
|
|
{
|
|
|
|
if (value.get_type() != Variant::Type::NIL)
|
|
|
|
{
|
|
|
|
add_theme_color_override(color_name, value);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
remove_theme_color_override(color_name);
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (property.begins_with("theme_override_fonts/"))
|
|
|
|
{
|
|
|
|
String font_type = property.split("/")[1];
|
|
|
|
if (_is_valid_font_type(font_type))
|
|
|
|
{
|
|
|
|
if (value.get_type() != Variant::Type::NIL)
|
|
|
|
{
|
|
|
|
add_theme_font_override(font_type, value);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
remove_theme_font_override(font_type);
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (property == String("theme_override_font_sizes/font_size"))
|
|
|
|
{
|
|
|
|
if (value.get_type() != Variant::Type::NIL)
|
|
|
|
{
|
|
|
|
add_theme_font_size_override("font_size", value == Variant(0) ? Variant(1) : value);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
remove_theme_font_size_override("font_size");
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
2023-01-20 22:37:26 +01:00
|
|
|
}
|
|
|
|
|
2024-02-06 12:01:14 +01:00
|
|
|
void Terminal::_get_property_list(List<PropertyInfo> *p_list) const
|
|
|
|
{
|
|
|
|
p_list->push_back(PropertyInfo(Variant::NIL, "Theme Overrides", PROPERTY_HINT_NONE, "theme_override_", PROPERTY_USAGE_GROUP));
|
|
|
|
p_list->push_back(PropertyInfo(Variant::NIL, "Colors", PROPERTY_HINT_NONE, "theme_override_colors/", PROPERTY_USAGE_SUBGROUP));
|
|
|
|
for (int i = 0; i < TSM_COLOR_NUM; ++i)
|
|
|
|
{
|
|
|
|
p_list->push_back(PropertyInfo(Variant::COLOR, "theme_override_colors/" + String(COLOR_NAMES[i]), PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_CHECKABLE));
|
|
|
|
}
|
|
|
|
p_list->push_back(PropertyInfo(Variant::NIL, "Fonts", PROPERTY_HINT_NONE, "theme_override_fonts/", PROPERTY_USAGE_SUBGROUP));
|
|
|
|
for (const String font_type : FONT_TYPES)
|
|
|
|
{
|
|
|
|
p_list->push_back(PropertyInfo(Variant::OBJECT, "theme_override_fonts/" + font_type, PROPERTY_HINT_RESOURCE_TYPE, "Font", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_CHECKABLE));
|
|
|
|
}
|
|
|
|
p_list->push_back(PropertyInfo(Variant::NIL, "Font Sizes", PROPERTY_HINT_NONE, "theme_override_font_sizes/", PROPERTY_USAGE_SUBGROUP));
|
|
|
|
p_list->push_back(PropertyInfo(Variant::INT, "theme_override_font_sizes/font_size", PROPERTY_HINT_RANGE, "1,256,1,or_greater,suffix:px", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_CHECKABLE));
|
2023-01-08 10:41:48 +01:00
|
|
|
}
|
2020-07-11 12:45:21 +02:00
|
|
|
|
2024-02-06 12:01:14 +01:00
|
|
|
bool Terminal::_is_valid_color_name(const String &p_name)
|
|
|
|
{
|
|
|
|
for (const char *entry : COLOR_NAMES)
|
|
|
|
{
|
|
|
|
if (std::strcmp(p_name.utf8().get_data(), entry) == 0)
|
|
|
|
{
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
2020-09-24 12:29:19 +02:00
|
|
|
|
2024-02-06 12:01:14 +01:00
|
|
|
bool Terminal::_is_valid_font_type(const String &p_name)
|
|
|
|
{
|
|
|
|
for (const char *entry : FONT_TYPES)
|
|
|
|
{
|
|
|
|
if (std::strcmp(p_name.utf8().get_data(), entry) == 0)
|
|
|
|
{
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return false;
|
2020-07-11 12:45:21 +02:00
|
|
|
}
|
|
|
|
|
2024-02-06 12:01:14 +01:00
|
|
|
void Terminal::update_sizes(bool force)
|
|
|
|
{
|
|
|
|
Vector2 prev_size = Vector2(size);
|
|
|
|
int32_t prev_font_size = font_size;
|
|
|
|
Vector2 prev_cell_size = Vector2(cell_size);
|
|
|
|
uint prev_cols = cols;
|
|
|
|
uint prev_rows = rows;
|
|
|
|
|
|
|
|
size = get_size();
|
|
|
|
font_size = get_theme_font_size("font_size");
|
|
|
|
cell_size = get_theme_font("normal_font")->get_string_size(
|
|
|
|
"W", HORIZONTAL_ALIGNMENT_LEFT, -1, get_theme_font_size("font_size"));
|
|
|
|
cols = floor(size.x / cell_size.x);
|
|
|
|
rows = floor(size.y / cell_size.y);
|
2020-07-11 12:45:21 +02:00
|
|
|
|
2024-02-06 12:01:14 +01:00
|
|
|
if (!force && size == prev_size && font_size == prev_font_size && cell_size == prev_cell_size && cols == prev_cols && rows == prev_rows)
|
|
|
|
return;
|
2021-06-19 15:57:05 +02:00
|
|
|
|
2024-02-06 12:01:14 +01:00
|
|
|
tsm_screen_resize(screen, cols, rows);
|
|
|
|
rs->viewport_set_size(viewport, size.x, size.y);
|
2020-09-24 12:29:19 +02:00
|
|
|
|
2024-02-06 12:01:14 +01:00
|
|
|
back_image = Image::create(std::max(cols, 1u), std::max(rows, 1u), false, Image::FORMAT_RGBA8);
|
|
|
|
back_texture->set_image(back_image);
|
2020-07-11 12:45:21 +02:00
|
|
|
|
2024-02-06 12:01:14 +01:00
|
|
|
attr_image = Image::create(std::max(cols, 1u), std::max(rows, 1u), false, Image::FORMAT_L8);
|
|
|
|
attr_texture->set_image(attr_image);
|
2021-07-12 17:24:21 +02:00
|
|
|
|
2024-02-07 09:37:50 +01:00
|
|
|
update_shader_parameters(back_material);
|
|
|
|
update_shader_parameters(fore_material);
|
2021-06-06 14:58:50 +02:00
|
|
|
|
2024-02-06 12:01:14 +01:00
|
|
|
refresh();
|
2020-07-11 12:45:21 +02:00
|
|
|
}
|
|
|
|
|
2024-02-07 09:37:50 +01:00
|
|
|
void Terminal::update_shader_parameters(Ref<ShaderMaterial> material)
|
|
|
|
{
|
|
|
|
material->set_shader_parameter("cols", cols);
|
|
|
|
material->set_shader_parameter("rows", rows);
|
|
|
|
material->set_shader_parameter("size", size);
|
|
|
|
material->set_shader_parameter("cell_size", cell_size);
|
|
|
|
material->set_shader_parameter("grid_size", Vector2(cols * cell_size.x, rows * cell_size.y));
|
|
|
|
}
|
|
|
|
|
2024-02-06 12:01:14 +01:00
|
|
|
void Terminal::initialize_rendering() {
|
|
|
|
ResourceLoader* rl = ResourceLoader::get_singleton();
|
2020-07-11 12:45:21 +02:00
|
|
|
|
2024-02-06 12:01:14 +01:00
|
|
|
rs = RenderingServer::get_singleton();
|
|
|
|
attr_texture.instantiate();
|
2023-01-08 10:41:48 +01:00
|
|
|
|
2024-02-06 12:01:14 +01:00
|
|
|
// Background.
|
2020-07-11 12:45:21 +02:00
|
|
|
|
2024-02-06 12:01:14 +01:00
|
|
|
back_texture.instantiate();
|
2020-07-11 12:45:21 +02:00
|
|
|
|
2024-02-06 12:01:14 +01:00
|
|
|
back_shader = rl->load(BACKGROUND_SHADER_PATH);
|
2020-07-11 12:45:21 +02:00
|
|
|
|
2024-02-06 12:01:14 +01:00
|
|
|
back_material.instantiate();
|
|
|
|
back_material->set_shader(back_shader);
|
2024-02-07 09:37:50 +01:00
|
|
|
back_material->set_shader_parameter("background_colors", back_texture);
|
2024-02-06 12:01:14 +01:00
|
|
|
back_material->set_shader_parameter("attributes", attr_texture);
|
2020-07-11 12:45:21 +02:00
|
|
|
|
2024-02-06 12:01:14 +01:00
|
|
|
back_canvas_item = rs->canvas_item_create();
|
|
|
|
rs->canvas_item_set_material(back_canvas_item, back_material->get_rid());
|
|
|
|
rs->canvas_item_set_parent(back_canvas_item, get_canvas_item());
|
|
|
|
rs->canvas_item_set_draw_behind_parent(back_canvas_item, true);
|
2021-06-06 14:58:50 +02:00
|
|
|
|
2024-02-06 12:01:14 +01:00
|
|
|
// Foreground.
|
2021-06-06 14:58:50 +02:00
|
|
|
|
2024-02-06 12:01:14 +01:00
|
|
|
char_shader = rs->shader_create();
|
|
|
|
rs->shader_set_code(char_shader, String(R"(
|
|
|
|
shader_type canvas_item;
|
|
|
|
render_mode blend_disabled;
|
|
|
|
)"));
|
2021-06-06 14:58:50 +02:00
|
|
|
|
2024-02-06 12:01:14 +01:00
|
|
|
char_material = rs->material_create();
|
|
|
|
rs->material_set_shader(char_material, char_shader);
|
2021-06-06 14:58:50 +02:00
|
|
|
|
2024-02-06 12:01:14 +01:00
|
|
|
char_canvas_item = rs->canvas_item_create();
|
|
|
|
rs->canvas_item_set_material(char_canvas_item, char_material);
|
2021-06-06 14:58:50 +02:00
|
|
|
|
2024-02-06 12:01:14 +01:00
|
|
|
canvas = rs->canvas_create();
|
|
|
|
rs->canvas_item_set_parent(char_canvas_item, canvas);
|
2021-06-06 14:58:50 +02:00
|
|
|
|
2024-02-06 12:01:14 +01:00
|
|
|
viewport = rs-> viewport_create();
|
|
|
|
rs->viewport_attach_canvas(viewport, canvas);
|
|
|
|
rs->viewport_set_disable_3d(viewport, true);
|
|
|
|
rs->viewport_set_transparent_background(viewport, true);
|
|
|
|
rs->viewport_set_clear_mode(viewport, RenderingServer::ViewportClearMode::VIEWPORT_CLEAR_NEVER);
|
|
|
|
rs->viewport_set_update_mode(viewport, RenderingServer::ViewportUpdateMode::VIEWPORT_UPDATE_WHEN_VISIBLE);
|
|
|
|
rs->viewport_set_active(viewport, true);
|
2020-07-11 12:45:21 +02:00
|
|
|
|
2024-02-06 12:01:14 +01:00
|
|
|
fore_shader = rl->load(FOREGROUND_SHADER_PATH);
|
|
|
|
|
|
|
|
fore_material.instantiate();
|
|
|
|
fore_material->set_shader(fore_shader);
|
|
|
|
fore_material->set_shader_parameter("attributes", attr_texture);
|
2021-07-08 15:10:58 +02:00
|
|
|
|
2024-02-06 12:01:14 +01:00
|
|
|
fore_canvas_item = rs->canvas_item_create();
|
|
|
|
rs->canvas_item_set_material(fore_canvas_item, fore_material->get_rid());
|
|
|
|
rs->canvas_item_set_parent(fore_canvas_item, get_canvas_item());
|
2021-07-08 15:33:46 +02:00
|
|
|
}
|
|
|
|
|
2024-02-06 12:01:14 +01:00
|
|
|
void Terminal::update_theme() {
|
|
|
|
palette.resize(TSM_COLOR_NUM);
|
|
|
|
for (int i = 0; i < TSM_COLOR_NUM; i++) {
|
|
|
|
tsm_vte_color color = static_cast<tsm_vte_color>(i);
|
|
|
|
palette[color] = get_theme_color(String(COLOR_NAMES[i]));
|
|
|
|
}
|
2024-02-07 09:37:50 +01:00
|
|
|
back_material->set_shader_parameter("background_color", palette[TSM_COLOR_BACKGROUND]);
|
2024-02-06 12:01:14 +01:00
|
|
|
|
|
|
|
// TODO: Default to mono font and handle other styles.
|
|
|
|
font = get_theme_font("normal_font");
|
|
|
|
|
|
|
|
refresh();
|
2021-07-13 01:27:20 +02:00
|
|
|
}
|
2021-07-13 17:20:29 +02:00
|
|
|
|
2024-02-06 12:01:14 +01:00
|
|
|
void Terminal::draw_screen() {
|
|
|
|
if (framebuffer_age == 0) {
|
|
|
|
Rect2 rect = Rect2(Vector2(), size);
|
2023-01-08 10:41:48 +01:00
|
|
|
|
2024-02-06 12:01:14 +01:00
|
|
|
rs->viewport_set_clear_mode(viewport, RenderingServer::ViewportClearMode::VIEWPORT_CLEAR_ONLY_NEXT_FRAME);
|
2023-01-08 10:41:48 +01:00
|
|
|
|
2024-02-06 12:01:14 +01:00
|
|
|
rs->canvas_item_clear(back_canvas_item);
|
|
|
|
rs->canvas_item_add_rect(back_canvas_item, rect, palette[TSM_COLOR_BLACK]);
|
|
|
|
back_image->fill(palette[TSM_COLOR_BLACK]);
|
2023-01-08 10:41:48 +01:00
|
|
|
|
2024-02-06 12:01:14 +01:00
|
|
|
rs->canvas_item_clear(fore_canvas_item);
|
|
|
|
rs->canvas_item_add_texture_rect(fore_canvas_item, rect, rs->viewport_get_texture(viewport));
|
|
|
|
}
|
2023-01-08 10:41:48 +01:00
|
|
|
|
2024-02-06 12:01:14 +01:00
|
|
|
rs->canvas_item_clear(char_canvas_item);
|
|
|
|
framebuffer_age = tsm_screen_draw(screen, Terminal::_draw_cb, this);
|
|
|
|
attr_texture->update(attr_image);
|
|
|
|
back_texture->update(back_image);
|
2021-07-20 02:18:32 +02:00
|
|
|
}
|
2023-01-20 22:37:26 +01:00
|
|
|
|
2024-02-06 12:01:14 +01:00
|
|
|
void Terminal::refresh() {
|
|
|
|
framebuffer_age = 0;
|
|
|
|
queue_redraw();
|
2023-01-20 22:37:26 +01:00
|
|
|
}
|
|
|
|
|
2024-02-06 12:01:14 +01:00
|
|
|
void Terminal::cleanup_rendering() {
|
|
|
|
// Background.
|
|
|
|
rs->free_rid(back_canvas_item);
|
|
|
|
|
|
|
|
// Foreground.
|
|
|
|
rs->free_rid(viewport);
|
|
|
|
rs->free_rid(canvas);
|
|
|
|
rs->free_rid(char_canvas_item);
|
|
|
|
rs->free_rid(char_material);
|
|
|
|
rs->free_rid(char_shader);
|
2023-01-20 22:37:26 +01:00
|
|
|
}
|
2024-02-07 10:26:45 +01:00
|
|
|
|
|
|
|
void Terminal::set_blink_on_time(const float time)
|
|
|
|
{
|
|
|
|
blink_on_time = time;
|
|
|
|
fore_material->set_shader_parameter("blink_on_time", blink_on_time);
|
|
|
|
}
|
|
|
|
|
|
|
|
float Terminal::get_blink_on_time() const
|
|
|
|
{
|
|
|
|
return blink_on_time;
|
|
|
|
}
|
|
|
|
|
|
|
|
void Terminal::set_blink_off_time(const float time)
|
|
|
|
{
|
|
|
|
blink_off_time = time;
|
|
|
|
fore_material->set_shader_parameter("blink_off_time", blink_off_time);
|
|
|
|
}
|
|
|
|
|
|
|
|
float Terminal::get_blink_off_time() const
|
|
|
|
{
|
|
|
|
return blink_off_time;
|
2024-02-07 11:03:11 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
void Terminal::set_inverse_mode(const int mode) {
|
|
|
|
inverse_mode = static_cast<InverseMode>(mode);
|
|
|
|
|
|
|
|
bool inverse_enabled = inverse_mode == InverseMode::INVERSE_MODE_INVERT;
|
|
|
|
back_material->set_shader_parameter("inverse_enabled", inverse_enabled);
|
|
|
|
fore_material->set_shader_parameter("inverse_enabled", inverse_enabled);
|
|
|
|
|
|
|
|
refresh();
|
|
|
|
}
|
|
|
|
|
|
|
|
int Terminal::get_inverse_mode() const {
|
|
|
|
return static_cast<int>(inverse_mode);
|
2024-02-07 10:26:45 +01:00
|
|
|
}
|