Skip to content

Instantly share code, notes, and snippets.

@YuriSizov
Last active December 19, 2021 19:50
Show Gist options
  • Save YuriSizov/b8b508922c1d947c53bd77936e31d80f to your computer and use it in GitHub Desktop.
Save YuriSizov/b8b508922c1d947c53bd77936e31d80f to your computer and use it in GitHub Desktop.
A sample code for Godot Editor plugin to play an arbitrary scene from GDScript
extends Node
# Should have been as easy as:
# editor_node._run(false, target_play_path)
# But is as easy as:
func play_scene(target_play_path : String) -> void:
# Get necessary nodes
var editor_interface = _get_plugin_instance().get_editor_interface()
var editor_base = editor_interface.get_base_control()
var editor_node = editor_base.get_tree().root.get_child(0)
# Get the Quick Run dialog (second EditorQuickOpen child)
var editor_quick_run = NodeUtils.get_child_by_class(editor_base, "EditorQuickOpen", 2)
if (editor_quick_run == null):
printerr("Failed to find Quick Run dialog")
return
# Get the Play Custom Scene Button (all intermediate nodes are fixed)
var editor_main_vbox = NodeUtils.get_child_by_class(editor_base, "VBoxContainer")
var editor_menu_hbox = NodeUtils.get_child_by_class(editor_main_vbox, "HBoxContainer")
var editor_play_hbox = NodeUtils.get_child_by_class(editor_menu_hbox, "HBoxContainer", 3)
var play_custom_button = NodeUtils.get_child_by_class(editor_play_hbox, "ToolButton", 5)
if (play_custom_button == null):
printerr("Failed to find 'Play Custom Scene' button")
return
# Force the popup to show so that the list is updated
play_custom_button.emit_signal("pressed")
editor_quick_run.hide()
# Get the content of the dialog (only VBoxContainer child)
var quick_run_control = NodeUtils.get_child_by_class(editor_quick_run, "VBoxContainer")
if (quick_run_control == null):
printerr("Failed to find Quick Run control")
return
# Get search box and tree containers (two MarginContainer children)
var quick_run_filter = NodeUtils.get_child_by_class(quick_run_control, "MarginContainer", 1)
var quick_run_tree = NodeUtils.get_child_by_class(quick_run_control, "MarginContainer", 2)
if (quick_run_filter == null || quick_run_tree == null):
printerr("Failed to find Quick Run form elements")
return
# The controls are just one node deep always
var search_box = (quick_run_filter.get_child(0) as LineEdit)
var scene_list = (quick_run_tree.get_child(0) as Tree)
# Clear list selection
search_box.clear()
TreeUtils.clear_selection(scene_list)
# Set list selection
search_box.text = target_play_path.trim_prefix("res://")
search_box.emit_signal("text_changed", search_box.text)
var was_selected = scene_list.get_root().get_children()
# Play selected scene
if (was_selected):
editor_node._quick_run()
else:
printerr("Failed to find the scene in scene list")
extends Object
class_name NodeUtils
static func get_child_by_class(node : Node, child_class : String, counter : int = 1) -> Node:
var match_counter = 0
var node_children = node.get_children()
for child in node_children:
if (child.get_class() == child_class):
match_counter += 1
if (match_counter == counter):
return child
return null
extends Object
class_name TreeUtils
static func clear_selection(tree : Tree) -> void:
var selected_item = tree.get_next_selected(null)
while (selected_item):
for i in tree.columns:
if (selected_item.is_selected(i)):
selected_item.deselect(i)
selected_item = tree.get_next_selected(selected_item)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment