Is there any way to run a given string at runtime? I have tried to write something like this by creating a new node and attaching a new script to it, and I have gotten this far:

var new_node:Node = Node.new()
add_child(new_node)
var new_script:GDScript = GDScript.new()
new_script.source_code = "extends Node\nfunc run():\n\t" + script_to_execute
print(new_script.source_code)
new_node.set_script(new_script)
pressed.connect(new_node.call.bind("run"))

This gets an error (but not a crash) when hitting that last line:

emit_signalp: Error calling from signal 'pressed' to callable: 'Node::call': Method not found.

This is pretty weird, as a Node should always have access to the method “call”. Does someone have an idea on how to solve this / their own idea on how to implement runtime code editing and executing?

  • sus@programming.dev
    link
    fedilink
    arrow-up
    12
    ·
    edit-2
    8 months ago

    found a few examples of how to do it on a github issue:

    var script = GDScript.new()
    script.source_code = "func say_hello():\n\tprint(\"Hello!\")"
    script.reload()
    var script_instance = script.new()
    script_instance.call("say_hello")
    
    
    var MyClass = load("myclass.gd")
    var instance = MyClass.new()
    assert(instance.get_script() == MyClass)
    
    
    • Smorty [she/her]@lemmy.blahaj.zoneOP
      link
      fedilink
      arrow-up
      4
      ·
      edit-2
      8 months ago

      This seems to be the exact thing I am searching for, thanks! I have run into an interesting hickup tho. One can pass self to the expression so that it uses the node as the base, but the expression doesn’t seem to have access to autoloads. The error I’m getting there looks something like this: Invalid named index ‘ExampleAutoload’ for base type Object EDIT: Turns out I need to pass these individually as arguments essentially.