mirror of
https://github.com/lihop/godot-xterm.git
synced 2024-11-10 04:40:25 +01:00
Add rudimentary terminal to editor's bottom panel
In order to use the gdnative library as an editor plugin it was neccessary to set the `reloadable` property of the gdnlib file to false, in order to prevent crashes when the godot editor window lost focus. This may have consequences when recompiling the library. See: https://docs.godotengine.org/en/3.3/classes/class_gdnativelibrary.html#class-gdnativelibrary-property-reloadable Still crashes quite frequently and doesn't close child processes properly. Part of #43.
This commit is contained in:
parent
33e4640b4b
commit
5e25ebbab6
7 changed files with 320 additions and 1 deletions
|
@ -0,0 +1,78 @@
|
||||||
|
tool
|
||||||
|
extends "res://addons/godot_xterm/nodes/terminal/terminal.gd"
|
||||||
|
|
||||||
|
var editor_settings: EditorSettings
|
||||||
|
var timer := Timer.new()
|
||||||
|
|
||||||
|
onready var pty = $PTY
|
||||||
|
|
||||||
|
|
||||||
|
# Sets terminal colors according to a dictionary that maps terminal color names
|
||||||
|
# to TextEditor theme color names.
|
||||||
|
func _set_terminal_colors(color_map: Dictionary) -> void:
|
||||||
|
for key in color_map.keys():
|
||||||
|
var val: String = color_map[key]
|
||||||
|
var color: Color = editor_settings.get_setting("text_editor/highlighting/%s" % val)
|
||||||
|
theme.set_color(key, "Terminal", color)
|
||||||
|
|
||||||
|
|
||||||
|
func _ready():
|
||||||
|
if not editor_settings:
|
||||||
|
return
|
||||||
|
|
||||||
|
theme = Theme.new()
|
||||||
|
|
||||||
|
# Use the same font as EditorLog.
|
||||||
|
theme.default_font = get_font("output_source", "EditorFonts")
|
||||||
|
|
||||||
|
# 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.
|
||||||
|
_set_terminal_colors(
|
||||||
|
{
|
||||||
|
"Black": "caret_background_color",
|
||||||
|
"Red": "keyword_color",
|
||||||
|
"Green": "gdscript/node_path_color",
|
||||||
|
"Yellow": "string_color",
|
||||||
|
"Blue": "function_color",
|
||||||
|
"Magenta": "symbol_color",
|
||||||
|
"Cyan": "gdscript/function_definition_color",
|
||||||
|
"Dark Grey": "comment_color",
|
||||||
|
"Light Grey": "text_color",
|
||||||
|
"Light Red": "breakpoint_color",
|
||||||
|
"Light Green": "base_type_color",
|
||||||
|
"Light Yellow": "search_result_color",
|
||||||
|
"Light Blue": "member_variable_color",
|
||||||
|
"Light Magenta": "code_folding_color",
|
||||||
|
"Light Cyan": "user_type_color",
|
||||||
|
"White": "text_selected_color",
|
||||||
|
"Background": "background_color",
|
||||||
|
"Foreground": "caret_color",
|
||||||
|
}
|
||||||
|
)
|
||||||
|
_native_terminal._update_theme()
|
||||||
|
|
||||||
|
# In editor _process is not called continuously unless the "Update Continuously"
|
||||||
|
# editor setting is enabled. This setting is disabled by default and uses 100%
|
||||||
|
# of one core when enabled, so best to leave it off and use a timer instead.
|
||||||
|
add_child(timer)
|
||||||
|
timer.wait_time = 0.025
|
||||||
|
timer.connect("timeout", self, "_poll")
|
||||||
|
timer.start()
|
||||||
|
|
||||||
|
|
||||||
|
func _poll():
|
||||||
|
if pty and pty._pipe:
|
||||||
|
pty._pipe.poll()
|
||||||
|
update()
|
||||||
|
|
||||||
|
|
||||||
|
func _input(event):
|
||||||
|
if not has_focus():
|
||||||
|
return
|
||||||
|
|
||||||
|
# We need to handle many input events otherwise keys such as TAB, ctrl, etc.
|
||||||
|
# will trigger editor shortcuts when using them in the terminal.
|
||||||
|
if event is InputEventKey:
|
||||||
|
get_tree().set_input_as_handled()
|
||||||
|
_gui_input(event)
|
|
@ -0,0 +1,24 @@
|
||||||
|
[gd_scene load_steps=3 format=2]
|
||||||
|
|
||||||
|
[ext_resource path="res://addons/godot_xterm/editor_plugins/terminal/editor_terminal.gd" type="Script" id=1]
|
||||||
|
[ext_resource path="res://addons/godot_xterm/nodes/pty/unix/pty_unix.gd" type="Script" id=2]
|
||||||
|
|
||||||
|
[node name="Terminal" type="Control"]
|
||||||
|
anchor_right = 1.0
|
||||||
|
anchor_bottom = 1.0
|
||||||
|
focus_mode = 1
|
||||||
|
size_flags_horizontal = 4
|
||||||
|
size_flags_vertical = 4
|
||||||
|
script = ExtResource( 1 )
|
||||||
|
__meta__ = {
|
||||||
|
"_edit_use_anchors_": false
|
||||||
|
}
|
||||||
|
copy_on_selection = true
|
||||||
|
|
||||||
|
[node name="PTY" type="Node" parent="."]
|
||||||
|
script = ExtResource( 2 )
|
||||||
|
terminal_path = NodePath("..")
|
||||||
|
env = {
|
||||||
|
"COLORTERM": "truecolor",
|
||||||
|
"TERM": "xterm-256color"
|
||||||
|
}
|
110
addons/godot_xterm/editor_plugins/terminal/terminal_panel.gd
Normal file
110
addons/godot_xterm/editor_plugins/terminal/terminal_panel.gd
Normal file
|
@ -0,0 +1,110 @@
|
||||||
|
# Copyright (c) 2021, Leroy Hopson (MIT License).
|
||||||
|
#
|
||||||
|
# This file contains snippets of code derived from Godot's editor_node.cpp file.
|
||||||
|
# These snippets are copyright of their authors and released under the MIT license:
|
||||||
|
# - Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur (MIT License).
|
||||||
|
# - Copyright (c) 2014-2021 Godot Engine contributors (MIT License).
|
||||||
|
tool
|
||||||
|
extends Control
|
||||||
|
|
||||||
|
const EditorTerminal := preload("./editor_terminal.tscn")
|
||||||
|
|
||||||
|
# Has access to the EditorSettings singleton so it can dynamically generate the
|
||||||
|
# terminal color scheme based on editor theme settings.
|
||||||
|
var editor_interface: EditorInterface
|
||||||
|
|
||||||
|
onready var editor_settings: EditorSettings = editor_interface.get_editor_settings()
|
||||||
|
onready var tabs: Tabs = $VBoxContainer/TabbarContainer/Tabs
|
||||||
|
onready var tabbar_container: HBoxContainer = $VBoxContainer/TabbarContainer
|
||||||
|
onready var add_button: ToolButton = $VBoxContainer/TabbarContainer/Tabs/AddButton
|
||||||
|
onready var tab_container: TabContainer = $VBoxContainer/TabContainer
|
||||||
|
onready var ready := true
|
||||||
|
|
||||||
|
var _theme := Theme.new()
|
||||||
|
var _tab_container_min_size
|
||||||
|
|
||||||
|
|
||||||
|
func _ready():
|
||||||
|
tab_container.add_stylebox_override("panel", get_stylebox("Background", "EditorStyles"))
|
||||||
|
_update_settings()
|
||||||
|
|
||||||
|
|
||||||
|
func _update_settings() -> void:
|
||||||
|
var editor_scale: float = editor_interface.get_editor_scale()
|
||||||
|
rect_min_size = Vector2(0, tabbar_container.rect_size.y + 182) * editor_scale
|
||||||
|
|
||||||
|
# Use the same policy as editor scene tabs.
|
||||||
|
tabs.tab_close_display_policy = (
|
||||||
|
Tabs.CLOSE_BUTTON_SHOW_ALWAYS
|
||||||
|
if editor_settings.get_setting("interface/scene_tabs/always_show_close_button")
|
||||||
|
else Tabs.CLOSE_BUTTON_SHOW_ACTIVE_ONLY
|
||||||
|
)
|
||||||
|
|
||||||
|
_update_terminal_tabs()
|
||||||
|
|
||||||
|
|
||||||
|
func _update_terminal_tabs():
|
||||||
|
# Wait a couple of frames to allow everything to resize before updating.
|
||||||
|
yield(get_tree(), "idle_frame")
|
||||||
|
yield(get_tree(), "idle_frame")
|
||||||
|
|
||||||
|
if tabs.get_offset_buttons_visible():
|
||||||
|
# Move add button to fixed position on the tabbar.
|
||||||
|
if add_button.get_parent() == tabs:
|
||||||
|
add_button.rect_position = Vector2.ZERO
|
||||||
|
tabs.remove_child(add_button)
|
||||||
|
tabbar_container.add_child(add_button)
|
||||||
|
tabbar_container.move_child(add_button, 0)
|
||||||
|
else:
|
||||||
|
# Move add button after last tab.
|
||||||
|
if add_button.get_parent() == tabbar_container:
|
||||||
|
tabbar_container.remove_child(add_button)
|
||||||
|
tabs.add_child(add_button)
|
||||||
|
var last_tab := Rect2()
|
||||||
|
if tabs.get_tab_count() > 0:
|
||||||
|
last_tab = tabs.get_tab_rect(tabs.get_tab_count() - 1)
|
||||||
|
add_button.rect_position = Vector2(
|
||||||
|
last_tab.position.x + last_tab.size.x + 3, last_tab.position.y
|
||||||
|
)
|
||||||
|
|
||||||
|
# Make sure we still own the button, so it gets saved with our scene.
|
||||||
|
add_button.owner = self
|
||||||
|
|
||||||
|
|
||||||
|
func _on_AddButton_pressed():
|
||||||
|
var shell = OS.get_environment("SHELL") if OS.has_environment("SHELL") else "sh"
|
||||||
|
var terminal := EditorTerminal.instance()
|
||||||
|
tabs.add_tab(shell.get_file())
|
||||||
|
terminal.editor_settings = editor_settings
|
||||||
|
terminal.set_anchors_preset(PRESET_WIDE)
|
||||||
|
tab_container.add_child(terminal)
|
||||||
|
terminal.pty.fork(shell)
|
||||||
|
terminal.grab_focus()
|
||||||
|
tabs.current_tab = tabs.get_tab_count() - 1
|
||||||
|
tab_container.current_tab = tabs.current_tab
|
||||||
|
_update_terminal_tabs()
|
||||||
|
|
||||||
|
|
||||||
|
func _on_Tabs_tab_changed(tab_index):
|
||||||
|
tab_container.current_tab = tab_index
|
||||||
|
tab_container.get_child(tab_index).grab_focus()
|
||||||
|
|
||||||
|
|
||||||
|
func _on_Tabs_tab_close(tab_index):
|
||||||
|
tabs.remove_tab(tab_index)
|
||||||
|
tab_container.get_child(tab_index).queue_free()
|
||||||
|
_update_terminal_tabs()
|
||||||
|
|
||||||
|
|
||||||
|
func _notification(what):
|
||||||
|
if not ready:
|
||||||
|
return
|
||||||
|
|
||||||
|
match what:
|
||||||
|
EditorSettings.NOTIFICATION_EDITOR_SETTINGS_CHANGED:
|
||||||
|
_update_settings()
|
||||||
|
_update_terminal_tabs()
|
||||||
|
NOTIFICATION_RESIZED:
|
||||||
|
_update_terminal_tabs()
|
||||||
|
NOTIFICATION_WM_FOCUS_IN:
|
||||||
|
_update_terminal_tabs()
|
100
addons/godot_xterm/editor_plugins/terminal/terminal_panel.tscn
Normal file
100
addons/godot_xterm/editor_plugins/terminal/terminal_panel.tscn
Normal file
|
@ -0,0 +1,100 @@
|
||||||
|
[gd_scene load_steps=7 format=2]
|
||||||
|
|
||||||
|
[ext_resource path="res://addons/godot_xterm/editor_plugins/terminal/terminal_panel.gd" type="Script" id=1]
|
||||||
|
|
||||||
|
[sub_resource type="Image" id=6]
|
||||||
|
data = {
|
||||||
|
"data": PoolByteArray( 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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": "LumAlpha8",
|
||||||
|
"height": 16,
|
||||||
|
"mipmaps": false,
|
||||||
|
"width": 16
|
||||||
|
}
|
||||||
|
|
||||||
|
[sub_resource type="ImageTexture" id=2]
|
||||||
|
flags = 4
|
||||||
|
flags = 4
|
||||||
|
image = SubResource( 6 )
|
||||||
|
size = Vector2( 16, 16 )
|
||||||
|
|
||||||
|
[sub_resource type="StyleBoxTexture" id=3]
|
||||||
|
texture = SubResource( 2 )
|
||||||
|
region_rect = Rect2( 0, 0, 16, 16 )
|
||||||
|
margin_left = 2.0
|
||||||
|
margin_right = 2.0
|
||||||
|
margin_top = 2.0
|
||||||
|
margin_bottom = 2.0
|
||||||
|
|
||||||
|
[sub_resource type="Image" id=7]
|
||||||
|
data = {
|
||||||
|
"data": PoolByteArray( 0, 0, 0, 0, 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",
|
||||||
|
"height": 16,
|
||||||
|
"mipmaps": false,
|
||||||
|
"width": 16
|
||||||
|
}
|
||||||
|
|
||||||
|
[sub_resource type="ImageTexture" id=5]
|
||||||
|
flags = 0
|
||||||
|
flags = 0
|
||||||
|
image = SubResource( 7 )
|
||||||
|
size = Vector2( 16, 16 )
|
||||||
|
|
||||||
|
[node name="Panel" type="Panel"]
|
||||||
|
anchor_right = 1.0
|
||||||
|
anchor_bottom = 1.0
|
||||||
|
margin_top = -3.0
|
||||||
|
rect_min_size = Vector2( 0, 34 )
|
||||||
|
custom_styles/panel = SubResource( 3 )
|
||||||
|
script = ExtResource( 1 )
|
||||||
|
__meta__ = {
|
||||||
|
"_edit_use_anchors_": false
|
||||||
|
}
|
||||||
|
|
||||||
|
[node name="VBoxContainer" type="VBoxContainer" parent="."]
|
||||||
|
anchor_right = 1.0
|
||||||
|
anchor_bottom = 1.0
|
||||||
|
rect_min_size = Vector2( 0, 24 )
|
||||||
|
custom_constants/separation = 0
|
||||||
|
__meta__ = {
|
||||||
|
"_edit_use_anchors_": false
|
||||||
|
}
|
||||||
|
|
||||||
|
[node name="TabbarContainer" type="HBoxContainer" parent="VBoxContainer"]
|
||||||
|
margin_right = 1024.0
|
||||||
|
margin_bottom = 24.0
|
||||||
|
|
||||||
|
[node name="Tabs" type="Tabs" parent="VBoxContainer/TabbarContainer"]
|
||||||
|
margin_right = 1024.0
|
||||||
|
margin_bottom = 24.0
|
||||||
|
size_flags_horizontal = 3
|
||||||
|
tab_align = 0
|
||||||
|
tab_close_display_policy = 1
|
||||||
|
__meta__ = {
|
||||||
|
"_edit_use_anchors_": false
|
||||||
|
}
|
||||||
|
|
||||||
|
[node name="AddButton" type="ToolButton" parent="VBoxContainer/TabbarContainer/Tabs"]
|
||||||
|
margin_left = 3.0
|
||||||
|
margin_right = 31.0
|
||||||
|
margin_bottom = 24.0
|
||||||
|
hint_tooltip = "Add a new scene."
|
||||||
|
icon = SubResource( 5 )
|
||||||
|
__meta__ = {
|
||||||
|
"_edit_use_anchors_": false
|
||||||
|
}
|
||||||
|
|
||||||
|
[node name="TabContainer" type="TabContainer" parent="VBoxContainer"]
|
||||||
|
margin_top = 24.0
|
||||||
|
margin_right = 1024.0
|
||||||
|
margin_bottom = 603.0
|
||||||
|
rect_clip_content = true
|
||||||
|
size_flags_vertical = 3
|
||||||
|
custom_styles/panel = SubResource( 3 )
|
||||||
|
custom_constants/top_margin = 0
|
||||||
|
custom_constants/side_margin = 0
|
||||||
|
tabs_visible = false
|
||||||
|
|
||||||
|
[connection signal="tab_changed" from="VBoxContainer/TabbarContainer/Tabs" to="." method="_on_Tabs_tab_changed"]
|
||||||
|
[connection signal="tab_close" from="VBoxContainer/TabbarContainer/Tabs" to="." method="_on_Tabs_tab_close"]
|
||||||
|
[connection signal="pressed" from="VBoxContainer/TabbarContainer/Tabs/AddButton" to="." method="_on_AddButton_pressed"]
|
|
@ -3,7 +3,7 @@
|
||||||
singleton=false
|
singleton=false
|
||||||
load_once=true
|
load_once=true
|
||||||
symbol_prefix="godot_"
|
symbol_prefix="godot_"
|
||||||
reloadable=true
|
reloadable=false
|
||||||
|
|
||||||
[entry]
|
[entry]
|
||||||
|
|
||||||
|
|
|
@ -108,6 +108,7 @@ func _ready():
|
||||||
|
|
||||||
|
|
||||||
func _refresh():
|
func _refresh():
|
||||||
|
_screen.update()
|
||||||
if update_mode == UpdateMode.AUTO:
|
if update_mode == UpdateMode.AUTO:
|
||||||
_native_terminal.update_mode = UpdateMode.ALL_NEXT_FRAME
|
_native_terminal.update_mode = UpdateMode.ALL_NEXT_FRAME
|
||||||
|
|
||||||
|
|
|
@ -3,6 +3,7 @@ extends EditorPlugin
|
||||||
|
|
||||||
var pty_supported := OS.get_name() in ["X11", "Server", "OSX"]
|
var pty_supported := OS.get_name() in ["X11", "Server", "OSX"]
|
||||||
var asciicast_import_plugin
|
var asciicast_import_plugin
|
||||||
|
var terminal_panel: Control
|
||||||
|
|
||||||
|
|
||||||
func _enter_tree():
|
func _enter_tree():
|
||||||
|
@ -23,6 +24,9 @@ func _enter_tree():
|
||||||
"X11", "Server", "OSX":
|
"X11", "Server", "OSX":
|
||||||
pty_script = load("res://addons/godot_xterm/nodes/pty/unix/pty_unix.gd")
|
pty_script = load("res://addons/godot_xterm/nodes/pty/unix/pty_unix.gd")
|
||||||
add_custom_type("PTY", "Node", pty_script, pty_icon)
|
add_custom_type("PTY", "Node", pty_script, pty_icon)
|
||||||
|
terminal_panel = preload("./editor_plugins/terminal/terminal_panel.tscn").instance()
|
||||||
|
terminal_panel.editor_interface = get_editor_interface()
|
||||||
|
add_control_to_bottom_panel(terminal_panel, "Terminal")
|
||||||
|
|
||||||
|
|
||||||
func _exit_tree():
|
func _exit_tree():
|
||||||
|
@ -34,3 +38,5 @@ func _exit_tree():
|
||||||
|
|
||||||
if pty_supported:
|
if pty_supported:
|
||||||
remove_custom_type("PTY")
|
remove_custom_type("PTY")
|
||||||
|
remove_control_from_bottom_panel(terminal_panel)
|
||||||
|
terminal_panel.free()
|
||||||
|
|
Loading…
Reference in a new issue