pragmagic / godot-nim

Nim bindings for Godot Engine
https://pragmagic.github.io/godot-nim/
Other
501 stars 25 forks source link

Generate .gdns files? #73

Open arunvickram opened 4 years ago

arunvickram commented 4 years ago

Hi, I just started playing around with the Godot Nim stub project, and I was wondering if there was a way to autogenerate the GDNative script files per compilation?

Right now I'm just copying the info from FPSCounter.gdns and tweaking the variables to fit the class file that I compile, but if I have to manually do this every time, it doesn't seem too scalable.

Looking forward to hearing from you, and so far nice work!

geekrelief commented 4 years ago

Sure why not? A gdns file is just text. Though you might have to shut down the editor to reload it. I'm pretty sure the editor only reloads the dll. What variables are you tweaking?

arunvickram commented 4 years ago

So, if I have a MainPanel.gdns with the following content:

[gd_resource type="NativeScript" load_steps=2 format=2]

[ext_resource path="res://nimlib.gdnlib" type="GDNativeLibrary" id=1]

[resource]

resource_name = "MainPanel"
library = ExtResource( 1 )
class_name = "MainPanel"

I end up changing class_name and resource_name, but I don't want to have to do that every time I create a new class.

geekrelief commented 4 years ago

So write a script to generate the gdns. That's what I did.

arunvickram commented 4 years ago

Right, I'm going to do that, but I figure it would be nice if the godot-nim project itself included that build script anyways as a quality-of-life improvement

geekrelief commented 4 years ago

Yeah I agree. :) Though I think the this would be more of a change to godot-nim-stub. You could modify the nakefile to add your own task to generate a nim, gdns, and tscn file.

arunvickram commented 4 years ago

So, quick update, this is what I ended up adding to my nakefile.nim:

proc genScripts() =
  for srcFile in walkFiles("src/source/**/*.nim"):
    let (_, fileName) = splitPath(srcFile)
    let file = open(srcFile)
    defer: file.close()

    let classNames = collect(newSeq):
      for line in file.lines:
        if line =~ re"gdobj\s*(\S+)\s*": matches[0]

    createDir("testScripts")

    for className in classNames:
      let scriptFile = open(fmt"scripts/{className}.gdns", mode = fmWrite)
      defer: scriptFile.close()

      scriptFile.writeLine("[gd_resource type=\"NativeScript\" load_steps=2 format=2]")
      scriptFile.writeLine("")
      scriptFile.writeLine("[ext_resource path=\"res://nimlib.gdnlib\" type=\"GDNativeLibrary\" id=1]")
      scriptFile.writeLine("")
      scriptFile.writeLine("[resource]")
      scriptFile.writeLine("")
      scriptFile.writeLine(&"resource_name = \"{className}\"")
      scriptFile.writeLine("library = ExtResource( 1 )")
      scriptFile.writeLine(&"class_name = \"{className}\"")

This requires that the src directory in the nimble project has an extra source directory with all the code so as to not process the generated Godot API for Nim

geekrelief commented 4 years ago

You can also use this: https://nim-lang.github.io/Nim/strutils.html#%25%2Cstring%2CopenArray%5Bstring%5D instead of writing line by line.

arunvickram commented 4 years ago

The reason I wrote it line by line was to avoid adding tabs/spaces at the beginning of the file, but I'll take a look at it.

geekrelief commented 4 years ago

Spaces shouldn't be a problem. I do this in my code.

const gdns_template = """
[gd_resource type="NativeScript" load_steps=2 format=2]

[sub_resource type="GDNativeLibrary" id=1]
entry/Windows.64 = "res://$3/$1.dll"
dependency/Windows.64 = [  ]

[resource]
resource_name = "$2"
class_name = "$2"
library = SubResource( 1 )
"""