Yield for "frame_pre_draw" signal before writing to terminal

Fixes #41. But creates another issue where sometimes the yield will
resume after the terminal node has already been freed logging an error
to the console.

Also a few changes to where update is called it the gdnative terminal
code.

Also changed gdnative terminal to only accept strings.
This commit is contained in:
Leroy Hopson 2021-07-03 00:04:34 +07:00 committed by Leroy Hopson
parent 4e6715329a
commit bfa561357e
3 changed files with 34 additions and 32 deletions

View file

@ -1,3 +1,5 @@
// Copyright (c) 2021, Leroy Hopson (MIT License).
#include "terminal.h" #include "terminal.h"
#include <Dictionary.hpp> #include <Dictionary.hpp>
#include <InputEventKey.hpp> #include <InputEventKey.hpp>
@ -543,36 +545,14 @@ 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));
emit_signal("size_changed", Vector2(cols, rows));
tsm_screen_resize(screen, cols, rows); tsm_screen_resize(screen, cols, rows);
update(); emit_signal("size_changed", Vector2(cols, rows));
} }
void Terminal::write(Variant data) { void Terminal::write(String data) {
const char *u8; const char *u8 = data.alloc_c_string();
size_t len; size_t len = strlen(u8);
switch (data.get_type()) {
case Variant::Type::POOL_BYTE_ARRAY: {
PoolByteArray bytes = data;
u8 = (char *)bytes.read().ptr();
len = bytes.size();
break;
}
case Variant::Type::STRING: {
String string = data;
u8 = string.alloc_c_string();
len = strlen(u8);
break;
}
default:
WARN_PRINT("Method expected a String or PoolByteArray");
return;
}
tsm_vte_input(vte, u8, len); tsm_vte_input(vte, u8, len);
update();
} }

View file

@ -1,3 +1,5 @@
// Copyright (c) 2021, Leroy Hopson (MIT License).
#ifndef TERMINAL_H #ifndef TERMINAL_H
#define TERMINAL_H #define TERMINAL_H
@ -52,7 +54,7 @@ public:
void _gui_input(Variant event); void _gui_input(Variant event);
void _draw(); void _draw();
void write(Variant data); void write(String data);
enum UpdateMode { enum UpdateMode {
DISABLED, DISABLED,

View file

@ -16,13 +16,18 @@ enum UpdateMode {
export (UpdateMode) var update_mode = UpdateMode.AUTO setget set_update_mode export (UpdateMode) var update_mode = UpdateMode.AUTO setget set_update_mode
var rows: int setget , get_rows # TODO: Show in inspector. var cols = 2
var cols: int setget , get_cols # TODO: Show in inspector. var rows = 2
var _viewport: Viewport = preload("./viewport.tscn").instance() var _viewport: Viewport = preload("./viewport.tscn").instance()
var _native_terminal: Control = _viewport.get_node("Terminal") var _native_terminal: Control = _viewport.get_node("Terminal")
var _screen := TextureRect.new() var _screen := TextureRect.new()
var _visibility_notifier := VisibilityNotifier2D.new() var _visibility_notifier := VisibilityNotifier2D.new()
var _dirty := false
var buffer := StreamPeerBuffer.new()
var times = 0
func set_update_mode(value): func set_update_mode(value):
@ -31,16 +36,22 @@ func set_update_mode(value):
func get_rows() -> int: func get_rows() -> int:
return _native_terminal.rows return 0
func get_cols() -> int: func get_cols() -> int:
return _native_terminal.cols return 0
func write(data) -> void: func write(data) -> void:
assert(data is String or data is PoolByteArray) assert(data is String or data is PoolByteArray)
_native_terminal.write(data)
# FIXME: This will occasionally cause a "Resumed function after yield, but class instance is gone" error after freeing the Terminal instance.
# However, this yield is necessary to ensure the terminal state machines framebuffer is up to date when we make all the draw_* calls.
yield(VisualServer, "frame_pre_draw")
_native_terminal.write(data if data is String else data.get_string_from_utf8())
_native_terminal.update()
func _ready(): func _ready():
@ -96,4 +107,13 @@ func _on_key_pressed(data: String, event: InputEventKey):
func _on_size_changed(new_size: Vector2): func _on_size_changed(new_size: Vector2):
cols = new_size.x
rows = new_size.y
emit_signal("size_changed", new_size) emit_signal("size_changed", new_size)
func _set_size_warning(value):
if value:
push_warning(
"Terminal cols and rows are read only and determined by the font and rect sizes."
)