Crude resize working

Former-commit-id: 6b92606d99
This commit is contained in:
Leroy Hopson 2020-07-11 19:14:25 +07:00
parent 6e938f03bf
commit bc86b92412
7 changed files with 177 additions and 100 deletions

View file

@ -1 +1 @@
ae254c9a4443cc28cdd000971eaf3133f690d2bd 0ecaef63a90e5b7cc5f1af692f4e6658886dcbcf

View file

@ -1,54 +1,59 @@
#include "terminal.h" #include "terminal.h"
#include <algorithm>
#include <Theme.hpp> #include <Theme.hpp>
using namespace godot; using namespace godot;
// Use xterm default for default color palette. // Use xterm default for default color palette.
const uint8_t Terminal::default_color_palette[TSM_COLOR_NUM][3] = { const uint8_t Terminal::default_color_palette[TSM_COLOR_NUM][3] = {
[TSM_COLOR_BLACK] = { 0x00, 0x00, 0x00 }, [TSM_COLOR_BLACK] = {0x00, 0x00, 0x00},
[TSM_COLOR_RED] = { 0x80, 0x00, 0x00 }, [TSM_COLOR_RED] = {0x80, 0x00, 0x00},
[TSM_COLOR_GREEN] = { 0x00, 0x80, 0x00 }, [TSM_COLOR_GREEN] = {0x00, 0x80, 0x00},
[TSM_COLOR_YELLOW] = { 0x80, 0x80, 0x00 }, [TSM_COLOR_YELLOW] = {0x80, 0x80, 0x00},
[TSM_COLOR_BLUE] = { 0x00, 0x00, 0x80 }, [TSM_COLOR_BLUE] = {0x00, 0x00, 0x80},
[TSM_COLOR_MAGENTA] = { 0x80, 0x00, 0x80 }, [TSM_COLOR_MAGENTA] = {0x80, 0x00, 0x80},
[TSM_COLOR_CYAN] = { 0x00, 0x80, 0x80 }, [TSM_COLOR_CYAN] = {0x00, 0x80, 0x80},
[TSM_COLOR_LIGHT_GREY] = { 0xc0, 0xc0, 0xc0 }, [TSM_COLOR_LIGHT_GREY] = {0xc0, 0xc0, 0xc0},
[TSM_COLOR_DARK_GREY] = { 0x80, 0x80, 0x80 }, [TSM_COLOR_DARK_GREY] = {0x80, 0x80, 0x80},
[TSM_COLOR_LIGHT_RED] = { 0xff, 0x00, 0x00 }, [TSM_COLOR_LIGHT_RED] = {0xff, 0x00, 0x00},
[TSM_COLOR_LIGHT_GREEN] = { 0x00, 0xff, 0x00 }, [TSM_COLOR_LIGHT_GREEN] = {0x00, 0xff, 0x00},
[TSM_COLOR_LIGHT_YELLOW] = { 0xff, 0xff, 0x00 }, [TSM_COLOR_LIGHT_YELLOW] = {0xff, 0xff, 0x00},
[TSM_COLOR_LIGHT_BLUE] = { 0x00, 0x00, 0xff }, [TSM_COLOR_LIGHT_BLUE] = {0x00, 0x00, 0xff},
[TSM_COLOR_LIGHT_MAGENTA] = { 0xff, 0x00, 0xff }, [TSM_COLOR_LIGHT_MAGENTA] = {0xff, 0x00, 0xff},
[TSM_COLOR_LIGHT_CYAN] = { 0x00, 0xff, 0xff }, [TSM_COLOR_LIGHT_CYAN] = {0x00, 0xff, 0xff},
[TSM_COLOR_WHITE] = { 0xff, 0xff, 0xff }, [TSM_COLOR_WHITE] = {0xff, 0xff, 0xff},
[TSM_COLOR_FOREGROUND] = { 0xff, 0xff, 0xff }, [TSM_COLOR_FOREGROUND] = {0xff, 0xff, 0xff},
[TSM_COLOR_BACKGROUND] = { 0x00, 0x00, 0x00 }, [TSM_COLOR_BACKGROUND] = {0x00, 0x00, 0x00},
}; };
static struct { static struct
{
Color col; Color col;
bool is_set; bool is_set;
} colours[16]; } colours[16];
static void term_output(const char *s, size_t len, void *user) { static void term_output(const char *s, size_t len, void *user)
{
} }
static void write_cb(struct tsm_vte *vte, const char *u8, size_t len, void *data) { static void write_cb(struct tsm_vte *vte, const char *u8, size_t len, void *data)
{
Terminal *term = static_cast<Terminal *>(data); Terminal *term = static_cast<Terminal *>(data);
} }
static int text_draw_cb(struct tsm_screen *con, static int text_draw_cb(struct tsm_screen *con,
uint64_t id, uint64_t id,
const uint32_t *ch, const uint32_t *ch,
size_t len, size_t len,
unsigned int width, unsigned int width,
unsigned int posx, unsigned int posx,
unsigned int posy, unsigned int posy,
const struct tsm_screen_attr *attr, const struct tsm_screen_attr *attr,
tsm_age_t age, tsm_age_t age,
void *data) { void *data)
{
Terminal *terminal = static_cast<Terminal *>(data); Terminal *terminal = static_cast<Terminal *>(data);
@ -56,23 +61,28 @@ static int text_draw_cb(struct tsm_screen *con,
return 0; return 0;
size_t ulen; size_t ulen;
char buf[5] = { 0 }; char buf[5] = {0};
if (len > 0) { if (len > 0)
{
char *utf8 = tsm_ucs4_to_utf8_alloc(ch, len, &ulen); char *utf8 = tsm_ucs4_to_utf8_alloc(ch, len, &ulen);
memcpy(terminal->cells[posy][posx].ch, utf8, ulen); memcpy(terminal->cells[posy][posx].ch, utf8, ulen);
} else { }
else
{
terminal->cells[posy][posx] = {}; terminal->cells[posy][posx] = {};
} }
memcpy(&terminal->cells[posy][posx].attr, attr, sizeof(tsm_screen_attr)); memcpy(&terminal->cells[posy][posx].attr, attr, sizeof(tsm_screen_attr));
terminal->update(); if (!terminal->sleep)
terminal->update();
return 0; return 0;
} }
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);
@ -80,89 +90,101 @@ void Terminal::_register_methods() {
register_method("_draw", &Terminal::_draw); register_method("_draw", &Terminal::_draw);
register_method("write", &Terminal::write); register_method("write", &Terminal::write);
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);
} }
Terminal::Terminal() { Terminal::Terminal()
{
} }
Terminal::~Terminal() { Terminal::~Terminal()
{
} }
void Terminal::_init() { void Terminal::_init()
{
sleep = true;
rows = 24; if (tsm_screen_new(&screen, NULL, NULL))
cols = 80; {
for (int x = 0; x < rows; x++) {
Row row(cols);
for (int y = 0; y < cols; y++) {
row[y] = empty_cell;
}
cells.push_back(row);
}
cell_size = Vector2(12, 21); // TODO: Get proper cell_size based on font.
sleep = false;
int ret;
if (tsm_screen_new(&screen, NULL, NULL)) {
ERR_PRINT("Error creating new tsm screen"); ERR_PRINT("Error creating new tsm screen");
} }
tsm_screen_set_max_sb(screen, 1000); // TODO: Use config var for scrollback size. tsm_screen_set_max_sb(screen, 1000); // TODO: Use config var for scrollback size.
if (tsm_vte_new(&vte, screen, write_cb, this, NULL, NULL)) { if (tsm_vte_new(&vte, screen, write_cb, this, NULL, NULL))
{
ERR_PRINT("Error creating new tsm vte"); ERR_PRINT("Error creating new tsm vte");
} }
/* Set the color palette */
update_color_palette(); update_color_palette();
if (tsm_vte_set_custom_palette(vte, color_palette)) { if (tsm_vte_set_custom_palette(vte, color_palette))
{
ERR_PRINT("Error setting custom palette"); ERR_PRINT("Error setting custom palette");
} }
if (tsm_vte_set_palette(vte, "custom")) { if (tsm_vte_set_palette(vte, "custom"))
{
ERR_PRINT("Error setting palette"); ERR_PRINT("Error setting palette");
} }
update_size();
}
void Terminal::_ready()
{
connect("resized", this, "update_size");
}
void Terminal::_notification(int what)
{
switch (what)
{
case NOTIFICATION_RESIZED:
Godot::print("resized!");
update_size();
break;
}
} }
void Terminal::_ready() { void Terminal::_input(Variant event)
{
} }
void Terminal::_input(Variant event) { void Terminal::_draw()
} {
void Terminal::_draw() {
if (sleep) if (sleep)
return; return;
/* Draw the background */ /* Draw the background */
draw_rect(get_rect(), get_color("Background", "Terminal"));
/* Draw the cell backgrounds */
// Draw the background first so subsequent rows don't overlap // Draw the background first so subsequent rows don't overlap
// foreground characters such as y that may extend below the baseline. // foreground characters such as y that may extend below the baseline.
for (int row = 0; row < rows; row++) { for (int row = 0; row < rows; row++)
for (int col = 0; col < cols; col++) { {
for (int col = 0; col < cols; col++)
{
draw_background(row, col, get_cell_colors(row, col).first); draw_background(row, col, get_cell_colors(row, col).first);
} }
} }
/* Draw the foreground */ /* Draw the cell foregrounds */
for (int row = 0; row < rows; row++) { for (int row = 0; row < rows; row++)
for (int col = 0; col < cols; col++) { {
for (int col = 0; col < cols; col++)
{
draw_foreground(row, col, get_cell_colors(row, col).second); draw_foreground(row, col, get_cell_colors(row, col).second);
} }
} }
} }
void Terminal::update_color_palette() { void Terminal::update_color_palette()
{
// Start with a copy of the default color palette // Start with a copy of the default color palette
memcpy(color_palette, Terminal::default_color_palette, sizeof(Terminal::default_color_palette)); memcpy(color_palette, Terminal::default_color_palette, sizeof(Terminal::default_color_palette));
@ -199,7 +221,8 @@ void Terminal::update_color_palette() {
set_pallete_color(TSM_COLOR_FOREGROUND, "Foreground"); set_pallete_color(TSM_COLOR_FOREGROUND, "Foreground");
} }
void Terminal::draw_background(int row, int col, Color bgcolor) { void Terminal::draw_background(int row, int col, Color bgcolor)
{
/* Draw the background */ /* Draw the background */
Vector2 background_pos = Vector2(col * cell_size.x, row * cell_size.y); Vector2 background_pos = Vector2(col * cell_size.x, row * cell_size.y);
@ -207,7 +230,8 @@ void Terminal::draw_background(int row, int col, Color bgcolor) {
draw_rect(background_rect, bgcolor); draw_rect(background_rect, bgcolor);
} }
void Terminal::draw_foreground(int row, int col, Color fgcolor) { void Terminal::draw_foreground(int row, int col, Color fgcolor)
{
struct cell cell = cells[row][col]; struct cell cell = cells[row][col];
@ -215,13 +239,20 @@ void Terminal::draw_foreground(int row, int col, Color fgcolor) {
Ref<Font> fontref = get_font(""); Ref<Font> fontref = get_font("");
if (cell.attr.bold && cell.attr.italic) { if (cell.attr.bold && cell.attr.italic)
{
fontref = get_font("Bold Italic", "Terminal"); fontref = get_font("Bold Italic", "Terminal");
} else if (cell.attr.bold) { }
else if (cell.attr.bold)
{
fontref = get_font("Bold", "Terminal"); fontref = get_font("Bold", "Terminal");
} else if (cell.attr.italic) { }
else if (cell.attr.italic)
{
fontref = get_font("Italic", "Terminal"); fontref = get_font("Italic", "Terminal");
} else { }
else
{
fontref = get_font("Regular", "Terminal"); fontref = get_font("Regular", "Terminal");
} }
@ -241,7 +272,8 @@ void Terminal::draw_foreground(int row, int col, Color fgcolor) {
draw_string(fontref, foreground_pos, "_", fgcolor); draw_string(fontref, foreground_pos, "_", fgcolor);
} }
std::pair<Color, Color> Terminal::get_cell_colors(int row, int col) { std::pair<Color, Color> Terminal::get_cell_colors(int row, int col)
{
struct cell cell = cells[row][col]; struct cell cell = cells[row][col];
Color fgcol, bgcol; Color fgcol, bgcol;
float fr = 1, fg = 1, fb = 1, br = 0, bg = 0, bb = 0; float fr = 1, fg = 1, fb = 1, br = 0, bg = 0, bb = 0;
@ -249,30 +281,38 @@ std::pair<Color, Color> Terminal::get_cell_colors(int row, int col) {
/* Get foreground color */ /* Get foreground color */
if (cell.attr.fccode && palette.count(cell.attr.fccode)) { if (cell.attr.fccode && palette.count(cell.attr.fccode))
{
fgcol = palette[cell.attr.fccode]; fgcol = palette[cell.attr.fccode];
} else { }
else
{
fr = (float)cell.attr.fr / 255.0; fr = (float)cell.attr.fr / 255.0;
fg = (float)cell.attr.fg / 255.0; fg = (float)cell.attr.fg / 255.0;
fb = (float)cell.attr.fb / 255.0; fb = (float)cell.attr.fb / 255.0;
fgcol = Color(fr, fg, fb); fgcol = Color(fr, fg, fb);
if (cell.attr.fccode) { if (cell.attr.fccode)
{
palette.insert(std::pair<int, Color>(cell.attr.fccode, Color(fr, fg, fb))); palette.insert(std::pair<int, Color>(cell.attr.fccode, Color(fr, fg, fb)));
} }
} }
/* Get background color */ /* Get background color */
if (cell.attr.bccode && palette.count(cell.attr.bccode)) { if (cell.attr.bccode && palette.count(cell.attr.bccode))
{
bgcol = palette[cell.attr.bccode]; bgcol = palette[cell.attr.bccode];
} else { }
else
{
br = (float)cell.attr.br / 255.0; br = (float)cell.attr.br / 255.0;
bg = (float)cell.attr.bg / 255.0; bg = (float)cell.attr.bg / 255.0;
bb = (float)cell.attr.bb / 255.0; bb = (float)cell.attr.bb / 255.0;
bgcol = Color(br, bg, bb); bgcol = Color(br, bg, bb);
if (cell.attr.bccode) { if (cell.attr.bccode)
{
palette.insert(std::pair<int, Color>(cell.attr.bccode, Color(br, bg, bb))); palette.insert(std::pair<int, Color>(cell.attr.bccode, Color(br, bg, bb)));
} }
} }
@ -283,8 +323,40 @@ std::pair<Color, Color> Terminal::get_cell_colors(int row, int col) {
return std::make_pair(bgcol, fgcol); return std::make_pair(bgcol, fgcol);
} }
void Terminal::write(PoolByteArray data) { // Recalculates the cell_size and number of cols/rows based on font size and the Control's rect_size
void Terminal::update_size()
{
sleep = true;
cell_size = get_font("Regular", "Terminal").ptr()->get_string_size("W");
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));
Godot::print(String("resized_rows: {0}, resized_cols: {1}").format(Array::make(rows, cols)));
cells = {};
for (int x = 0; x < rows; x++)
{
Row row(cols);
for (int y = 0; y < cols; y++)
{
row[y] = empty_cell;
}
cells.push_back(row);
}
tsm_screen_resize(screen, cols, rows);
sleep = false;
update();
}
void Terminal::write(PoolByteArray data)
{
tsm_vte_input(vte, (char *)data.read().ptr(), data.size()); tsm_vte_input(vte, (char *)data.read().ptr(), data.size());
framebuffer_age = tsm_screen_draw(screen, text_draw_cb, this); framebuffer_age = tsm_screen_draw(screen, text_draw_cb, this);
} }

View file

@ -8,19 +8,22 @@
#include <map> #include <map>
#include <vector> #include <vector>
namespace godot { namespace godot
{
class Terminal : public Control { class Terminal : public Control
{
GODOT_CLASS(Terminal, Control) GODOT_CLASS(Terminal, Control)
public: public:
struct cell { struct cell
{
char ch[5]; char ch[5];
struct tsm_screen_attr attr; struct tsm_screen_attr attr;
} empty_cell = { ch : { 0, 0, 0, 0, 0 }, attr : {} }; } empty_cell = {ch : {0, 0, 0, 0, 0}, attr : {}};
public: public:
typedef std::vector<std::vector<struct cell> > Cells; typedef std::vector<std::vector<struct cell>> Cells;
typedef std::vector<struct cell> Row; typedef std::vector<struct cell> Row;
Cells cells; Cells cells;
@ -35,6 +38,8 @@ private:
Vector2 cell_size; Vector2 cell_size;
std::map<int, Color> palette = {}; std::map<int, Color> palette = {};
void update_size();
void update_color_palette(); void update_color_palette();
std::pair<Color, Color> get_cell_colors(int row, int col); std::pair<Color, Color> get_cell_colors(int row, int col);
void draw_background(int row, int col, Color bgcol); void draw_background(int row, int col, Color bgcol);
@ -48,6 +53,7 @@ public:
void _init(); void _init();
void _ready(); void _ready();
void _notification(int what);
void _input(Variant event); void _input(Variant event);
void _draw(); void _draw();

View file

@ -6,6 +6,8 @@
[ext_resource path="res://examples/terminal/container.gd" type="Script" id=4] [ext_resource path="res://examples/terminal/container.gd" type="Script" id=4]
[node name="Container" type="Container"] [node name="Container" type="Container"]
margin_right = 40.0
margin_bottom = 40.0
script = ExtResource( 4 ) script = ExtResource( 4 )
__meta__ = { __meta__ = {
"_edit_use_anchors_": false "_edit_use_anchors_": false
@ -16,9 +18,6 @@ margin_right = 40.0
margin_bottom = 40.0 margin_bottom = 40.0
theme = ExtResource( 2 ) theme = ExtResource( 2 )
script = ExtResource( 1 ) script = ExtResource( 1 )
__meta__ = {
"_edit_use_anchors_": false
}
[node name="Pseudoterminal" type="Node" parent="."] [node name="Pseudoterminal" type="Node" parent="."]
script = ExtResource( 3 ) script = ExtResource( 3 )