Open Razoric480 opened 4 years ago
I don't know if it's possible to get the exported variables specifically - well, with the language server's json export it is, but that could be a little heavy to probe.
In any case, that'd be a good general debug tool, so we could make it part of another repo where we have debug and/or UI components
If we use the language server, we'd have to grab the data before running, because the language server is only available in Editor as a tool script. With that in mind, then I can see an EditorScript that generates/updates a TSCN file.
If we want to go on-the-fly, then we'd probably stick with parsing the script as a text document, and regex-match variables based on some parameters of our choosing.
But yes, it should be its own project.
On my own time/for fun, was messing around and wrote the following:
tool
extends EditorScript
export(int, 0, 200, 5) var range_test: int = 50
export var standard_value_test := 20.0
export var variant_test = ""
export(ImageTexture) var resource_test
func _run() -> void:
var workspace = (
Engine.get_singleton('GDScriptLanguageProtocol').get_workspace()
)
workspace.parse_local_script("res://SymbolTest.gd")
var api: Dictionary = workspace.generate_script_api("res://SymbolTest.gd")
var file := File.new()
file.open("res://SymbolTest.gd", File.READ)
var content := file.get_as_text()
file.close()
var values := []
for m in api.members:
if m.export:
var var_name: String = m.name
var var_value: String = str(m.default_value) if m.default_value else ""
var type: String = m.data_type
var export_line := ""
var regex := RegEx.new()
regex.compile("export[ \t]*?\\((.*?)\\)[ \t]*?var " + var_name)
var line := regex.search(content)
var has_hints := not line == null
if has_hints:
var export_data: PoolStringArray = line.strings.slice(1, line.strings.size()-1)
export_line = export_data.join(", ")
values.append({name = var_name, value = var_value, controls = has_hints})
var scene := _build_scene(values)
ResourceSaver.save("res://SymbolTestGUI.tscn", scene)
func _build_scene(values: Array) -> PackedScene:
var node := MarginContainer.new()
node.set("custom_constants/margin_top", 20)
node.set("custom_constants/margin_left", 20)
node.set("custom_constants/margin_bottom", 20)
node.set("custom_constants/margin_right", 20)
var vbox := VBoxContainer.new()
node.add_child(vbox)
vbox.owner = node
for v in values:
var name: String = v.name
var value: String = v.value
var controls: bool = v.controls
var name_label := Label.new()
name_label.text = name + (" = " if not value.empty() else "")
var value_label := Label.new()
value_label.text = value
var hbox := HBoxContainer.new()
hbox.add_child(name_label)
hbox.add_child(value_label)
var controls_node: Label
if controls:
controls_node = Label.new()
controls_node.text = "Slider/etc goes here"
hbox.add_child(controls_node)
vbox.add_child(hbox)
name_label.owner = node
value_label.owner = node
hbox.owner = node
if controls_node:
controls_node.owner = node
var scene := PackedScene.new()
scene.pack(node)
return scene
As a show of idea.
You can get the object variables at runtime with Object.get_property_list()
and then filter those. This might work:
func _ready():
var list = get_property_list()
for v in list:
if v.usage & PROPERTY_USAGE_SCRIPT_VARIABLE and v.usage & PROPERTY_USAGE_EDITOR:
print(v)
While the Demo Selector is useful, one downside is that you can't change values quite as easily; needing to go into the Remote Tree to do so. So it's nice for showcase, but for actual study and playing around with the variables, opening the actual demo will still be called for.
Occasionally, Godot's keep-window-on-top option also stops working for unexplained reasons, depending on the state of your alt-tabbing and clicking, so using the inspector for all tweaking starts to lose some of its lustre.
An in-demo GUI system that we don't have to manually build but that automatically outputs the exported variables that are on the root node would alleviate all of those issues.