...seems simple enough:
Make a dock scene, load it, add it, done. Like any other dock, right?
extends EditorPlugin
var dock: Control
func _enter_tree():
dock = preload("res://addons/tab_dock/dock.tscn").instance()
add_control_to_bottom_panel(dock, 'Tab Dock')
Perfect!
Wait, why do we have a border around everything and the debugger doesn't?
To investigate, I've used the editor debugger addon. It can show the editor nodes in the inspector, so you can have a good look at all of their properties.
Let's have a look how Godot does it. Ah, here we have it - github.com/godotengine/godot/blob/.../editor/editor_node.cpp
void EditorNode::_bottom_panel_switch(bool p_enable, int p_idx) {
// other stuff
if (p_enable) { // <- ah, when they are enabling it
if (EditorDebuggerNode::get_singleton() == bottom_panel_items[p_idx].control) {
// This is the debug panel which uses tabs, so the top section should be smaller.
bottom_panel->add_theme_style_override("panel", gui_base->get_theme_stylebox(SNAME("BottomPanelDebuggerOverride"), SNAME("EditorStyles")));
} else {
bottom_panel->add_theme_style_override("panel", gui_base->get_theme_stylebox(SNAME("BottomPanel"), SNAME("EditorStyles")));
}
}
}
So, they are using a specific override panel there and they set it when the tab switches. Cool, we can do that too!
Let's get the base theme first. We can get that in the EditorPlugin script and just pass it to the dock
func _enter_tree():
dock = preload("res://addons/tab_dock/dock.tscn").instance()
dock.base_theme = get_editor_interface().get_base_control().theme
add_control_to_bottom_panel(dock, 'Tab Dock')
Then we take it in the dock script and just override it when the visibility changes
"it" in this case means two nodes above our dock, since the dock is not the panel itself. I called that parent tab_parent_bottom_panel
var base_theme: Theme # passed from the EditorPlugin
var tab_parent_bottom_panel: PanelContainer
func _ready() -> void:
tab_parent_bottom_panel = get_parent().get_parent() as PanelContainer
func _on_dock_visibility_changed() -> void:
if not visible or not base_theme or not tab_parent_bottom_panel:
return
var panel_box: StyleBoxFlat = base_theme.get_stylebox("BottomPanelDebuggerOverride", "EditorStyles")
tab_parent_bottom_panel.add_stylebox_override("panel", panel_box)
Hold up. Why does this not work? It seems as if the method to change the override is called right after ours and just overrides it back to the default? How dare they. But - we can just wait a frame and then override the override with what we want.
yield(get_tree(), "idle_frame")
tab_parent_bottom_panel.add_stylebox_override("panel", panel_box)
Good. What does it look like now?
Okay, we can handle that. Looks like the style box has content margins on the left and right, we can just remove those.
panel_box.content_margin_left = 0
panel_box.content_margin_right = 0
Now the debugger overflows. Undo.
Godot placed the debugger inside a Control node with left and right margins set to -10 and 10 to compensate for the content margin of the panel. Don't ask me why.
Okay, we copy that structure.
And, looks good for both now!
Wait, there is a little edge left. That stems from the tab panel stylebox it seems. Ah, they also have an override panel for that, let's use it.
func _ready() -> void:
if base_theme:
var tab_panel: StyleBoxFlat = base_theme.get_stylebox("DebuggerPanel", "EditorStyles")
$TabContainer.add_stylebox_override("panel", tab_panel)
Now we are done. What a journey!
res://addons/tab_dock/plugin.gd
extends EditorPlugin
var dock: Control
func _enter_tree():
dock = preload("res://addons/tab_dock/dock.tscn").instance()
dock.base_theme = get_editor_interface().get_base_control().theme
add_control_to_bottom_panel(dock, 'Tab Dock')
res://addons/tab_dock/dock.gd
var base_theme: Theme # passed from the EditorPlugin
var tab_parent_bottom_panel: PanelContainer
func _ready() -> void:
tab_parent_bottom_panel = get_parent().get_parent() as PanelContainer
if base_theme:
$TabContainer.add_stylebox_override("panel", base_theme.get_stylebox("DebuggerPanel", "EditorStyles"))
# replicates the behaviour for the debugger tab styles
# for the full setup of this, the TabContainer needs to be the child of a
# full rect Control and have a margin_left of -10 and a margin_right of 10
# this is to offset the 10px content margins that are still present in the
# BottomPanelDebuggerOverride stylebox for some reason. It's how Godot does it.
func _on_ModToolsDock_visibility_changed() -> void:
if not visible or not base_theme or not tab_parent_bottom_panel:
return
# the panel style is overridden by godot after this method is called
# make sure our override-override is applied after that
yield(get_tree(), "idle_frame")
var panel_box: StyleBoxFlat = base_theme.get_stylebox("BottomPanelDebuggerOverride", "EditorStyles")
tab_parent_bottom_panel.add_stylebox_override("panel", panel_box)
Now you know! If you have more questions, feel free to ask.
If you want to support me, you can