diff --git a/.gitignore b/.gitignore index 7ed1b30..e06f7ed 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,14 @@ nimcache/ -.DS_Store + /godot/apigen/apigen /godot/apigen/apigen.exe +/godot/godotapigen +/godot/godotapigen.exe + +/docgen +/docs/docbuild +/docs/docbuild.exe +/docs/docpublish +/docs/docpublish.exe + +.DS_Store \ No newline at end of file diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..b0b27d4 --- /dev/null +++ b/.travis.yml @@ -0,0 +1,53 @@ +sudo: false +language: c +os: + - osx +compiler: clang +env: + global: + - secure: o+IZkRS6J7bGYkiilm10KDeCTDIVHszZ9dPvb93cdUKX/9hFVRiUjDOvNXqBdyOv43JIAsRTppym4B2pfcp9cwLoVBJNW70GKhp6ChLZm3wFdabScWKemuG2YtAUyGiSmxbVmUZ4baltnADyGFHuYWgHLjx6AKO26SqrXRLJ0I1IzGNKKNIfoyZzm7qdFDGJRnSC7L+y1pOITK7dpy60D1vat4FhOLaz2K7L8T8tZYZFK7yyxKduFUlY3cy4z3TpjxMa9/ksCiPiuPDN5xOrVIw0AtgZ2gYodZJUEnfaRzFkgcZ4OJuTAMNMalu52mVAVAoDt4yc7BnbtfsYJzfIjTeLjjWKWz8mqqp/HpxcfVnmPKxV5zeN8UhbosT8vNjwretWbQcFndzt0ohK7E8uMsnDGER7sGPEhCZCttkId96gi7Ro1awPIKCqLaMqB43Bwo48nnW0oQgrfWe1ZKtREXWI4F1F2GMbU8Jsvv0N5GnPGd4RDieBH5KIkJXcttAwRk8AUQ4U5PVkQ/OK9xm9BH2tB0vrjZ4FZWnFPapKVcPUYw9deyyXOXwSMmDpuwkJIjqi3tRyBWJG9+tUlAJw8zyFkCPeN9kzyVH/PhbacwBMdSxew24VLAWWCUhQHCP+fcjpKio8uDUFQN3javIRV4N3mHJ9v0VAF7Ixzh8AviQ= + +addons: + apt: + sources: + - ubuntu-toolchain-r-test + - llvm-toolchain-trusty-3.9 + packages: + - build-essential + - scons + - pkg-config + - libx11-dev + - libxcursor-dev + - libasound2-dev + - libfreetype6-dev + - libgl1-mesa-dev + - libglu1-mesa-dev + - libssl-dev + - libxinerama-dev + - libxrandr-dev + +before_install: + - if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then rvm --default use 2.3; brew update; brew install scons ; fi + +install: + - if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then export GODOT_PLATFORM=osx; else export GODOT_PLATFORM=x11; fi + - git clone --depth=1 https://github.com/nim-lang/Nim.git + - cd Nim + - git checkout devel + - sh ci/build.sh + - export PATH=$PATH:"`pwd`/bin" + - ./koch tools -d:release + - nimble install -y + - cd .. + - git clone --depth=1 https://github.com/godotengine/godot.git godotengine + - cd godotengine + - scons -j 3 platform=$GODOT_PLATFORM + - export GODOT_BIN="`pwd`/bin/godot.$GODOT_PLATFORM.tools.64" + - cd .. + +script: + - set -e + - mkdir godotapi + - nim c -d:release -r godot/godotapigen.nim "$GODOT_BIN" godotapi + - nim c -d:useRealtimeGc --path:godot -c godotapi/godotall.nim + - nim c -d:release -r docs/docpublish.nim diff --git a/.vscode/settings.json b/.vscode/settings.json index c26d7e1..6960f9a 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -6,10 +6,10 @@ "files.eol": "\n", "files.trimTrailingWhitespace": true, "nim.project": ["godot/godot.nim", - "godot/apigen/apigen.nim"], + "godot/godotapigen.nim"], "nim.buildOnSave": false, "nim.lintOnSave": true, - "nim.licenseString": "# Copyright 2017 Xored Software, Inc.\n\n", + "nim.licenseString": "# Copyright 2018 Xored Software, Inc.\n\n", "files.exclude": { "**/nimcache/**": true } diff --git a/LICENSE b/LICENSE index 16a448a..07ecdb6 100644 --- a/LICENSE +++ b/LICENSE @@ -2,7 +2,7 @@ godot-nim - Nim bindings for Godot Engine The MIT License -Copyright (c) 2017 Xored Software Inc. +Copyright (c) 2018 Xored Software Inc. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, diff --git a/README.md b/README.md index 40ee649..62e28d3 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,8 @@ # Nim bindings for Godot Engine -Nim bindings for Godot 3.0 based on [GDNative](https://godotengine.org/article/dlscript-here). +Nim bindings for Godot 3 based on [GDNative](https://godotengine.org/article/dlscript-here). + +Documentation: https://pragmagic.github.io/godot-nim/ ## Links @@ -9,6 +11,6 @@ Nim bindings for Godot 3.0 based on [GDNative](https://godotengine.org/article/d ## License -This project is licensed under the MIT license. Read [LICENSE](https://github.com/pragmagic/godot-nim/blob/master/LICENSE) file for details. +This project is licensed under the MIT license. Read [LICENSE](LICENSE) file for details. -Copyright (c) 2017 Xored Software, Inc. \ No newline at end of file +Copyright (c) 2018 Xored Software, Inc. diff --git a/docs/docbuild.nim b/docs/docbuild.nim new file mode 100644 index 0000000..477c45b --- /dev/null +++ b/docs/docbuild.nim @@ -0,0 +1,161 @@ +# Copyright 2018 Xored Software, Inc. + +import threadpool, os, osproc, strutils, sequtils, pegs + +import "../godot/godotapigen.nim" + +const dirs = ["godot"/"core", "godot"/"internal", "godot"/"nim"] +const files = ["godot"/"godotapigen.nim", "godot"/"godotinternal.nim", + "godot"/"godot.nim"] +const indexFile = "docs"/"index.rst" +const gitHubUrl = "https://github.com/pragmagic/godot-nim" + +proc outName(outDir, file: string): string = + outDir / file.extractFilename().changeFileExt("html") + +template quoted(s: string): string = + ('"' & s & '"') + +proc execOrFail(cmd: string) = + echo "[exec] " & cmd + let ret = execShellCmd(cmd) + if ret != 0: + raise newException( + Exception, "Command quit with exit code " & $ret & ": " & cmd) + +template withDir(dir: string, body: typed) = + let curDir = getCurrentDir() + setCurrentDir(dir) + try: + body + finally: + setCurrentDir(curDir) + +iterator walkDirRec(dir: string, filter: set[PathComponent], + extensions: openarray[string]): string = + for file in walkDirRec(dir, filter): + if not extensions.anyIt(file.endsWith(it)): continue + yield file + +proc genApiFiles(targetDir, godotBin: string) = + let jsonFile = targetDir / "api.json" + try: + execOrFail(quoted(godotBin) & + " --gdnative-generate-json-api " & quoted(jsonFile)) + except: + # this fails unstably even if api.json is created successfully + discard + if not fileExists(jsonFile): + raise newException(Exception, "Failed to generate Godot API wrappers") + + genApi(targetDir, jsonFile) + + writeFile(targetDir / "nim.cfg", "path=\"$projectdir/../../godot\"") + +proc extractVersion(nimbleFile: string): string = + let contents = readFile(nimbleFile) + var matches: array[1, string] + doAssert match(contents, peg"""'version' \s* '=' \s* '"' {@} '"' """, matches) + result = matches[0] + +proc fixupHrefs(file: string) = + var contents = readFile(file) + contents = contents.replacef( + peg"""'href="' ('internal'/'core'/'nim') '/' {@} '"' """, + "href=\"$#\"") + if file.contains("godotapi"): + contents = contents.replacef( + peg"""'href="' {('godotinternal' / 'godot') '.html"'} """, + "href=\"../$#") + writeFile(file, contents) + +proc getGitHash(): string = + result = execProcess("git rev-parse HEAD") + if result.len > 0: + result = result.replace("\L", "").replace("\r", "") + +proc buildDocs*(outDir, godotNimDir, godotBin: string) = + removeDir(outDir) + createDir(outDir) + let outDirAbs = expandFilename(outDir) + let godotBinAbs = expandFilename(godotBin) + + setCurrentDir(godotNimDir) + + let godotNimVersion = extractVersion("godot.nimble") + putEnv("godotnimversion", godotNimVersion) + putEnv("godotnimgithub", gitHubUrl) + let gitCommit = getGitHash() + + var allNimFiles = newSeq[string]() + allNimFiles.add(files) + for dir in dirs: + for file in walkDirRec(dir, {pcFile, pcDir}, [".nim"]): + allNimFiles.add(file) + for file in allNimFiles: + spawn execOrFail( + "nim doc -d:useRealtimeGc --path:godot -o:" & + quoted(outName(outDirAbs, file)) & + " --git.url:" & quoted(gitHubUrl) & + " --git.commit:" & quoted(gitCommit) & + ' ' & quoted(file)) + + let godotApiFolder = outDirAbs / "godotapi" + createDir(godotApiFolder) + genApiFiles(godotApiFolder, godotBinAbs) + for file in walkDirRec(godotApiFolder, {pcFile, pcDir}, [".nim"]): + spawn execOrFail("nim doc -d:useRealtimeGc --path:godot -o:" & + quoted(outName(godotApiFolder, file)) & ' ' & quoted(file)) + + sync() + + var gitHash: string + withDir(godotBinAbs.parentDir()): + gitHash = getGitHash() + if gitHash.len == 0: + raise newException(Exception, + "Godot executable is not under Git repository") + + var indexContent = readFile(indexFile) + var apiList = newStringOfCap(4096) + for file in walkDirRec(godotApiFolder, {pcFile, pcDir}): + if not file.endsWith(".html"): + removeFile(file) + else: + let moduleHtml = file.extractFileName() + let moduleName = moduleHtml.changeFileExt("") + apiList.add("* `" & moduleName & " `_\L") + indexContent = indexContent.replace("$GODOTAPI_CHANGESET_HASH", gitHash). + replace("$AUTO_GENERATED_GODOTAPI_LIST", apiList). + replace("$GODOTNIM_GITHUB_URL", gitHubUrl) + + let tmpRst = outDirAbs/"index.rst" + writeFile(tmpRst, indexContent) + try: + execOrFail("nim rst2html -o:" & quoted(outName(outDirAbs, tmpRst)) & + ' ' & quoted(tmpRst)) + finally: + removeFile(tmpRst) + + for file in walkDirRec(outDir, {pcFile, pcDir}, [".html"]): + spawn fixupHrefs(file) + + sync() + +when isMainModule: + const outDir = "docgen" + + if not fileExists("godot.nimble"): + echo "Must be executed from godot-nim root dir" + quit(-1) + + let godotBin = getEnv("GODOT_BIN") + if godotBin.len == 0: + echo "GODOT_BIN environment variable must point to Godot executable" + quit(-1) + + try: + buildDocs(outDir, getCurrentDir(), godotBin) + except: + echo getCurrentExceptionMsg() + quit(-1) diff --git a/docs/docpublish.nim b/docs/docpublish.nim new file mode 100644 index 0000000..e55974c --- /dev/null +++ b/docs/docpublish.nim @@ -0,0 +1,97 @@ +# Copyright 2018 Xored Software, Inc. + +import os, pegs, strutils +import docbuild + +const indexTemplate = """ +godot-nim docs index + +

Documentation of Nim bindings for Godot Engine (GitHub)


+$VERSION_LIST + + +""" + +proc execOrQuit(cmd: string) = + let ret = execShellCmd(cmd) + if ret != 0: + quit(ret) + +proc walkDirRecRelative(dir: string, cb: proc (file: string), start = "") = + for kind, path in walkDir(dir, relative = true): + if kind in {pcFile, pcLinkToFile}: + cb(if start.len > 0: start / path else: path) + elif kind in {pcDir, pcLinkToDir}: + let fullPath = if start.len > 0: start / path else: path + walkDirRecRelative(dir / fullPath, cb, fullPath) + +proc publish(docDir, gitHubToken, repoSlug, branch, tag, changeset: string) = + let release = if branch == "master": branch else: tag + let commitComment = if release == "master": + "Update master documentation for changeset " & changeset + else: + "Update documentation for " & tag + + const repoDir = "gh-pages" + execOrQuit( + "git clone --depth=1 --branch=gh-pages https://github.com/$#.git $#" % + [repoSlug, repoDir]) + try: + removeDir(repoDir/release) + createDir(repoDir/release) + var versionList = newStringOfCap(4096) + for kind, path in walkDir(repoDir, relative = true): + if kind == pcDir and not path.startsWith("."): + versionList.add("$1
" % path) + let index = indexTemplate.replace("$REPO_SLUG", repoSlug). + replace("$VERSION_LIST", versionList) + writeFile(repoDir/"index.html", index) + + walkDirRecRelative(docDir) do (file: string): + createDir(parentDir(repoDir/release/file)) + copyFile(docDir/file, repoDir/release/file) + + setCurrentDir(repoDir) + try: + execOrQuit("git add --all") + execOrQuit("git commit -m \"$#\"" % commitComment) + execOrQuit("git push -fq \"https://$#@github.com/$#.git\" gh-pages" % + [gitHubToken, repoSlug]) + finally: + setCurrentDir("..") + finally: + removeDir(repoDir) + +when isMainModule: + proc getEnvOrQuit(key: string): string = + result = getEnv(key) + if result.len == 0: + echo "Expected environment variable: " & key + quit(1) + + let pr = getEnv("TRAVIS_PULL_REQUEST") + if pr.len > 0 and pr != "false": + echo "This is a PR build. Skipping." + quit(0) + + let repoSlug = getEnvOrQuit("TRAVIS_REPO_SLUG") + let branch = getEnvOrQuit("TRAVIS_BRANCH") + let changeset = getEnvOrQuit("TRAVIS_COMMIT") + let tag = getEnv("TRAVIS_TAG") + + # let repoSlug = "pragmagic/godot-nim" + # let branch = "master" + # let changeset = "0fd0101432c1fed1004f50b035fcf74f75f004a8" + # let tag = "" + + let gitHubToken = getEnvOrQuit("GITHUB_TOKEN") + + if branch != "master" and not (tag =~ peg"^ 'v' \d+ '.' \d+ '.' \d+ $"): + echo "This is not master or tagged changeset. Skipping." + quit(0) + + let godotBin = getEnvOrQuit("GODOT_BIN") + + const docDir = "docgen" + buildDocs(docDir, getCurrentDir(), godotBin) + publish(docDir, gitHubToken, repoSlug, branch, tag, changeset) diff --git a/docs/godotapi.rst b/docs/godotapi.rst new file mode 100644 index 0000000..9bea41d --- /dev/null +++ b/docs/godotapi.rst @@ -0,0 +1,12 @@ +=============== +Godot API (Nim) +=============== + +:Godot Git Hash: |godothash| + +.. contents:: + +This is an auto-generated index of Godot API. It's built from Git changeset +$GODOTAPI_CHANGESET_HASH. + +$AUTO_GENERATED_GODOTAPI_LIST \ No newline at end of file diff --git a/docs/index.rst b/docs/index.rst new file mode 100644 index 0000000..e14d38d --- /dev/null +++ b/docs/index.rst @@ -0,0 +1,173 @@ +============================= +Nim bindings for Godot Engine +============================= + +:Author: Ruslan Mustakov +:Version: |godotnimversion| +:GitHub: `$GODOTNIM_GITHUB_URL <$GODOTNIM_GITHUB_URL>`_ +:License: MIT + +.. contents:: + +``godot-nim`` library allows to create games on +`Godot Engine `_ with +`Nim programming language `_. Nim is a statically typed +language with an elegant Python-like syntax that compiles to native code. +It is garbage-collected, but its GC supports real-time mode which this library +makes use of. It means the GC will never run during game frames and will use +fixed amount of frame idle time to collect garbage. This leads to no stalls +and close to zero compromise on performance comparing to native languages with +manual memory management. + +If you are not familiar with Nim yet, it is recommended to go through the +`official tutorial `_. + +`VSCode `_ is the recommended editor for +working with Nim code. It is cross-platform and has the excellent +`nim plugin `_ +that supports most of the features you would expect from an IDE. +It also has `godot-tools plugin `_ +which adds features for editing GDScript and Godot resource files. + + +Getting Started +=============== + +Getting Godot +-------------- + +The library requires Godot version 3.0, which you can get here: +https://godotengine.org/download + +Installing Nim +------------- + +The library requires Nim version 0.18.0 or newer, which you can get here: +https://nim-lang.org/install.html + +Make sure you also have ``nimble`` (Nim's package manager) installed. + +Creating Project +---------------- + +The fastest way to set up a Godot-Nim project is to use the existing stub: + +.. code-block:: bash + git clone --depth=1 https://github.com/pragmagic/godot-nim-stub.git myproject + +(you can then delete the .git directory within to untie the project from the +stub repository) + +The stub contains the necessary build configuration to compile your code for +desktop and mobile platforms, as well as a couple of very simple scenes to +help you get started. Consult the stub's `README +`_ for information about +compiling the project. + + +Adding Nim to Existing Project +------------------------------ + +If you would like to use Nim in an existing project: + +1. Copy ``nakefile.nim`` file and ``src`` directory from the stub described + in the previous section above your Godot project folder. Adjust paths in + build scripts (``nakefile.nim``, ``src/stub.nimble``) according to your + own project structure. + +2. Copy ``nimlib.gdnlib`` to your Godot project folder. It is a + GDNative library resource that contains paths to dynamic libraries + compiled by Nim. + +Next Steps +---------- + +Once you are familiarized with the build process (it's as simple as running +``nake build`` after you are set up), it is recommended to go through +`godotmacros `_ and `godotnim `_ module +documentations. They describe special macros and procedures needed to define +or instantiate Godot objects. After you learned that, the rest is similar to +using any Nim library. These bindings do not limit any of Nim's capabilities, +and you can use any Nim types as fields or parameters of Godot objects and +their procedures (but, obviously, you may not be able to export some of them +to Godot editor or GDScript, unless you define your own converters). + + +Modules +======= + +The binding library consists of three major modules: + +* `godot <#modules-godot-module>`_ - Contains core types and macro definitions. + You need to import this in any module that defines or makes use of Godot + types. + +* `godotinternal <#modules-godotinternal-module>`_ - Contains raw wrappers over + few core types, such as ``GodotVariant``, ``GodotString``, ``GodotNodePath``, + ``GodotDictionary``, pool arrays. These are used by ``godotapigen`` and macro + implementations, and you don't have to use them at all in your code, unless + you want to go into low-level details for some reason. Each of those types + needs to be destructed manually with ``deinit`` procedure. + +* `godotapigen `_ - Wrapper generator based on data from + Godot's ``ClassDB``. You only need to use it as a part of the build process. + + +godot Module +------------ + +Contains core types and macro definitions. You need to import this in any +module that defines or makes use of Godot types. The sumbodules below are +exported and you don't have to import any of them directly. + +* `godotnim `_ Defines ``NimGodotObject`` and Varaint converters + for standard Nim types. +* `godotmacros `_ Defines ``gdobj`` macro for defining + Godot objects. +* `variants `_ ``Variant`` type represents a "dynamic object" + that many Godot procedures make use of. +* `arrays `_ Defines ``Array`` of Variants. +* `basis `_ Defines 3D ``Basis``. +* `colors `_ Defines ARGB ``Color``. +* `dictionaries `_ Defines ``Variant`` -> ``Variant`` + ``Dictionary``. +* `nodepaths `_ Defines ``NodePath`` - a path to a ``Node``. +* `planes `_ Defines 3D ``Plane``. +* `poolarrays `_ Defines pooled arrays: ``PoolByteArray``, + ``PoolIntArray``, ``PoolRealArray``, ``PoolVector2Array``, + ``PoolVector3Array``, ``PoolColorArray``, ``PoolStringArray``. +* `quats `_ Defines ``Quat`` (quaternion) describing object + rotation in 3D space. +* `rect2 `_ Defines ``Rect2`` - a 2D rectangle. +* `aabb `_ Defines ``AABB`` - a 3D box. +* `rids `_ Defines ``RID`` - a resource identifier. +* `transform2d `_ Defines ``Transform2D``. +* `transforms `_ Defines ``Transform``. +* `vector2 `_ Defines ``Vector2``. +* `vector3 `_ Defines ``Vector3``. +* `godotbase `_ Defines ``Error`` type and few common math + procedures missing in Nim's standard library. + + +Godot API +--------- + +This is an auto-generated list of Godot API modules. It's built from Godot +changeset `$GODOTAPI_CHANGESET_HASH +`_. + +$AUTO_GENERATED_GODOTAPI_LIST + + +godotinternal Module +-------------------- + +Contains low-level wrappers over Godot types that require manual memory +management. This module is used within ``godot-nim`` implementation and you +don't need to import it unless you know what you are doing. + +* `godotdictionaries `_ +* `godotnodepaths `_ +* `godotpoolarrays `_ +* `godotstrings `_ +* `godotvariants `_ diff --git a/docs/nim.cfg b/docs/nim.cfg new file mode 100644 index 0000000..9d57ecf --- /dev/null +++ b/docs/nim.cfg @@ -0,0 +1 @@ +--threads:on \ No newline at end of file diff --git a/godot.nimble b/godot.nimble index b58f9e1..d7ca12b 100644 --- a/godot.nimble +++ b/godot.nimble @@ -1,7 +1,7 @@ -version = "0.1.1" +version = "0.8.2" author = "Xored Software, Inc." description = "Godot Engine bindings" license = "MIT" srcDir = "godot" -requires "nim >= 0.17.0", "compiler >= 0.17.0" \ No newline at end of file +requires "nim >= 0.17.3", "compiler >= 0.17.3" \ No newline at end of file diff --git a/godot/apigen/apigen.nim b/godot/apigen/apigen.nim deleted file mode 100644 index 8238029..0000000 --- a/godot/apigen/apigen.nim +++ /dev/null @@ -1,860 +0,0 @@ -# Copyright 2017 Xored Software, Inc. - -import streams, json, ospaths, strutils, times, sets, tables -import sequtils, algorithm -import compiler / [ast, renderer, idents, astalgo] - -proc ident(ident: string): PNode = - result = newNode(nkIdent) - result.ident = getIdent(ident) - -proc addChain(node: PNode, others: varargs[PNode]): PNode {.discardable.} = - for other in others: - node.add(other) - result = node - -proc newIdentDefs(name, typ: PNode, - defaultVal: PNode = nil): PNode = - result = newNode(nkIdentDefs) - result.add(name) - result.add(typ) - if defaultVal.isNil: - result.add(newNode(nkEmpty)) - else: - result.add(defaultVal) - -proc newProc(name: PNode, params: openArray[PNode], body = newNode(nkEmpty), - procType = nkProcDef): PNode = - result = newNode(procType) - result.add(name) - result.add(newNode(nkEmpty)) - result.add(newNode(nkEmpty)) - let formalParams = newNode(nkFormalParams) - for param in params: - formalParams.add(param) - result.add(formalParams) - result.add(newNode(nkEmpty)) - result.add(newNode(nkEmpty)) - result.add(body) - -proc newIfStmt(condition, body: PNode): PNode = - result = newNode(nkIfStmt) - let branch = newNode(nkElifBranch) - result.add(branch) - branch.add(condition) - branch.add(body) - -proc newCall(theProc: PNode, args: varargs[PNode]): PNode = - result = newNode(nkCall) - result.add(theProc) - for arg in args: - result.add(arg) - -proc newCall(theProc: string, args: varargs[PNode]): PNode = - newCall(ident(theProc), args) - -proc newStrLit(s: string): PNode = - result = newNode(nkStrLit) - result.strVal = s - -proc newRStrLit(s: string): PNode = - result = newNode(nkRStrLit) - result.strVal = s - -proc newCStringLit(s: string): PNode = - newNode(nkCallStrLit).addChain(ident("cstring"), newRStrLit(s)) - -proc newIntLit(val: BiggestInt): PNode = - result = newNode(nkIntLit) - result.intVal = val - -proc newInt64Lit(val: BiggestInt): PNode = - result = newNode(nkInt64Lit) - result.intVal = val - -proc newFloatLit(val: BiggestFloat): PNode = - result = newNode(nkFloatLit) - result.floatVal = val - -proc newFloat64Lit(val: BiggestFloat): PNode = - result = newNode(nkFloat64Lit) - result.floatVal = val - -proc newNilLit(): PNode = - result = newNode(nkNilLit) - -proc newDotExpr(left, right: PNode): PNode = - result = newNode(nkDotExpr) - result.add(left) - result.add(right) - -proc newCommand(left, right: PNode): PNode = - result = newNode(nkCommand) - result.add(left) - result.add(right) - -proc newInfix(left, op, right: PNode): PNode = - result = newNode(nkInfix) - result.add(op) - result.add(left) - result.add(right) - -proc postfix(left: PNode, op: string): PNode = - result = newNode(nkPostfix) - result.add(ident(op)) - result.add(left) - -proc newExprColonExpr(key, value: PNode): PNode = - newNode(nkExprColonExpr).addChain(key, value) - -proc pragma(key: PNode, value: PNode): PNode = - newNode(nkPragma).addChain(key, value) - -proc newBracketExpr(first, bracket: PNode): PNode = - newNode(nkBracketExpr).addChain(first, bracket) - -proc newEmptyNode(): PNode = - newNode(nkEmpty) - -type GodotType = ref object - name: string - godotName: string - baseName: string - doc: string - derivedCount: int - isSingleton: bool - jsonNode: JsonNode - -proc findCommonRoot(typeRegistry: Table[string, GodotType], - types: seq[string]): string = - if types.len == 0: return "Object" - var chains = newSeq[seq[string]](types.len) - for idx, typ in types: - chains[idx] = newSeq[string]() - chains[idx].add(typ) - var curTyp = typeRegistry[typ] - while curTyp.baseName != "NimGodotObject": - chains[idx].add(curTyp.baseName) - curTyp = typeRegistry[curTyp.baseName] - chains[idx].reverse() - - var idx = 0 - while true: - var curType: string - var allEqual = true - for chain in chains: - if idx >= chain.len: - allEqual = false - break - if curType.isNil: - curType = chain[idx] - elif curType != chain[idx]: - allEqual = false - break - if allEqual: - result = curType - else: - break - inc idx - -proc incDerivedCount(types: var Table[string, GodotType], - className: string) = - let typ = types.getOrDefault(className) - if not typ.isNil: - inc typ.derivedCount - types.incDerivedCount(typ.baseName) - -proc toNimType(godotType: string): string = - case godotType: - of "float": "float64" - of "int": "int64" - of "String": "string" - of "File": "godottypes.File" - else: godotType - -proc toNimType(types: Table[string, GodotType], godotType: string): string = - let origType = - if godotType.contains(','): - findCommonRoot(types, godotType.split(',')) - else: - godotType - result = toNimType(origType) - -proc toNimStyle(name: string): string = - result = newStringOfCap(name.len + 1) - var i = 0 - var makeUpperCase: bool - while i < name.len: - if name[i] == '_': - if result.len != 0: - makeUpperCase = true - elif name[i] != '/': # remove slashes - if makeUpperCase: - result.add(name[i].toUpperAscii()) - makeUpperCase = false - else: - result.add(name[i]) - inc i - - while isKeyword(getIdent(result)): - result.add(result[result.len - 1]) - - if result == "result": - result = "resultVal" - -proc newRefTypeNode(typeSection: PNode, typ, base, doc: string, - isExported = true) = - let typeDef = newNode(nkTypeDef) - typeSection.add(typeDef) - if isExported: - typeDef.add(postfix(ident(typ), "*")) - else: - typeDef.add(ident(typ)) - - typeDef.add(newNode(nkEmpty)) # generic - let objTy = newNode(nkObjectTy) - let refTy = newNode(nkRefTy) - refTy.add(objTy) - typeDef.add(refTy) - - objTy.add(newNode(nkEmpty)) - let inherit = newNode(nkOfInherit) - inherit.add(ident(base)) - objTy.add(inherit) - - if not doc.isNil: - let recList = newNode(nkRecList) - let docNode = newNode(nkCommentStmt) - docNode.comment = doc - recList.add(docNode) - objTy.add(recList) - else: - objTy.add(newNode(nkEmpty)) - -proc makeConstSection(constObj: JsonNode): PNode = - if constObj.len == 0: - return newNode(nkEmpty) - - result = newNode(nkConstSection) - for field, val in constObj: - let def = newNode(nkConstDef) - def.add(postfix(ident(field), "*")) - def.add(newNode(nkEmpty)) # infer type - var valNode: PNode - if val.kind == JInt: - valNode = newInt64Lit(val.num) - # valNode.intVal = val.num - elif val.kind == JFloat: - valNode = newFloat64Lit(val.fnum) - elif val.kind == JBool: - valNode = ident($val.bval) - elif val.kind == JString: - valNode = newNode(nkStrLit) - valNode.strVal = val.str - else: - raise newException(ValueError, "Unexpected constant kind: " & $val.kind) - def.add(valNode) - result.add(def) - -type MethodArg = tuple[name, typ: string, defaultVal: JsonNode, isVarargs: bool] - -const standardTypes = toSet( - ["bool", "cint", "int", "uint8", "int8", "uint16", "int16", "uint32", "int32", - "uint64", - "int64", "float32", "cfloat", "float64", "GodotString", "Vector2", "Rect2", - "Vector3", "Transform2D", "Plane", "Quat", "Rect3", "Basis", "Transform", - "Color", "NodePath", "RID", "Dictionary", "Array", "PoolByteArray", - "PoolIntArray", "PoolRealArray", "PoolStringArray", "PoolVector2Array", - "PoolVector3Array", "PoolColorArray", "Variant"]) - -const smallIntTypes = toSet(["uint8", "int8", "uint16", "int16", "uint32", "int32", - "cint", "int", "Error"]) -const int64Types = toSet(["uint64", "int64"]) -const intTypes = union(smallIntTypes, int64Types) -const float64Types = toSet(["float64", "cdouble"]) -const float32Types = toSet(["float32", "cfloat"]) -const floatTypes = union(float64Types, float32Types) -const arrayTypes = toSet(["Array", "PoolByteArray", - "PoolIntArray", "PoolRealArray", "PoolStringArray", "PoolVector2Array", - "PoolVector3Array", "PoolColorArray"]) - -proc newNilCheck(ident, toAssign: PNode): PNode = - newIfStmt(newCall("isNil", ident), - newNode(nkAsgn).addChain(ident).addChain( - toAssign - ) - ) - -proc singletonName(typ: string): PNode = - ident("singleton" & typ) - -proc makeDefaultValue(arg: MethodArg): PNode = - result = newEmptyNode() - if not arg.defaultVal.isNil: - if arg.typ == "bool": - result = ident(arg.defaultVal.str.toLowerAscii()) - elif arg.typ in intTypes: - result = newInt64Lit(parseBiggestInt(arg.defaultVal.str)) - elif arg.typ == "string" or arg.typ == "NodePath": - result = newStrLit(arg.defaultVal.str) - elif arg.typ in floatTypes: - result = newFloatLit(parseFloat(arg.defaultVal.str)) - elif arg.defaultVal.str == "Null": - if arg.typ == "Variant": - result = newCall("variant") - else: - result = newNilLit() - elif arg.typ == "Color": - result = newCall("initColor", - arg.defaultVal.str.split(',').mapIt(newFloatLit(parseFloat(it)))) - # elif arg.typ in arrayTypes and (arg.defaultVal.str == "[]" or - # arg.defaultVal.str == "[" & arg.typ & "]"): - # result = newCall("init" & arg.typ) - elif arg.typ == "RID" and arg.defaultVal.str == "[RID]": - result = newCall("initRID") - elif arg.typ == "Vector2" or arg.typ == "Vector3" or arg.typ == "Rect2": - let parts = arg.defaultVal.str.replace("(", "").replace(")", ""). - replace(" ", ""). - split(",").mapIt(newFloatLit(parseFloat(it))) - if arg.typ.endsWith("r2"): - result = newCall("vec2", parts) - elif arg.typ.endsWith('3'): - result = newCall("vec3", parts) - else: - result = newCall("initRect2", parts) - elif arg.defaultVal.str == "[Object:null]": - result = newNilLit() - elif arg.typ != "Transform" and arg.typ != "Transform2D" and - arg.typ != "Variant" and arg.typ notin arrayTypes: # TODO - raise newException( - ValueError, - "Cannot build default value from $# ($#)" % - [$arg.defaultVal, arg.typ]) - -proc doGenerateMethod(tree: PNode, methodBindRegistry: var HashSet[string], - name: PNode, godotMethodName: string, - typ: GodotType, args: seq[MethodArg], - returnType: string, isVirtual, - isBase, withImplementation: bool) = - var body: PNode - if not withImplementation: - body = newNode(nkEmpty) - else: - var methodBindName = toNimStyle( - typ.name & "_" & godotMethodName & "_method_bind") - if methodBindName[0].isUpperAscii(): - methodBindName[0] = methodBindName[0].toLowerAscii() - if methodBindName notin methodBindRegistry: - let methodBindDecl = newNode(nkVarSection).addChain( - newIdentDefs( - newNode(nkPragmaExpr).addChain( - ident(methodBindName)).addChain( - newNode(nkPragma).addChain(ident("threadvar"))), - newNode(nkPtrTy).addChain(ident("GodotMethodBind")) - )) - tree.add(methodBindDecl) - methodBindRegistry.incl(methodBindName) - - let nilCheck = newNilCheck(ident(methodBindName), - newCall("getMethod", newCStringLit(typ.godotName), - newCStringLit(godotMethodName)) - ) - let vars = newNode(nkVarSection) - var varargsName: string - var isVarargs: bool - var staticArgsLen: int - var argLenNode = newIntLit(0) - let argsName = ident("argsToPassToGodot") - if args.len > 0: - for arg in args: - if arg.isVarargs: - varargsName = arg.name - isVarargs = true - vars.add(newIdentDefs(ident("callError"), ident("VariantCallError"))) - break - let argsAlloc = newNode(nkCast).addChain( - newNode(nkPtrTy).addChain( - newNode(nkBracketExpr).addChain( - ident("array"), ident("MAX_ARG_COUNT"), - if isVarargs: ident("Variant") else: ident("pointer")))) - staticArgsLen = if varargsName.isNil: args.len - else: args.len - 1 - if not varargsName.isNil: - argLenNode = newCall("cint", - newInfix(newIntLit(staticArgsLen), - ident("+"), - newDotExpr(ident(varargsName), ident("len")))) - argsAlloc.add(newCall("godotAlloc", newCall("cint", newInfix( - newCall("sizeof", ident("Variant")), ident("*"), - newNode(nkPar).addChain(argLenNode)))) - ) - else: - argLenNode = newCall("cint", newIntLit(staticArgsLen)) - vars.add(newIdentDefs( - ident("argsStatic"), - newNode(nkBracketExpr).addChain( - ident("array"), newIntLit(staticArgsLen), ident("pointer")), - newNode(nkEmpty))) - argsAlloc.add(newCommand(ident("addr"), ident("argsStatic"))) - vars.add(newIdentDefs(argsName, newNode(nkEmpty), argsAlloc)) - - let argConversions = newNode(nkStmtList) - for idx, arg in args: - var argName = ident(arg.name) - if arg.isVarargs: - argName = newNode(nkBracketExpr).addChain( - ident(varargsName), - newInfix(ident("idx"), ident("-"), newIntLit(staticArgsLen))) - let argIdx = if arg.isVarargs: ident("idx") else: newIntLit(idx) - let isStandardType = arg.typ in standardTypes - let convArg = if not varargsName.isNil: newCall("toGodot", argName) - elif isStandardType: newCall("unsafeAddr", argName) - elif arg.typ == "string": newCall("unsafeAddr", - ident("argToPassToGodot" & $idx)) - else: ident("argToPassToGodot" & $idx) # object - if not isStandardType and arg.isVarargs: - raise newException(ValueError, - "Non-standard type $# for varargs params of method $# of type $#" % - [arg.typ, godotMethodName, typ.godotName]) - if not isStandardType: - if arg.typ == "string": - argConversions.add(newNode(nkLetSection).addChain( - newIdentDefs(ident("argToPassToGodot" & $idx), newEmptyNode(), - newCall("toGodotString", argName)))) - else: - argConversions.add(newNode(nkLetSection).addChain( - newIdentDefs(ident("argToPassToGodot" & $idx), newEmptyNode(), - newDotExpr(argName, ident("godotObject"))))) - let argAsgn = newNode(nkAsgn).addChain( - newNode(nkBracketExpr).addChain( - newNode(nkBracketExpr).addChain(argsName), argIdx), - convArg - ) - if not arg.isVarargs: - argConversions.add( - argAsgn - ) - else: - argConversions.add(newNode(nkVarSection).addChain( - newIdentDefs(ident("idx"), newNode(nkEmpty), newIntLit(staticArgsLen)))) - let argLoop = newNode(nkWhileStmt) - argConversions.add(argLoop) - argLoop.add(newInfix(ident("idx"), ident("<"), argLenNode) - ) - argLoop.add(argAsgn) - argLoop.add(newCommand(ident("inc"), ident("idx"))) - - let retName = if isVarargs: "callRet" else: "ptrCallRet" - let theCall = newCall( - newDotExpr(ident(methodBindName), - ident(if isVarargs: "call" else: "ptrCall")), - newDotExpr(ident("self"), ident("godotObject")), - if args.len > 0: argsName else: newNode(nkNilLit), - argLenNode, - if not isVarargs: ident(retName) else: ident("callError") - ) - if not isVarargs: - theCall.sons.delete(3) - let freeCall = newCall("godotFree", argsName) - body = newNode(nkStmtList) - if typ.isSingleton: - let varName = singletonName(typ.name) - body.add(newNilCheck(varName, newCall( - newBracketExpr(ident("getSingleton"), ident(typ.name))))) - body.add(newNode(nkLetSection).addChain(newIdentDefs( - ident("self"), newNode(nkEmpty), varName - ))) - if not varargsName.isNil: - body.add( - pragma(ident("push"), newExprColonExpr( - newBracketExpr(ident("warning"), ident("Destructor")), - ident("off")))) - body.add(nilCheck) - body.add(vars) - body.add(argConversions) - if not isVarargs: - let retPtrDecl = newNode(nkVarSection).addChain( - newIdentDefs(ident(retName), ident("pointer"), newEmptyNode()) - ) - body.add(retPtrDecl) - var isVariantRet: bool - var isConversionRet: bool - var isObjRet: bool - var isStringRet: bool - let retValIdent = if not isVarargs: ident("ptrCallVal") else: ident(retName) - if not returnType.isNil and varargsName.isNil: - var addrToAssign = newCall("addr", ident("ptrCallVal")) - if returnType in smallIntTypes: - isConversionRet = true - body.add(newNode(nkVarSection).addChain(newIdentDefs( - retValIdent, ident("int64"), - ))) - elif returnType in float32Types: - isConversionRet = true - body.add(newNode(nkVarSection).addChain(newIdentDefs( - retValIdent, ident("float64"), - ))) - elif returnType in standardTypes: - addrToAssign = newCall("addr", ident("result")) - elif returnType == "string": - isStringRet = true - body.add(newNode(nkVarSection).addChain(newIdentDefs( - retValIdent, ident("GodotString"), - ))) - else: - isObjRet = true - body.add(newNode(nkVarSection).addChain(newIdentDefs( - retValIdent, newNode(nkPtrTy).addChain(ident("GodotObject")), - ))) - body.add(newNode(nkAsgn).addChain(ident(retName), addrToAssign)) - - if not isVarargs: - body.add(theCall) - else: - if not returnType.isNil: - isVariantRet = true - let callStmt = newNode(nkLetSection).addChain( - newIdentDefs( - newNode(nkPragmaExpr).addChain( - ident(retName), newNode(nkPragma).addChain(ident("used"))), - newNode(nkEmpty), theCall)) - body.add(callStmt) - # if not returnType.isNil and not varargsName.isNil: - # body.add(newCall("fromGodot", ident("result"), ident(retName))) - # body.add(newCall("deinit", ident(retName))) - if args.len > 0 and not varargsName.isNil: - body.add(freeCall) - if not varargsName.isNil: - let errCheck = newIfStmt( - newInfix(newDotExpr(ident("callError"), ident("error")), ident("!="), - newDotExpr(ident("VariantCallErrorType"), ident("OK"))), - newNode(nkRaiseStmt).addChain( - newCall("newCallError", ident("callError"))) - ) - body.add(errCheck) - if isVariantRet: - let convErrDef = newNode(nkLetSection).addChain( - newIdentDefs(ident("convErr"), newNode(nkEmpty), - newCall("fromGodot", ident("result"), retValIdent))) - let convCheck = newIfStmt( - newInfix(ident("convErr"), ident("!="), - newDotExpr(ident("ConversionResult"), ident("OK"))), - newNode(nkRaiseStmt).addChain( - newCall("newConversionError", ident("convErr"))) - ) - body.add(convErrDef) - body.add(convCheck) - if not isVarargs and (isVariantRet or isStringRet): - # varargs use call with "let" so destructor is invoked - body.add(newCall("deinit", retValIdent)) - elif isConversionRet: - body.add(newNode(nkAsgn).addChain(ident("result"), - newCall(returnType, retValIdent))) - elif isObjRet: - body.add(newNode(nkAsgn).addChain(ident("result"), - newCall(newBracketExpr(ident("asNimGodotObject"), - newCall("type", ident("result"))), retValIdent))) - elif isStringRet: - body.add(newNode(nkAsgn).addChain(ident("result"), - newCall("$", retValIdent))) - if not varargsName.isNil: - body.add( - pragma(ident("push"), newExprColonExpr( - newBracketExpr(ident("warning"), ident("Destructor")), - ident("on")))) - - let procType = if isVirtual: nkMethodDef - else: nkProcDef - var params = newSeqOfCap[PNode](args.len + 2) - if not returnType.isNil: - params.add(ident(returnType)) - else: - params.add(newNode(nkEmpty)) - if not typ.isSingleton: - params.add(newIdentDefs(ident("self"), ident(toNimType(typ.name)))) - - for arg in args: - if arg.isVarargs: - params.add(newIdentDefs(ident(arg.name), - newNode(nkBracketExpr).addChain(ident("varargs"), ident(arg.typ)))) - else: - let defaultValue = arg.makeDefaultValue() - params.add(newIdentDefs(ident(arg.name), ident(arg.typ), defaultValue)) - let procDecl = newProc(if not withImplementation: postfix(name, "*") - else: name, - params, body, procType) - if not withImplementation: - let pragma = newNode(nkPragma) - pragma.add(ident("gcsafe")) - pragma.add(newNode(nkExprColonExpr).addChain(ident("locks"), - newIntLit(0))) - if isVirtual and isBase: - pragma.add(ident("base")) - procDecl.sons[4] = pragma - tree.add(procDecl) - -proc generateMethod(tree: PNode, methodBindRegistry: var HashSet[string], - name: PNode, godotMethodName: string, - typ: GodotType, args: seq[MethodArg], - returnType: string, isVirtual, isBase, withImplementation: bool) = - doGenerateMethod( - tree, methodBindRegistry, name, godotMethodName, typ, - args, returnType, isVirtual, isBase, withImplementation) - -proc makeProperty(types: Table[string, GodotType], tree: PNode, - methodBindRegistry: var HashSet[string], - typ: GodotType, - propertyObj: JsonNode, withImplementation: bool) = - let getterNameStr = toNimStyle(propertyObj["name"].str) - let getterName = ident(toNimStyle(propertyObj["name"].str)) - let setterName = newNode(nkAccQuoted).addChain(ident(getterNameStr & "=")) - - let nimType = toNimType(types, propertyObj["type"].str) - generateMethod(tree, methodBindRegistry, - getterName, propertyObj["getter"].str, typ, - @[], nimType, isVirtual = false, - isBase = false, withImplementation) - generateMethod(tree, methodBindRegistry, - setterName, propertyObj["setter"].str, typ, - @[("val", nimType, JsonNode(nil), false)], - nil, isVirtual = false, isBase = false, withImplementation) - -proc makeMethod(types: Table[string, GodotType], tree: PNode, - methodBindRegistry: var HashSet[string], - typ: GodotType, methodObj: JsonNode, - withImplementation: bool) = - let returnType = if methodObj["return_type"].str != "void": - toNimType(types, methodObj["return_type"].str) - else: nil - - for prop in typ.jsonNode["properties"]: - if prop["getter"].str == methodObj["name"].str or - prop["setter"].str == methodObj["name"].str: - return - - var args = newSeqOfCap[MethodArg](methodObj["arguments"].len + 1) - var origArgs = methodObj["arguments"] - var isBase = methodObj["is_virtual"].bval - if methodObj["is_virtual"].bval: - proc getMethod(typNode: JsonNode, methName: string): JsonNode = - for meth in typNode["methods"]: - if meth["is_virtual"].bval and - meth["name"].str == methName: return meth - var curTyp = types.getOrDefault(typ.baseName) - while not curTyp.isNil: - let meth = curTyp.jsonNode.getMethod(methodObj["name"].str) - if not meth.isNil: - origArgs = meth["arguments"] - isBase = false - curTyp = types.getOrDefault(curTyp.baseName) - - for arg in origArgs: - let typ = toNimType(types, arg["type"].str) - let defaultVal = if arg["has_default_value"].bval: arg["default_value"] - else: nil - args.add((toNimStyle(arg["name"].str), typ, - defaultVal, false)) - if methodObj["has_varargs"].bval: - args.add(("variantArgs", "Variant", JsonNode(nil), true)) - - let godotName = methodObj["name"].str - generateMethod(tree, methodBindRegistry, - ident(toNimStyle(godotName)), methodObj["name"].str, - typ, args, - returnType, methodObj["is_virtual"].bval, isBase, - withImplementation) - -proc addAttributeToDoc(doc: var string, propName, propValue: string) = - if doc.len > 0: - doc.add("\n") - doc.add(propName & ": " & propValue) - -const classAttributes = ["singleton", "instanciable", "is_reference"] - -proc typeNameToModuleName(name: string): string = - var wasUpperOrDigit = true - result = newStringOfCap(name.len + 10) - for idx, c in name: - if c.isUpperAscii() or c.isDigit(): - if not wasUpperOrDigit or idx > 0 and idx < name.len - 1 and - name[idx + 1].isLowerAscii(): - result.add('_') - result.add(c.toLowerAscii()) - wasUpperOrDigit = true - else: - result.add(c) - wasUpperOrDigit = false - if result == "object": - # keyword - result = "objects" - if result == "os": - # to avoid clash with stdlib - result = "gd_os" - -proc newRegisterClassNode(typ: GodotType): PNode = - newCall("registerClass", - ident(typ.name), - newCStringLit(typ.godotName), - ident("true") # isNative - ) - -proc genSingletonDecl(typ: string): PNode = - result = newNode(nkVarSection) - let name = singletonName(typ) - let threadvar = newNode(nkPragma).addChain(ident("threadvar")) - result.add(newIdentDefs(newNode(nkPragmaExpr).addChain(name, threadvar), - ident(typ))) - -proc shouldExport(typ: GodotType, types: Table[string, GodotType]): bool = - var curTyp = typ - while not curTyp.isNil and not curTyp.isSingleton: - curTyp = types.getOrDefault(curTyp.baseName) - result = curTyp.isNil - -proc genTypeFile*(types: var Table[string, GodotType], targetDir: string) = - for typ in types.values(): - types.incDerivedCount(typ.baseName) - - var sortedTypes = toSeq(types.values()) - sortedTypes.sort do (x, y: GodotType) -> int: - cmp(y.derivedCount, x.derivedCount) - - let godotApiTypesTree = newNode(nkStmtList) - godotApiTypesTree.add(newNode(nkImportStmt).addChain(ident("godot"))) - let typeSection = newNode(nkTypeSection) - godotApiTypesTree.add(typeSection) - - for typ in sortedTypes: - if not typ.shouldExport(types): continue - newRefTypeNode(typeSection, typ.name, typ.baseName, typ.doc) - - for typ in sortedTypes: - if not typ.shouldExport(types): continue - let regNode = newCall("registerClass", - ident(typ.name), - newCStringLit(typ.godotName), - ident("true") # isNative - ) - godotApiTypesTree.add(regNode) - - renderModule(godotApiTypesTree, targetDir / "godottypes.nim") - -proc genApi*(targetDir: string, apiJsonFile: string) = - let apiJson = parseJson(newFileStream(apiJsonFile), - apiJsonFile.extractFilename()) - var megaImport = newStringOfCap(64 * 1024) - - var types = initTable[string, GodotType]() - for obj in apiJson: - let godotClassName = obj["name"].str - let className = godotClassName.replace("_", "") - var baseClassName = obj["base_class"].str - baseClassName = toNimType(baseClassName.replace("_", "")) - if baseClassName.isNil or baseClassName.len == 0: - baseClassName = "NimGodotObject" - var doc = "" - for attr in classAttributes: - if attr in obj: - addAttributeToDoc(doc, attr, $obj[attr]) - types[className] = GodotType( - name: className, - godotName: godotClassName, - baseName: baseClassName, - doc: doc, - jsonNode: obj, - isSingleton: obj["singleton"].bval - ) - for typ in types.values(): - let tree = newNode(nkStmtList) - let importStmt = newNode(nkImportStmt) - importStmt.add(ident("godot")) - importStmt.add(ident("godottypes")) - importStmt.add(newDotExpr(ident("core"), ident("godotcore"))) - tree.add(importStmt) - let exportStmt = newNode(nkExportStmt) - exportStmt.add(ident("godottypes")) - tree.add(exportStmt) - - var methodBindRegsitry = initSet[string]() - let obj = typ.jsonNode - if typ.baseName != "NimGodotObject": - let baseModule = typeNameToModuleName(typ.baseName) - let baseModuleNode = if getIdent(baseModule).isKeyword: - newStrLit(baseModule & ".nim") - else: - ident(baseModule) - importStmt.add(baseModuleNode) - exportStmt.add(baseModuleNode) - let constSection = makeConstSection(obj["constants"]) - if constSection.kind != nkEmpty: - # renderer doesn't properly render empty stmt after type section - tree.add(makeConstSection(obj["constants"])) - - if typ.isSingleton: - let typeDecl = newNode(nkTypeSection) - newRefTypeNode(typeDecl, typ.name, typ.baseName, typ.doc, - isExported = false) - tree.add(typeDecl) - tree.add(newRegisterClassNode(typ)) - tree.add(genSingletonDecl(typ.name)) - - # first, generate declarations only for ease of - # human readability of the file - for property in obj["properties"]: - makeProperty(types, tree, methodBindRegsitry, typ, property, - withImplementation = false) - for meth in obj["methods"]: - makeMethod(types, tree, methodBindRegsitry, typ, - meth, withImplementation = false) - - for property in obj["properties"]: - makeProperty(types, tree, methodBindRegsitry, typ, - property, withImplementation = true) - for meth in obj["methods"]: - makeMethod(types, tree, methodBindRegsitry, typ, meth, - withImplementation = true) - - let moduleName = typeNameToModuleName(typ.name) - renderModule(tree, targetDir / moduleName & ".nim") - - megaImport.add("import \"" & moduleName & "\"\n") - - genTypeFile(types, targetDir) - - writeFile(targetDir / "godotall.nim", megaImport) - writeFile(targetDir / splitPath(targetDir)[1] & ".nimble", "") - -when isMainModule: - import os - - const usage = slurp("usage.txt") - - proc main() = - if paramCount() < 2: - echo usage - quit(-1) - let godotBin = paramStr(1) - let targetDir = paramStr(2) - - if not dirExists(targetDir): - echo "The specified directory does not exist" - quit(-1) - if not fileExists(godotBin): - echo "Invalid godot binary path" - quit(-1) - - let jsonFile = targetDir / "api.json" - if fileExists(jsonFile) and - godotBin.getLastModificationTime() <= jsonFile.getLastModificationTime(): - echo "api.json if up to date - doing nothing." - return - - discard execShellCmd( - "\"" & godotBin & "\" --gdnative-generate-json-api \"" & jsonFile & "\"") - if not fileExists(jsonFile): - echo "Failed to generate api.json" - quit(-1) - - genApi(targetDir, jsonFile) - - main() diff --git a/godot/apigen/usage.txt b/godot/apigen/usage.txt deleted file mode 100644 index 566634c..0000000 --- a/godot/apigen/usage.txt +++ /dev/null @@ -1,3 +0,0 @@ -Tool for wrapping Godot API into Nim - - apigen [godot binary path] [target directory] \ No newline at end of file diff --git a/godot/core/aabb.nim b/godot/core/aabb.nim new file mode 100644 index 0000000..2d816da --- /dev/null +++ b/godot/core/aabb.nim @@ -0,0 +1,79 @@ +# Copyright (c) 2018 Xored Software, Inc. + +import hashes + +import vector3 +import internal/godotinternaltypes, internal/godotstrings +import godotcoretypes, gdnativeapi + +proc initAABB*(pos, size: Vector3): AABB {.inline.} = + AABB(position: pos, size: size) + +proc `$`*(self: AABB): string {.inline.} = + $getGDNativeAPI().aabbAsString(self) + +proc hash*(self: AABB): Hash {.inline.} = + !$(self.position.hash() !& self.size.hash()) + +proc area*(self: AABB): float32 {.inline.} = + getGDNativeAPI().aabbGetArea(self) + +proc hasNoArea*(self: AABB): bool {.inline.} = + getGDNativeAPI().aabbHasNoArea(self) + +proc hasNoSurface*(self: AABB): bool {.inline.} = + getGDNativeAPI().aabbHasNoSurface(self) + +proc intersects*(self, other: AABB): bool {.inline.} = + getGDNativeAPI().aabbIntersects(self, other) + +proc encloses*(self, other: AABB): bool {.inline.} = + getGDNativeAPI().aabbEncloses(self, other) + +proc merge*(self, other: AABB): AABB {.inline.} = + getGDNativeAPI().aabbMerge(self, other).toAABB() + +proc intersection*(self, other: AABB): AABB {.inline.} = + getGDNativeAPI().aabbIntersection(self, other).toAABB() + +proc intersectsPlane*(self: AABB; plane: Plane): bool {.inline.} = + getGDNativeAPI().aabbIntersectsPlane(self, plane) + +proc intersectsSegment*(self: AABB; start, to: Vector3): bool {.inline.} = + getGDNativeAPI().aabbIntersectsSegment(self, start, to) + +proc contains*(self: AABB; point: Vector3): bool {.inline.} = + getGDNativeAPI().aabbHasPoint(self, point) + +proc getSupport*(self: AABB; dir: Vector3): Vector3 {.inline.} = + getGDNativeAPI().aabbGetSupport(self, dir).toVector3() + +proc getLongestAxis*(self: AABB): Vector3 {.inline.} = + getGDNativeAPI().aabbGetLongestAxis(self).toVector3() + +proc getLongestAxisIndex*(self: AABB): cint {.inline.} = + getGDNativeAPI().aabbGetLongestAxisIndex(self) + +proc getLongestAxisSize*(self: AABB): float32 {.inline.} = + getGDNativeAPI().aabbGetLongestAxisSize(self) + +proc getShortestAxis*(self: AABB): Vector3 {.inline.} = + getGDNativeAPI().aabbGetShortestAxis(self).toVector3() + +proc getShortestAxisIndex*(self: AABB): cint {.inline.} = + getGDNativeAPI().aabbGetShortestAxisIndex(self) + +proc getShortestAxisSize*(self: AABB): float32 {.inline.} = + getGDNativeAPI().aabbGetShortestAxisSize(self) + +proc expand*(self: AABB; toPoint: Vector3): AABB {.inline.} = + getGDNativeAPI().aabbExpand(self, toPoint).toAABB() + +proc grow*(self: AABB; by: float32): AABB {.inline.} = + getGDNativeAPI().aabbGrow(self, by).toAABB() + +proc getEndpoint*(self: AABB; idx: cint): Vector3 {.inline.} = + getGDNativeAPI().aabbGetEndpoint(self, idx).toVector3() + +proc `==`*(a, b: AABB): bool {.inline.} = + getGDNativeAPI().aabbOperatorEqual(a, b) diff --git a/godot/core/arrays.nim b/godot/core/arrays.nim index 8359fc7..fcbafb2 100644 --- a/godot/core/arrays.nim +++ b/godot/core/arrays.nim @@ -1,145 +1,146 @@ -# Copyright (c) 2017 Xored Software, Inc. +# Copyright 2018 Xored Software, Inc. import hashes -import godotbase, poolarray, variant, strings +import internal/godotinternaltypes, internal/godotarrays -proc initArray(dest: var Array) {. - importc: "godot_array_new", header: "godot_array.h".} -proc initArray(dest: var Array; pca: PoolColorArray) {. - importc: "godot_array_new_pool_coloarray", - header: "godot_array.h".} -proc initArray(dest: var Array; pv3a: PoolVector3Array) {. - importc: "godot_array_new_pool_vector3_array", - header: "godot_array.h".} -proc initArray(dest: var Array; pv2a: PoolVector2Array) {. - importc: "godot_array_new_pool_vector2_array", - header: "godot_array.h".} -proc initArray(dest: var Array; psa: PoolStringArray) {. - importc: "godot_array_new_pool_string_array", - header: "godot_array.h".} -proc initArray(dest: var Array; pra: PoolRealArray) {. - importc: "godot_array_new_pool_real_array", - header: "godot_array.h".} -proc initArray(dest: var Array; pia: PoolIntArray) {. - importc: "godot_array_new_pool_int_array", - header: "godot_array.h".} -proc initArray(dest: var Array; pba: PoolByteArray) {. - importc: "godot_array_new_pool_byte_array", - header: "godot_array.h".} +type + Array* = ref object + godotArray: GodotArray -proc initArray*(): Array {.inline.} = - initArray(result) +proc godotArray*(arr: Array): ptr GodotArray {.inline.} = + ## WARNING: do not keep the returned value for longer than the lifetime of + ## ``arr`` + addr arr.godotArray -proc initArray*(pca: PoolColorArray): Array {.inline.} = - initArray(result, pca) +proc arrayFinalizer(arr: Array) = + arr.godotArray.deinit() -proc initArray*(pv3a: PoolVector3Array): Array {.inline.} = - initArray(result, pv3a) +proc newArray*(arr: GodotArray): Array {.inline.} = + new(result, arrayFinalizer) + result.godotArray = arr -proc initArray*(pv2a: PoolVector2Array): Array {.inline.} = - initArray(result, pv2a) +import variants -proc initArray*(psa: PoolStringArray): Array {.inline.} = - initArray(result, psa) +proc newArray*(s: varargs[Variant]): Array = + new(result, arrayFinalizer) + initGodotArray(result.godotArray) + for v in s: + result.godotArray.add(v.godotVariant[]) -proc initArray*(pra: PoolRealArray): Array {.inline.} = - initArray(result, pra) +proc newArray*(s: openarray[Variant]): Array = + result = newArray() + for v in s: + result.godotArray.add(v.godotVariant[]) -proc initArray*(pia: PoolIntArray): Array {.inline.} = - initArray(result, pia) +import poolarrays -proc initArray*(pba: PoolByteArray): Array {.inline.} = - initArray(result, pba) +proc newArray*(pca: PoolColorArray): Array {.inline.} = + new(result, arrayFinalizer) + initGodotArray(result.godotArray, pca.godotPoolColorArray[]) -proc `[]=`*(self: var Array; idx: cint; - value: Variant) {. - noSideEffect, - importc: "godot_array_set", header: "godot_array.h".} -proc `[]`*(self: Array; idx: cint): Variant {. - noSideEffect, - importc: "godot_array_get", header: "godot_array.h".} -proc mget*(self: var Array; idx: cint): ptr Variant {. - importc: "godot_array_operator_index", header: "godot_array.h".} +proc newArray*(pv3a: PoolVector3Array): Array {.inline.} = + new(result, arrayFinalizer) + initGodotArray(result.godotArray, pv3a.godotPoolVector3Array[]) -proc add*(self: var Array; value: Variant) {. - noSideEffect, - importc: "godot_array_append", header: "godot_array.h".} -proc clear*(self: var Array) {.importc: "godot_array_clear", - header: "godot_array.h".} -proc count*(self: Array; value: Variant): cint {. - noSideEffect, - importc: "godot_array_count", header: "godot_array.h".} -proc isEmpty*(self: Array): bool {. - noSideEffect, - importc: "godot_array_empty", header: "godot_array.h".} -proc erase*(self: var Array; value: Variant) {. - importc: "godot_array_erase", header: "godot_array.h".} -proc first*(self: Array): Variant {. - noSideEffect, - importc: "godot_array_front", header: "godot_array.h".} -proc last*(self: Array): Variant {. - noSideEffect, - importc: "godot_array_back", header: "godot_array.h".} -proc find*(self: Array; what: Variant; - f: cint): cint {. - noSideEffect, - importc: "godot_array_find", header: "godot_array.h".} -proc findLast*(self: Array; what: Variant): cint {. - noSideEffect, - importc: "godot_array_find_last", header: "godot_array.h".} -proc contains*(self: Array; value: Variant): bool {. - noSideEffect, - importc: "godot_array_has", header: "godot_array.h".} +proc newArray*(pv2a: PoolVector2Array): Array {.inline.} = + new(result, arrayFinalizer) + initGodotArray(result.godotArray, pv2a.godotPoolVector2Array[]) + +proc newArray*(psa: PoolStringArray): Array {.inline.} = + new(result, arrayFinalizer) + initGodotArray(result.godotArray, psa.godotPoolStringArray[]) + +proc newArray*(pra: PoolRealArray): Array {.inline.} = + new(result, arrayFinalizer) + initGodotArray(result.godotArray, pra.godotPoolRealArray[]) + +proc newArray*(pia: PoolIntArray): Array {.inline.} = + new(result, arrayFinalizer) + initGodotArray(result.godotArray, pia.godotPoolIntArray[]) + +proc newArray*(pba: PoolByteArray): Array {.inline.} = + new(result, arrayFinalizer) + initGodotArray(result.godotArray, pba.godotPoolByteArray[]) + +proc `[]=`*(self: Array; idx: int; value: Variant) {.inline.} = + self.godotArray[idx.cint] = value.godotVariant[] + +proc `[]`*(self: Array; idx: int): Variant {.inline.} = + newVariant(self.godotArray[idx.cint]) + +proc add*(self: Array; value: Variant) {.inline.} = + self.godotArray.add(value.godotVariant[]) + +proc clear*(self: Array) {.inline.} = + self.godotArray.clear() + +proc count*(self: Array; value: Variant): int {.inline.} = + self.godotArray.count(value.godotVariant[]).int + +proc isEmpty*(self: Array): bool {.inline.} = + self.godotArray.isEmpty() + +proc erase*(self: Array; value: Variant) {.inline.} = + self.godotArray.erase(value.godotVariant[]) + +proc first*(self: Array): Variant {.inline.} = + newVariant(self.godotArray.first()) + +proc last*(self: Array): Variant {.inline.} = + newVariant(self.godotArray.last()) + +proc find*(self: Array; what: Variant; f: int): int {.inline.} = + self.godotArray.find(what.godotVariant[], f.cint).int + +proc findLast*(self: Array; what: Variant): int {.inline.} = + self.godotArray.findLast(what.godotVariant[]).int + +proc contains*(self: Array; value: Variant): bool {.inline.} = + self.godotArray.contains(value.godotVariant[]) -proc godotHash*(self: Array): cint {. - noSideEffect, - importc: "godot_array_hash", header: "godot_array.h".} proc hash*(self: Array): Hash {.inline.} = - hash(godotHash(self)) + hash(self.godotArray.godotHash()) -proc insert*(self: var Array; pos: cint; - value: Variant) {. - importc: "godot_array_insert", header: "godot_array.h".} -proc reverse*(self: var Array) {.importc: "godot_array_invert", - header: "godot_array.h".} -proc popLast*(self: var Array): Variant {. - importc: "godot_array_pop_back", header: "godot_array.h".} -proc popFirst*(self: var Array): Variant {. - importc: "godot_array_pop_front", header: "godot_array.h".} -proc addLast*(self: var Array; value: Variant) {. - importc: "godot_array_push_back", header: "godot_array.h".} -proc addFirst*(self: var Array; value: Variant) {. - importc: "godot_array_push_front", header: "godot_array.h".} +proc insert*(self: Array; pos: int; value: Variant) {.inline.} = + self.godotArray.insert(pos.cint, value.godotVariant[]) -proc delete*(self: var Array; idx: cint) {. - importc: "godot_array_remove", header: "godot_array.h".} -proc setLen*(self: var Array; size: cint) {. - importc: "godot_array_resize", header: "godot_array.h".} -proc rfind*(self: Array; what: Variant; - f: cint): cint {. - noSideEffect, - importc: "godot_array_rfind", header: "godot_array.h".} -proc len*(self: Array): cint {. - noSideEffect, - importc: "godot_array_size", header: "godot_array.h".} -proc sort*(self: var Array) {.importc: "godot_array_sort", - header: "godot_array.h".} -proc sortCustom*(self: var Array; obj: var GodotObject; - funcName: GodotString) {. - importc: "godot_array_sort_custom", header: "godot_array.h".} +proc reverse*(self: Array) {.inline.} = + self.godotArray.reverse() -iterator items*(arr: Array): Variant = - for i in 0.. -PI * 0.5: + result.x = arctan2(-self.elements[1].z, self.elements[2].z) + result.z = arctan2(-self.elements[0].y, self.elements[0].x) + else: + let r = arctan2(self.elements[1].x, self.elements[1].y) + result.x = -r + else: + let r = arctan2(self.elements[0].y, self.elements[1].y) + result.x = r proc initBasis*(euler: Vector3): Basis {.inline.} = - initBasis(result, euler) + result.setEuler(euler) -proc toGodotString*(self: Basis): GodotString {. - noSideEffect, - importc: "godot_basis_as_string", header: "godot_basis.h".} +proc outer*(self, other: Vector3): Basis {.inline.} = + let row0 = vec3(self.x * other.x, self.x * other.y, self.x * other.z) + let row1 = vec3(self.y * other.x, self.y * other.y, self.y * other.z) + let row2 = vec3(self.z * other.x, self.z * other.y, self.z * other.z) + initBasis(row0, row1, row2) + +proc toDiagonalMatrix*(self: Vector3): Basis {.inline.} = + initBasis( + self.x, 0, 0, + 0, self.y, 0, + 0, 0, self.z + ) proc `$`*(self: Basis): string {.inline.} = - $self.toGodotString() + result = newStringOfCap(128) + for i in 0..2: + for j in 0..2: + if i != 0 or j != 0: + result.add(", ") + result.add($self[i][j]) -proc inverse*(self: Basis): Basis {. - noSideEffect, - importc: "godot_basis_inverse", header: "godot_basis.h".} -proc transposed*(self: Basis): Basis {. - noSideEffect, - importc: "godot_basis_transposed", header: "godot_basis.h".} -proc orthonormalized*(self: Basis): Basis {. - noSideEffect, - importc: "godot_basis_orthonormalized", header: "godot_basis.h".} -proc determinant*(self: Basis): float32 {. - noSideEffect, - importc: "godot_basis_determinant", header: "godot_basis.h".} -proc rotated*(self: Basis; axis: Vector3; - phi: float32): Basis {. - noSideEffect, - importc: "godot_basis_rotated", header: "godot_basis.h".} -proc scaled*(self: Basis; scale: Vector3): Basis {. - noSideEffect, - importc: "godot_basis_scaled", header: "godot_basis.h".} +proc hash*(self: Basis): Hash {.inline.} = + !$(self.elements[0].hash() !& self.elements[1].hash() !& self.elements[2].hash()) -proc setScale*(self: var Basis; scale: Vector3) {. - noSideEffect, - importc: "godot_basis_set_scale", header: "godot_basis.h".} -proc setRotationEuler*(self: var Basis; - euler: Vector3) {. - noSideEffect, - importc: "godot_basis_set_rotation_euler", header: "godot_basis.h".} -proc setRotationAxisAngle*(self: var Basis; axis: Vector3; angle: float32) {. - noSideEffect, - importc: "godot_basis_set_rotation_axis_angle", header: "godot_basis.h".} +template cofac(row1, col1, row2, col2: int): float32 = + self.elements[row1][col1] * self.elements[row2][col2] - + self.elements[row1][col2] * self.elements[row2][col1] -proc scale*(self: Basis): Vector3 {. - noSideEffect, - importc: "godot_basis_get_scale", header: "godot_basis.h".} -proc euler*(self: Basis): Vector3 {. - noSideEffect, - importc: "godot_basis_get_euler", header: "godot_basis.h".} +proc determinant(self: Basis): float32 {.inline.} = + self[0][0] * cofac(1, 1, 2, 2) - + self[1][0] * cofac(0, 1, 2, 2) + + self[2][0] * cofac(0, 1, 1, 2) -proc tdotx*(self: Basis; x: Vector3): float32 {. - noSideEffect, - importc: "godot_basis_tdotx", header: "godot_basis.h".} -proc tdoty*(self: Basis; y: Vector3): float32 {. - noSideEffect, - importc: "godot_basis_tdoty", header: "godot_basis.h".} -proc tdotz*(self: Basis; z: Vector3): float32 {. - noSideEffect, - importc: "godot_basis_tdotz", header: "godot_basis.h".} +proc invert*(self: var Basis) = + let co = [cofac(1, 1, 2, 2), cofac(1, 2, 2, 0), cofac(1, 0, 2, 1)] + let det = self.elements[0][0] * co[0] + + self.elements[0][1] * co[1] + + self.elements[0][2] * co[2] + assert(det != 0) + let s = 1.0'f32 / det + self.setCells( + co[0] * s, cofac(0, 2, 2, 1) * s, cofac(0, 1, 1, 2) * s, + co[1] * s, cofac(0, 0, 2, 2) * s, cofac(0, 2, 1, 0) * s, + co[2] * s, cofac(0, 1, 2, 0) * s, cofac(0, 0, 1, 1) * s + ) -proc xform*(self: Basis; v: Vector3): Vector3 {. - noSideEffect, - importc: "godot_basis_xform", header: "godot_basis.h".} -proc xformInv*(self: Basis; v: Vector3): Vector3 {. - noSideEffect, - importc: "godot_basis_xform_inv", header: "godot_basis.h".} +proc inverse*(self: Basis): Basis {.inline.} = + result = self + result.invert() -proc orthogonalIndex*(self: Basis): cint {. - noSideEffect, - importc: "godot_basis_get_orthogonal_index", header: "godot_basis.h".} +proc axis*(self: Basis; idx: range[0..2]): Vector3 {.inline.} = + vec3(self[0][idx], self[1][idx], self[2][idx]) -proc godot_basis_get_elements(self: Basis; - elements: var array[3, Vector3]) {. - noSideEffect, - importc: "godot_basis_get_elements", header: "godot_basis.h".} +proc setAxis*(self: var Basis; idx: range[0..2]; value: Vector3) {.inline.} = + self.elements[0][idx] = value.x + self.elements[1][idx] = value.y + self.elements[2][idx] = value.z -proc elements*(self: Basis): array[3, Vector3] {.inline.} = - godot_basis_get_elements(self, result) +proc row*(self: Basis; row: range[0..2]): Vector3 {.inline.} = + self.elements[row] -proc `[]`*(self: Basis; axis: range[0..2]): Vector3 {. - noSideEffect, - importc: "godot_basis_get_axis", header: "godot_basis.h".} -proc `[]=`*(self: var Basis; axis: range[0..2]; - value: Vector3) {. - noSideEffect, - importc: "godot_basis_set_axis", header: "godot_basis.h".} -proc row*(self: Basis; row: cint): Vector3 {. - noSideEffect, - importc: "godot_basis_get_row", header: "godot_basis.h".} -proc setRow*(self: var Basis; row: cint; - value: Vector3) {. - noSideEffect, - importc: "godot_basis_set_row", header: "godot_basis.h".} -proc `==`*(self: Basis; b: Basis): bool {. - noSideEffect, - importc: "godot_basis_operator_equal", header: "godot_basis.h".} -proc `+`*(self: Basis; b: Basis): Basis {. - noSideEffect, - importc: "godot_basis_operator_add", header: "godot_basis.h".} -proc `-`*(self: Basis; b: Basis): Basis {. - noSideEffect, - importc: "godot_basis_operator_substract", header: "godot_basis.h".} -proc `*`*(self: Basis; b: Basis): Basis {. - noSideEffect, - importc: "godot_basis_operator_multiply_vector", header: "godot_basis.h".} -proc `*`*(self: Basis; b: float32): Basis {. - noSideEffect, - importc: "godot_basis_operator_multiply_scalar", header: "godot_basis.h".} +proc setRow*(self: var Basis; row: range[0..2]; value: Vector3) {.inline.} = + self.elements[row] = value + +proc getMainDiagonal*(self: Basis): Vector3 {.inline.} = + vec3(self.elements[0][0], self.elements[1][1], self.elements[2][2]) + +proc zero*(self: var Basis) {.inline.} = + self.elements[0].zero() + self.elements[1].zero() + self.elements[2].zero() + +proc orthonormalize(self: var Basis) = + var x = self.axis(0) + var y = self.axis(1) + var z = self.axis(2) + + x.normalize() + y = y - x * x.dot(y) + y.normalize() + z = z - x * x.dot(z) - y * y.dot(z) + z.normalize() + + self.setAxis(0, x) + self.setAxis(1, y) + self.setAxis(2, z) + +proc orthonormalized*(self: Basis): Basis {.inline.} = + result = self + result.orthonormalize() + +proc transpose*(self: var Basis) {.inline.} = + swap(self.elements[0].x, self.elements[1].x) + swap(self.elements[0].z, self.elements[2].x) + swap(self.elements[1].z, self.elements[2].y) + +proc transposed*(self: Basis): Basis {.inline.} = + result = self + result.transpose() + +proc isOrthogonal*(self: Basis): bool {.inline.} = + let id = initBasis() + let m = self * self.transposed() + result = id.isEqualApprox(m) + +proc isRotation*(self: Basis): bool {.inline.} = + self.determinant().isEqualApprox(1.0) and self.isOrthogonal() + +proc isSymmetric*(self: Basis): bool {.inline.} = + if not self.elements[0][1].isEqualApprox(self.elements[1][0]): + return false + if not self.elements[0][2].isEqualApprox(self.elements[2][0]): + return false + if not self.elements[1][2].isEqualApprox(self.elements[2][1]): + return false + result = true + +proc scale*(self: var Basis, scale: Vector3) = + self[0].x *= scale.x + self[0].y *= scale.x + self[0].z *= scale.x + self[1].x *= scale.y + self[1].y *= scale.y + self[1].z *= scale.y + self[2].x *= scale.z + self[2].y *= scale.z + self[2].z *= scale.z + +proc scaled*(self: Basis, scale: Vector3): Basis = + result = self + result.scale(scale) + +proc rotated*(self: Basis; axis: Vector3; phi: float32): Basis {.inline.} = + initBasis(axis, phi) * self + +proc rotate*(self: var Basis; axis: Vector3; phi: float32) {.inline.} = + self = self.rotated(axis, phi) + +proc rotated*(self: Basis; euler: Vector3): Basis {.inline.} = + initBasis(euler) * self + +proc rotate*(self: var Basis; euler: Vector3) {.inline.} = + self = self.rotated(euler) + +proc getScale*(self: Basis): Vector3 = + let detSign = if self.determinant() > 0: 1'f32 else: -1'f32 + result = detSign * vec3( + vec3(self.elements[0].x, self.elements[1].x, self.elements[2].x).length(), + vec3(self.elements[0].y, self.elements[1].y, self.elements[2].y).length(), + vec3(self.elements[0].z, self.elements[1].z, self.elements[2].z).length(), + ) + +proc getRotation*(self: Basis): Vector3 {.inline.} = + var m = self.orthonormalized() + let det = m.determinant() + if det < 0: + m.scale(vec3(-1, -1, -1)) + result = m.getEuler() + +proc setScale*(self: var Basis; scale: Vector3) = + let e = self.getEuler() + self = initBasis() # reset to identity + self.scale(scale) + self.rotate(e) + +proc setRotationEuler*(self: var Basis; euler: Vector3) = + let s = self.getScale() + self = initBasis() + self.scale(s) + self.rotate(euler) + +proc setRotationAxisAngle*(self: var Basis; axis: Vector3; angle: float32) = + let s = self.getScale() + self = initBasis() + self.scale(s) + self.rotate(axis, angle) + +proc asQuat*(self: Basis): Quat = + let trace = self.elements[0].x + self.elements[1].y + self.elements[2].z + var temp: array[4, float32] + if trace > 0'f32: + var s = sqrt(trace + 1.0) + temp[3] = s * 0.5 + s = 0.5 / s + + temp[0] = (self.elements[2].y - self.elements[1].z) * s + temp[1] = (self.elements[0].z - self.elements[2].x) * s + temp[2] = (self.elements[1].x - self.elements[0].y) * s + else: + let i = if self.elements[0].x < self.elements[1].y: + if self.elements[1].y < self.elements[2].z: 2 else: 1 + else: + if self.elements[0].x < self.elements[2].z: 2 else: 0 + let j = (i + 1) mod 3 + let k = (i + 2) mod 3 + + var s = sqrt(self.elements[i][i] - self.elements[j][j] - + self.elements[k][k] + 1.0) + temp[i] = s * 0.5 + s = 0.5 / s + + temp[3] = (self.elements[k][j] - self.elements[j][k]) * s + temp[j] = (self.elements[j][i] + self.elements[i][j]) * s + temp[k] = (self.elements[k][i] + self.elements[i][k]) * s + + result = initQuat(temp[0], temp[1], temp[2], temp[3]) + +proc xform*(self: Basis; v: Vector3): Vector3 {.inline.} = + vec3( + self.elements[0].dot(v), + self.elements[1].dot(v), + self.elements[2].dot(v) + ) + +proc xformInv*(self: Basis; v: Vector3): Vector3 {.inline.} = + vec3( + self.elements[0].x * v.x + self.elements[1].x * v.y + self.elements[2].x * v.z, + self.elements[0].y * v.x + self.elements[1].y * v.y + self.elements[2].y * v.z, + self.elements[0].z * v.x + self.elements[1].z * v.y + self.elements[2].z * v.z, + ) + +const orthoBases = [ + initBasis(1, 0, 0, 0, 1, 0, 0, 0, 1), + initBasis(0, -1, 0, 1, 0, 0, 0, 0, 1), + initBasis(-1, 0, 0, 0, -1, 0, 0, 0, 1), + initBasis(0, 1, 0, -1, 0, 0, 0, 0, 1), + initBasis(1, 0, 0, 0, 0, -1, 0, 1, 0), + initBasis(0, 0, 1, 1, 0, 0, 0, 1, 0), + initBasis(-1, 0, 0, 0, 0, 1, 0, 1, 0), + initBasis(0, 0, -1, -1, 0, 0, 0, 1, 0), + initBasis(1, 0, 0, 0, -1, 0, 0, 0, -1), + initBasis(0, 1, 0, 1, 0, 0, 0, 0, -1), + initBasis(-1, 0, 0, 0, 1, 0, 0, 0, -1), + initBasis(0, -1, 0, -1, 0, 0, 0, 0, -1), + initBasis(1, 0, 0, 0, 0, 1, 0, -1, 0), + initBasis(0, 0, -1, 1, 0, 0, 0, -1, 0), + initBasis(-1, 0, 0, 0, 0, -1, 0, -1, 0), + initBasis(0, 0, 1, -1, 0, 0, 0, -1, 0), + initBasis(0, 0, 1, 0, 1, 0, -1, 0, 0), + initBasis(0, -1, 0, 0, 0, 1, -1, 0, 0), + initBasis(0, 0, -1, 0, -1, 0, -1, 0, 0), + initBasis(0, 1, 0, 0, 0, -1, -1, 0, 0), + initBasis(0, 0, 1, 0, -1, 0, 1, 0, 0), + initBasis(0, 1, 0, 0, 0, 1, 1, 0, 0), + initBasis(0, 0, -1, 0, 1, 0, 1, 0, 0), + initBasis(0, -1, 0, 0, 0, -1, 1, 0, 0) +] + +proc orthogonalIndex*(self: Basis): int = + var orth = self + for i in 0..2: + for j in 0..2: + var v = orth[i][j] + if v > 0.5: + v = 1.0'f32 + elif v < -0.5: + v = -1.0'f32 + else: + v = 0'f32 + orth[i][j] = v + + for idx, base in orthoBases: + if base == orth: + return idx + +proc setOrthogonalIndex*(self: var Basis, idx: range[0..23]) = + self = orthoBases[idx] + +proc rotate*(self: var Vector3; axis: Vector3; phi: float32) = + self = initBasis(axis, phi).xform(self) + +proc rotated*(self: Vector3; axis: Vector3; phi: float32): Vector3 = + result = self + result.rotate(axis, phi) + +{.pop.} # stackTrace: off \ No newline at end of file diff --git a/godot/core/color.nim b/godot/core/color.nim deleted file mode 100644 index 7faf63c..0000000 --- a/godot/core/color.nim +++ /dev/null @@ -1,76 +0,0 @@ -# Copyright (c) 2017 Xored Software, Inc. - -import godotbase, strings - -type - Color* {.importc: "godot_color", header: "godot_color.h", byref.} = object - -proc initColor(dest: var Color; r, g, b, a: float32) {. - importc: "godot_color_new_rgba", header: "godot_color.h".} -proc initColor(dest: var Color; r, g, b: float32) {. - importc: "godot_color_new_rgb", - header: "godot_color.h".} - -proc initColor*(r, g, b, a: float32): Color {.inline.} = - initColor(result, r, g, b, a) - -proc initColor*(r, g, b: float32): Color {.inline.} = - initColor(result, r, g, b) - -proc r*(self: Color): float32 {. - importc: "godot_color_get_r", header: "godot_color.h".} -proc `r=`*(self: var Color; r: float32) {. - importc: "godot_color_set_r", header: "godot_color.h".} -proc g*(self: Color): float32 {. - importc: "godot_color_get_g", header: "godot_color.h".} -proc `g=`*(self: var Color; g: float32) {. - importc: "godot_color_set_g", header: "godot_color.h".} -proc b*(self: Color): float32 {. - importc: "godot_color_get_b", header: "godot_color.h".} -proc `b=`*(self: var Color; b: float32) {. - importc: "godot_color_set_b", header: "godot_color.h".} -proc a*(self: Color): float32 {. - importc: "godot_color_get_a", header: "godot_color.h".} -proc `a=`*(self: var Color; a: float32) {. - importc: "godot_color_set_a", header: "godot_color.h".} - -proc h*(self: Color): float32 {. - importc: "godot_color_get_h", header: "godot_color.h".} -proc s*(self: Color): float32 {. - importc: "godot_color_get_s", header: "godot_color.h".} -proc v*(self: Color): float32 {. - importc: "godot_color_get_v", header: "godot_color.h".} - -proc toGodotString*(self: Color): GodotString {. - importc: "godot_color_as_string", header: "godot_color.h".} -proc `$`*(self: Color): string {.inline.} = - $self.toGodotString() - -proc toHtml*(self: Color; with_alpha: bool): GodotString {. - importc: "godot_color_to_html", header: "godot_color.h".} - -proc to32CInt(self: Color): cint {. - importc: "godot_color_to_32", header: "godot_color.h".} -proc toARGB32CInt(self: Color): cint {. - importc: "godot_color_to_ARGB32", header: "godot_color.h".} - -proc to32*(self: Color): uint32 {.inline.}= - cast[uint32](to32CInt(self)) -proc toARGB32*(self: Color): uint32 {.inline.} = - cast[uint32](toARGB32CInt(self)) - -proc gray*(self: Color): float32 {. - importc: "godot_color_gray", header: "godot_color.h".} -proc inverted*(self: Color): Color {. - importc: "godot_color_inverted", header: "godot_color.h".} -proc contrasted*(self: Color): Color {. - importc: "godot_color_contrasted", header: "godot_color.h".} -proc lerp*(self: Color; b: Color; t: float32): Color {. - importc: "godot_color_linear_interpolate", header: "godot_color.h".} -proc blend*(self: Color; over: Color): Color {. - importc: "godot_color_blend", header: "godot_color.h".} - -proc `==`*(self, b: Color): bool {. - importc: "godot_color_operator_equal", header: "godot_color.h".} -proc `<`*(self, b: Color): bool {. - importc: "godot_color_operator_less", header: "godot_color.h".} diff --git a/godot/core/colors.nim b/godot/core/colors.nim new file mode 100644 index 0000000..8e01b7a --- /dev/null +++ b/godot/core/colors.nim @@ -0,0 +1,88 @@ +# Copyright (c) 2018 Xored Software, Inc. + +import hashes + +import godotcoretypes, gdnativeapi + +proc initColor*(r, g, b: float32; a: float32 = 1.0'f32): Color {.inline.} = + Color( + r: r, + g: g, + b: b, + a: a + ) + +proc initColor*(): Color {.inline.} = + ## Initializes black color with 1.0 alpha + initColor(0, 0, 0) + +proc h*(self: Color): float32 {.inline.} = + getGDNativeAPI().colorGetH(self) + +proc s*(self: Color): float32 {.inline.} = + getGDNativeAPI().colorGetS(self) + +proc v*(self: Color): float32 {.inline.} = + getGDNativeAPI().colorGetV(self) + +proc `$`*(self: Color): string {.inline.} = + result = newStringOfCap(50) + result.add($self.r) + result.add(", ") + result.add($self.g) + result.add(", ") + result.add($self.b) + result.add(", ") + result.add($self.a) + +proc hash*(self: Color): Hash {.inline.} = + !$(self.r.hash() !& self.g.hash() !& self.b.hash() !& self.a.hash()) + +proc toHex(val: float32, target: var string, targetIdx: int) = + let val = clamp(int(val * 255), 0, 255) + let nums = [(val and 0xF0) shr 4, val and 0xF] + for i, num in nums: + target[targetIdx + i] = if num < 10: chr(ord('0') + num) + else: chr(ord('A') + (num - 10)) + +proc toHtml*(self: Color, withAlpha: bool): string = + let size = if withAlpha: 8 else: 6 + result = newString(size) + toHex(self.r, result, 0) + toHex(self.g, result, 2) + toHex(self.b, result, 4) + if withAlpha: + toHex(self.b, result, 6) + +proc toARGB32*(self: Color): uint32 {.inline.} = + result = uint8(self.a * 255) + result = (result shl 8) or uint8(self.r * 255) + result = (result shl 8) or uint8(self.g * 255) + result = (result shl 8) or uint8(self.b * 255) + +proc gray*(self: Color): float32 {.inline.} = + getGDNativeAPI().colorGray(self) + +proc inverted*(self: Color): Color {.inline.} = + getGDNativeAPI().colorInverted(self).toColor() + +proc contrasted*(self: Color): Color {.inline.} = + getGDNativeAPI().colorContrasted(self).toColor() + +proc lerp*(self: Color; b: Color; t: float32): Color {.inline.} = + getGDNativeAPI().colorLinearInterpolate(self, b, t).toColor() + +proc blend*(self: Color; over: Color): Color {.inline.} = + getGDNativeAPI().colorBlend(self, over).toColor() + +proc `==`*(a, b: Color): bool {.inline.} = + a.r == b.r and a.g == b.g and a.b == b.b and a.a == b.a + +proc `<`*(a, b: Color): bool = + if a.r == b.r: + if a.g == b.g: + if a.b == b.b: + return a.a < b.a + return a.b < b.b + return a.g < b.g + return a.r < b.r diff --git a/godot/core/dictionaries.nim b/godot/core/dictionaries.nim new file mode 100644 index 0000000..3aea17a --- /dev/null +++ b/godot/core/dictionaries.nim @@ -0,0 +1,110 @@ +# Copyright 2018 Xored Software, Inc. + +import hashes +import internal/godotinternaltypes, internal/godotdictionaries, + internal/godotvariants, internal/godotstrings + +type + Dictionary* = ref object + godotDictionary: GodotDictionary + +proc dictionaryFinalizer(dict: Dictionary) = + dict.godotDictionary.deinit() + +proc newDictionary*(): Dictionary {.inline.} = + new(result, dictionaryFinalizer) + initGodotDictionary(result.godotDictionary) + +proc newDictionary*(dict: GodotDictionary): Dictionary {.inline.} = + new(result, dictionaryFinalizer) + result.godotDictionary = dict + +proc godotDictionary*(dict: Dictionary): ptr GodotDictionary = + ## WARNING: do not keep the returned value for longer than the lifetime of + ## ``dict`` + addr dict.godotDictionary + +proc len*(self: Dictionary): int {.inline.} = + self.godotDictionary.len.int + +proc isEmpty*(self: Dictionary): bool {.inline.} = + self.godotDictionary.isEmpty() + +proc clear*(self: Dictionary) {.inline.} = + self.godotDictionary.clear() + +proc hash*(self: Dictionary): Hash {.inline.} = + hash(self.godotDictionary.godotHash()) + +import variants, arrays + +proc newVariant*(dict: Dictionary): Variant {.inline.} = + new(result, variantFinalizer) + initGodotVariant(result.godotVariant[], dict.godotDictionary) + +proc asDictionary*(self: Variant): Dictionary {.inline.} = + newDictionary(self.godotVariant[].asGodotDictionary()) + +proc contains*(self: Dictionary; key: Variant): bool {.inline.}= + self.godotDictionary.contains(key.godotVariant[]) + +proc contains*(self: Dictionary; keys: Array): bool {.inline.} = + self.godotDictionary.contains(keys.godotArray[]) + +proc del*(self: Dictionary; key: Variant) {.inline.} = + self.godotDictionary.del(key.godotVariant[]) + +proc keys*(self: Dictionary): Array {.inline.} = + newArray(self.godotDictionary.keys()) + +proc values*(self: Dictionary): Array {.inline.} = + newArray(self.godotDictionary.values()) + +proc `[]`*(self: Dictionary; key: Variant): Variant {.inline.} = + newVariant(self.godotDictionary[key.godotVariant[]]) + +proc `[]`*(self: Dictionary; keyStr: string): Variant {.inline.} = + var godotVariant: GodotVariant + var godotStr = keyStr.toGodotString() + initGodotVariant(godotVariant, godotStr) + result = newVariant(self.godotDictionary[godotVariant]) + godotStr.deinit() + godotVariant.deinit() + +proc `[]=`*(self: Dictionary; key, value: Variant) {.inline.} = + self.godotDictionary[key.godotVariant[]] = value.godotVariant[] + +proc `==`*(self, other: Dictionary): bool {.inline.} = + if self.isNil and other.isNil: return true + if self.isNil != other.isNil: return false + result = self.godotDictionary == other.godotDictionary + +proc toJson*(self: Dictionary): string {.inline.} = + var s = self.godotDictionary.toJson() + result = $s + s.deinit() + +iterator keys*(dict: Dictionary): Variant = + let keyArr = dict.keys() + for key in keyArr: + yield key + +iterator values*(dict: Dictionary): Variant = + let valArr = dict.values() + for val in valArr: + yield val + +iterator pairs*(dict: Dictionary): tuple[key, val: Variant] = + for key in keys(dict): + yield (key, dict[key]) + +proc `$`*(self: Dictionary): string = + result = newStringOfCap(32) + result.add('{') + for k, v in self: + if result.len > 1: + result.add(", ") + result.add($k) + result.add(": ") + result.add($v) + result.add('}') diff --git a/godot/core/dictionary.nim b/godot/core/dictionary.nim deleted file mode 100644 index 18c462f..0000000 --- a/godot/core/dictionary.nim +++ /dev/null @@ -1,96 +0,0 @@ -# Copyright (c) 2017 Xored Software, Inc. - -import hashes -import godotbase, arrays, variant, strings - -type - Dictionary* {.importc: "godot_dictionary", - header: "godot_dictionary.h", byref.} = object - -proc initVariant(dest: var Variant; dict: Dictionary) {. - importc: "godot_variant_new_dictionary", - header: "godot_variant.h".} - -proc variant*(dict: Dictionary): Variant {.inline.} = - initVariant(result, dict) - -proc asDictionary*(self: Variant): Dictionary {. - importc: "godot_variant_as_dictionary", header: "godot_variant.h".} - -proc initDictionary(dest: var Dictionary; - src: Dictionary) {. - importc: "godot_dictionary_new_copy", - header: "godot_dictionary.h".} - -proc deinit(self: var Dictionary) {. - importc: "godot_dictionary_destroy", header: "godot_dictionary.h".} - -proc `=`(self: var Dictionary, other: Dictionary) {.inline.} = - initDictionary(self, other) - -proc `=destroy`(self: Dictionary) {.inline.} = - unsafeAddr(self)[].deinit() - -proc initDictionary(dest: var Dictionary) {. - importc: "godot_dictionary_new", header: "godot_dictionary.h".} -proc initDictionary*(): Dictionary {.inline.} = - initDictionary(result) - -proc len*(self: Dictionary): cint {. - importc: "godot_dictionary_size", header: "godot_dictionary.h".} -proc isEmpty*(self: Dictionary): bool {. - importc: "godot_dictionary_empty", header: "godot_dictionary.h".} -proc clear*(self: var Dictionary) {. - importc: "godot_dictionary_clear", header: "godot_dictionary.h".} -proc contains*(self: Dictionary; key: Variant): bool {. - importc: "godot_dictionary_has", - header: "godot_dictionary.h".} -proc contains*(self: Dictionary; keys: Array): bool {. - importc: "godot_dictionary_has_all", - header: "godot_dictionary.h".} -proc del*(self: var Dictionary; key: Variant) {. - importc: "godot_dictionary_erase", header: "godot_dictionary.h".} - -proc godotHash*(self: Dictionary): cint {. - importc: "godot_dictionary_hash", header: "godot_dictionary.h".} -proc hash*(self: Dictionary): Hash {.inline.} = - hash(godotHash(self)) - -proc keys*(self: Dictionary): Array {. - importc: "godot_dictionary_keys", header: "godot_dictionary.h".} -proc values*(self: Dictionary): Array {. - importc: "godot_dictionary_values", header: "godot_dictionary.h".} -proc `[]`*(self: Dictionary; key: Variant): Variant {. - importc: "godot_dictionary_get", header: "godot_dictionary.h".} - -proc `[]`*(self: Dictionary; keyStr: string): Variant = - let key = variant(keyStr) - result = self[key] - -proc `[]=`*(self: var Dictionary; key, value: Variant) {. - importc: "godot_dictionary_set", - header: "godot_dictionary.h".} -proc mget*(self: var Dictionary; key: Variant): ptr Variant {. - importc: "godot_dictionary_operator_index", - header: "godot_dictionary.h".} - -proc `==`*(self, other: Dictionary): bool {. - importc: "godot_dictionary_operator_equal", - header: "godot_dictionary.h".} - -proc toJson*(self: Dictionary): GodotString {. - importc: "godot_dictionary_to_json", header: "godot_dictionary.h".} - -iterator keys*(dict: Dictionary): Variant = - let keyArr = dict.keys() - for key in keyArr: - yield key - -iterator values*(dict: Dictionary): Variant = - let valArr = dict.values() - for val in valArr: - yield val - -iterator pairs*(dict: Dictionary): tuple[key, val: Variant] = - for key in keys(dict): - yield (key, dict[key]) diff --git a/godot/core/godotbase.nim b/godot/core/godotbase.nim index 8af977e..7b5b804 100644 --- a/godot/core/godotbase.nim +++ b/godot/core/godotbase.nim @@ -1,107 +1,64 @@ -# Copyright (c) 2017 Xored Software, Inc. +# Copyright (c) 2018 Xored Software, Inc. -type - Error* {.importc: "godot_error", header: "../godot.h", - size: sizeof(cint), pure.} = enum - OK, - Failed, ## Generic fail error - Unavailable, ## What is requested is unsupported/unavailable - Unconfigured, ## The object being used hasnt been properly set up yet - Unauthorized, ## Missing credentials for requested resource - ParameterRangeError, ## Parameter given out of range (5) - OutOfMemory, ## Out of memory - FileNotFound, - FileBadDrive, - FileBadPath, - FileNoPermission, ## (10) - FileAlreadyInUse, - FileCantOpen, - FileCantWrite, - FileCantRead, - FileUnrecognized, ## (15) - FileCorrupt, - FileMissingDependencies, - FileEOF, - CantOpen, ## Can't open a resource/socket/file - CantCreate, ## (20) - QueryFailed, - AlreadyInUse, - Locked, ## resource is locked - Timeout, - CantConnect, ## (25) - CantResolve, - ConnectionError, - CantAquireResource, - CantFork, - InvalidData, ## Data passed is invalid (30) - InvalidParameter, ## Parameter passed is invalid - AlreadyExists, ## When adding, item already exists - DoesNotExist, ## When retrieving/erasing, it item does not exist - DatabaseCantRead, ## Database is full - DatabaseCantWrite, ## Database is full (35) - CompilationFailed, - MethodNotFound, - LinkFailed, - ScriptFailed, - CyclicLink, ## (40) - InvalidDeclaration, - DuplicateSymbol, - PauseError, - Busy, - Skip, ## (45) - Help, ## user requested help!! - Bug, - ## a bug in the software certainly happened, due to a double - ## check failing or unexpected behavior. - PrinterOnFire, ## the parallel port printer is engulfed in flames - WTF ## shit happens, has never been used, though +import math, godotinternal -const MAX_ARG_COUNT* = 128 +# math helpers -type - GodotObject* {.importc: "godot_object", header: "../godot.h".} = object - Array* {.importc: "godot_array", header: "godot_array.h", byref.} = object - Variant* {.importc: "godot_variant", - header: "godot_variant.h", byref.} = object +{.push stackTrace: off.} +const EPSILON = 0.00001'f32 +proc isEqualApprox*(a, b: float32): bool {.inline, noinit.} = + abs(a - b) < EPSILON -proc initArray(dest: var Array, src: Array) {. - importc: "godot_array_new_copy", - header: "godot_array.h".} +proc isEqualApprox*(a, b: float64): bool {.inline, noinit.} = + abs(a - b) < EPSILON -proc deinit(self: var Array) {.importc: "godot_array_destroy", - header: "godot_array.h".} +proc sign*(a: float32): float32 {.inline, noinit.} = + if a < 0: -1.0'f32 else: 1.0'f32 -proc `=`(self: var Array, other: Array) {.inline.} = - initArray(self, other) +proc sign*(a: float64): float64 {.inline, noinit.} = + if a < 0: -1.0'f64 else: 1.0'f64 -proc `=destroy`(self: Array) {.inline.} = - unsafeAddr(self).deinit() +proc stepify*(value, step: float64): float64 {.inline, noinit.} = + if step != 0'f64: + floor(value / step + 0.5'f64) * step + else: + value -proc initVariant(dest: var Variant; src: Variant) {. - importc: "godot_variant_new_copy", header: "godot_variant.h".} +proc stepify*(value, step: float32): float32 {.inline, noinit.} = + if step != 0'f32: + floor(value / step + 0.5'f32) * step + else: + value -proc deinit*(self: var Variant) {. - importc: "godot_variant_destroy", header: "godot_variant.h".} +when (NimMajor, NimMinor, NimPatch) < (0, 20, 4): + # Newer Nim has these procs in system module -proc `=`(self: var Variant, other: Variant) {.inline.} = - initVariant(self, other) + proc min*(x, y: float32): float32 {.inline, noinit.} = + if x <= y: x else: y -proc `=destroy`(self: Variant) {.inline.} = - unsafeAddr(self).deinit() + proc abs*(x: float32): float32 {.inline, noinit.} = + if x < 0.0: -x else: x -# System Functions + proc max*(x, y: float32): float32 {.inline, noinit.} = + if y <= x: x else: y -proc godotAlloc*(bytes: cint): pointer {. - importc: "godot_alloc", header: "../godot.h".} - ## Allocates the specified number of bytes. - ## Using this instead of stdlib proc will help Godot track how much memory - ## is in use in debug mode. -proc godotRealloc*(p: pointer; bytes: cint): pointer {. - importc: "godot_realloc", header: "../godot.h".} - ## Reallocates the pointer for the specified number of bytes. - ## Using this instead of stdlib proc will help Godot track how much memory - ## is in use in debug mode. -proc godotFree*(p: pointer) {.importc: "godot_free", header: "../godot.h".} - ## Frees the memory pointed to by the pointer. - ## Using this instead of stdlib proc will help Godot track how much memory - ## is in use in debug mode. +{.pop.} # stackTrace: off + +template printWarning*(warning: typed) = + ## Prints ``warning`` to Godot log, adding filename and line information. + let instInfo = instantiationInfo() + godotPrintWarning(cstring($warning), cstring"", cstring(instInfo.filename), instInfo.line.cint) + +template printError*(error: typed) = + ## Prints ``error`` to Godot log, adding filename and line information. + let instInfo = instantiationInfo() + godotPrintError(cstring($error), cstring"", cstring(instInfo.filename), instInfo.line.cint) + +proc print*(parts: varargs[string, `$`]) = + ## Prints concatenated ``parts`` to Godot log. + var combined = "" + for v in parts: + combined.add(v) + var s = combined.toGodotString() + godotPrint(s) + s.deinit() diff --git a/godot/core/godotcore.nim b/godot/core/godotcore.nim deleted file mode 100644 index daffeaf..0000000 --- a/godot/core/godotcore.nim +++ /dev/null @@ -1,288 +0,0 @@ -# Copyright (c) 2017 Xored Software, Inc. - -import godotbase -import strings, vector2, rect2, vector3, transform2d, plane, quat -import rect3, basis, transform, color, nodepath, rid -import dictionary, arrays, poolarray, variant - -export godotbase, strings, vector2, rect2, vector3, transform2d, plane, quat, - rect3, basis, transform, color, nodepath, rid, dictionary, arrays, - poolarray, variant - -# MethodBind API - -type - GodotMethodBind* {.importc: "godot_method_bind", - header: "../godot.h".} = object - -proc getMethod*(className: cstring; methodName: cstring): ptr GodotMethodBind {. - importc: "godot_method_bind_get_method", header: "../godot.h".} -proc ptrCall*(methodBind: ptr GodotMethodBind; - instance: ptr GodotObject; - args: ptr array[MAX_ARG_COUNT, pointer]; - ret: pointer) {. - importc: "godot_method_bind_ptrcall", header: "../godot.h".} -proc call*(methodBind: ptr GodotMethodBind; - instance: ptr GodotObject; - args: ptr array[MAX_ARG_COUNT, Variant]; argCount: cint; - callError: var VariantCallError): Variant {. - importc: "godot_method_bind_call", header: "../godot.h".} - -# Script API - -type - GodotNativeInitOptions* {.importc: "godot_native_init_options", - header: "../godot.h".} = object - inEditor* {.importc: "in_editor".}: bool - coreApiHash* {.importc: "core_api_hash".}: uint64 - editorApiHash* {.importc: "editor_api_hash".}: uint64 - noApiHash* {.importc: "no_api_hash".}: uint64 - - GodotNativeTerminateOptions* {.importc: "godot_native_terminate_options", - header: "../godot.h".} = object - inEditor* {.importc: "in_editor".}: bool - - GodotMethodRPCMode* {.importc: "godot_method_rpc_mode", header: "../godot.h", - size: sizeof(cint), pure.} = enum - Disabled, - Remote, - Sync, - Master, - Slave - - GodotMethodAttributes* {.importc: "godot_method_attributes", - header: "../godot.h".} = object - rpcMode* {.importc: "rpc_type".}: GodotMethodRPCMode - - GodotPropertyHint* {.importc: "godot_property_hint", header: "../godot.h", - size: sizeof(cint), pure.} = enum - None, ## no hint provided. - Range, ## hint_text = "min,max,step,slider; // slider is optional" - ExpRange, ## hint_text = "min,max,step", exponential edit - Enum, ## hint_text= "val1,val2,val3,etc" - ExpEasing, ## exponential easing funciton (Math::ease) - Length, ## hint_text= "length" (as integer) - SpriteFrame, - KeyAccel, ## hint_text= "length" (as integer) - Flags, ## hint_text= "flag1,flag2,etc" (as bit flags) - Layers2DRender, - Layers2DPhysics, - Layers3DRender, - Layers3DPhysics, - File, ## a file path must be passed, hint_text (optionally) - ## is a filter "*.png,*.wav,*.doc," - Dir, ## a directort path must be passed - GlobalFile, ## a file path must be passed, hint_text (optionally) is a - ## filter "*.png,*.wav,*.doc," - GlobalDir, ## a directort path must be passed - ResourceType, ## a resource object type - MultilineText, ## used for string properties that can contain multiple lines - ColorNoAlpha, ## used for ignoring alpha component when editing a color - ImageCompressLossy, - ImageCompressLossless, - ObjectId, - TypeString, ## a type string, the hint is the base type to choose - NodePathToEditedNode, ## so something else can provide this - ## (used in scripts) - MethodOfVariantType, ## a method of a type - MethodOfBaseType, ## a method of a base type - MethodOfInstance, ## a method of an instance - MethodOfScript, ## a method of a script & base - PropertyOfVariantType, ## a property of a type - PropertyOfBaseType, ## a property of a base type - PropertyOfInstance, ## a property of an instance - PropertyOfScript, ## a property of a script & base - PropertyHintMax - -const - GODOT_PROPERTY_USAGE_STORAGE_VALUE = 1.cint - GODOT_PROPERTY_USAGE_EDITOR_VALUE = 2.cint - GODOT_PROPERTY_USAGE_NETWORK_VALUE = 4.cint - GODOT_PROPERTY_USAGE_EDITOR_HELPER_VALUE = 8.cint - GODOT_PROPERTY_USAGE_CHECKABLE_VALUE = 16.cint - GODOT_PROPERTY_USAGE_CHECKED_VALUE = 32.cint - GODOT_PROPERTY_USAGE_INTERNATIONALIZED_VALUE = 64.cint - GODOT_PROPERTY_USAGE_GROUP_VALUE = 128.cint - GODOT_PROPERTY_USAGE_CATEGORY_VALUE = 256.cint - GODOT_PROPERTY_USAGE_STORE_IF_NONZERO_VALUE = 512.cint - GODOT_PROPERTY_USAGE_STORE_IF_NONONE_VALUE = 1024.cint - GODOT_PROPERTY_USAGE_NO_INSTANCE_STATE_VALUE = 2048.cint - GODOT_PROPERTY_USAGE_RESTART_IF_CHANGED_VALUE = 4096.cint - GODOT_PROPERTY_USAGE_SCRIPT_VARIABLE_VALUE = 8192.cint - GODOT_PROPERTY_USAGE_STORE_IF_NULL_VALUE = 16384.cint - GODOT_PROPERTY_USAGE_ANIMATE_AS_TRIGGER_VALUE = 32768.cint - GODOT_PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED_VALUE = 65536.cint - - GODOT_PROPERTY_USAGE_DEFAULT_VALUE: cint = - GODOT_PROPERTY_USAGE_STORAGE_VALUE or GODOT_PROPERTY_USAGE_EDITOR_VALUE or - GODOT_PROPERTY_USAGE_NETWORK_VALUE - GODOT_PROPERTY_USAGE_DEFAULT_INTL_VALUE: cint = - GODOT_PROPERTY_USAGE_STORAGE_VALUE or - GODOT_PROPERTY_USAGE_EDITOR_VALUE or GODOT_PROPERTY_USAGE_NETWORK_VALUE or - GODOT_PROPERTY_USAGE_INTERNATIONALIZED_VALUE - GODOT_PROPERTY_USAGE_NOEDITOR_VALUE: cint = - GODOT_PROPERTY_USAGE_STORAGE_VALUE or GODOT_PROPERTY_USAGE_NETWORK_VALUE - -type - GodotPropertyUsageFlags* {.importc: "godot_property_usage_flags", - header: "../godot.h", size: sizeof(cint), - pure.} = enum - Storage = GODOT_PROPERTY_USAGE_STORAGE_VALUE - Editor = GODOT_PROPERTY_USAGE_EDITOR_VALUE - Network = GODOT_PROPERTY_USAGE_NETWORK_VALUE - NoEditor = GODOT_PROPERTY_USAGE_NOEDITOR_VALUE - Default = GODOT_PROPERTY_USAGE_DEFAULT_VALUE - EditorHelper = GODOT_PROPERTY_USAGE_EDITOR_HELPER_VALUE - Checkable = GODOT_PROPERTY_USAGE_CHECKABLE_VALUE - ## used for editing global variables - Checked = GODOT_PROPERTY_USAGE_CHECKED_VALUE - ## used for editing global variables - Internationalized = GODOT_PROPERTY_USAGE_INTERNATIONALIZED_VALUE - ## hint for internationalized strings - DefaultIntl = GODOT_PROPERTY_USAGE_DEFAULT_INTL_VALUE - Group = GODOT_PROPERTY_USAGE_GROUP_VALUE - ## used for grouping props in the editor - Category = GODOT_PROPERTY_USAGE_CATEGORY_VALUE - NonZero = GODOT_PROPERTY_USAGE_STORE_IF_NONZERO_VALUE - ## only store if nonzero - NonOne = GODOT_PROPERTY_USAGE_STORE_IF_NONONE_VALUE - ## only store if false - NoInstanceState = GODOT_PROPERTY_USAGE_NO_INSTANCE_STATE_VALUE - RestartIfChanged = GODOT_PROPERTY_USAGE_RESTART_IF_CHANGED_VALUE - ScriptVariable = GODOT_PROPERTY_USAGE_SCRIPT_VARIABLE_VALUE - StoreIfNull = GODOT_PROPERTY_USAGE_STORE_IF_NULL_VALUE - AnimateAsTrigger = GODOT_PROPERTY_USAGE_ANIMATE_AS_TRIGGER_VALUE - UpdateAllIfModified = GODOT_PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED_VALUE - - GodotPropertyAttributes* {.importc: "godot_property_attributes", - header: "../godot.h", bycopy.} = object - rsetType* {.importc: "rset_type".}: GodotMethodRPCMode - typ* {.importc: "type".}: cint - hint* {.importc: "hint".}: GodotPropertyHint - hintString* {.importc: "hint_string".}: GodotString - usage* {.importc: "usage".}: GodotPropertyUsageFlags - defaultValue* {.importc: "default_value".}: Variant - - GodotInstanceCreateFunc* {.importc: "godot_instance_create_func", - header: "../godot.h", bycopy.} = object - createFunc* {.importc: "create_func".}: - proc (obj: ptr GodotObject; methodData: pointer): pointer {.noconv.} - ## returns user data - methodData* {.importc: "method_data".}: pointer - freeFunc* {.importc: "free_func".}: proc (a2: pointer) {.noconv.} - - GodotInstanceDestroyFunc* {.importc: "godot_instance_destroy_func", - header: "../godot.h", bycopy.} = object - destroyFunc* {.importc: "destroy_func".}: - proc (obj: ptr GodotObject; methodData: pointer; - userData: pointer) {.noconv.} - methodData* {.importc: "method_data".}: pointer - freeFunc* {.importc: "free_func".}: proc (a2: pointer) {.noconv.} - -proc godotScriptRegisterClass*(name, base: cstring; - create_func: GodotInstanceCreateFunc; - destroy_func: GodotInstanceDestroyFunc) {. - importc: "godot_script_register_class", header: "../godot.h".} -proc godotScriptRegisterToolClass*(name, base: cstring; - createFunc: GodotInstanceCreateFunc; - destroyFunc: GodotInstanceDestroyFunc) {. - importc: "godot_script_register_tool_class", header: "../godot.h".} -type - GodotInstanceMethod* {.importc: "godot_instance_method", - header: "../godot.h", bycopy.} = object - meth* {.importc: "method".}: - proc (obj: ptr GodotObject; methodData: pointer; - userData: pointer; numArgs: cint; - args: var ptr array[MAX_ARG_COUNT, Variant]): Variant {.noconv.} - methodData* {.importc: "method_data".}: pointer - freeFunc* {.importc: "free_func".}: proc (a2: pointer) {.noconv.} - -proc godotScriptRegisterMethod*(name: cstring; function_name: cstring; - attr: GodotMethodAttributes; - meth: GodotInstanceMethod) {. - importc: "godot_script_register_method", header: "../godot.h".} -type - GodotPropertySetFunc* {.importc: "godot_property_set_func", - header: "../godot.h", bycopy.} = object - setFunc* {.importc: "set_func".}: proc (obj: ptr GodotObject; - methodData: pointer; - userData: pointer; - value: Variant) {.noconv.} - methodData* {.importc: "method_data".}: pointer - freeFunc* {.importc: "free_func".}: proc (a2: pointer) {.noconv.} - - GodotPropertyGetFunc* {.importc: "godot_property_get_func", - header: "../godot.h", bycopy.} = object - getFunc* {.importc: "get_func".}: - proc (obj: ptr GodotObject; methodData: pointer; - userData: pointer): Variant {.noconv.} - methodData* {.importc: "method_data".}: pointer - freeFunc* {.importc: "free_func".}: proc (a2: pointer) {.noconv.} - -proc godotScriptRegisterProperty*(name: cstring; path: cstring; - attr: var GodotPropertyAttributes; - setFunc: GodotPropertySetFunc; - getFunc: GodotPropertyGetFunc) {. - importc: "godot_script_register_property", header: "../godot.h".} - -type - GodotSignalArgument* {.importc: "godot_signal_argument", - header: "../godot.h", bycopy.} = object - name* {.importc: "name".}: GodotString - typ* {.importc: "type".}: cint - hint* {.importc: "hint".}: GodotPropertyHint - hintString* {.importc: "hint_string".}: GodotString - usage* {.importc: "usage".}: GodotPropertyUsageFlags - defaultValue* {.importc: "default_value".}: Variant - - GodotSignal* {.importc: "godot_signal", header: "../godot.h".} = object - name* {.importc: "name".}: GodotString - numArgs* {.importc: "num_args".}: cint - args* {.importc: "args".}: ptr GodotSignalArgument - numDefaultArgs* {.importc: "num_default_args".}: cint - defaultArgs* {.importc: "default_args".}: ptr Variant - -proc godotScriptRegisterSignal*(name: cstring; signal: GodotSignal) {. - importc: "godot_script_register_signal", header: "../godot.h".} -proc getUserdata*(instance: ptr GodotObject): pointer {. - importc: "godot_native_get_userdata", header: "../godot.h".} - -type - GodotClassConstructor* = proc (): ptr GodotObject {.gcsafe, noconv.} - -proc getClassConstructor*(className: cstring): GodotClassConstructor {. - importc: "godot_get_class_constructor", header: "../godot.h".} -proc getGlobalConstants*(): Dictionary {. - importc: "godot_get_global_constants", header: "../godot.h".} -proc godotNew*(p_classname: cstring): ptr GodotObject {. - importc: "godot_new", header: "../godot.h".} -proc godotStackBottom*(): pointer {. - importc: "godot_get_stack_bottom", header: "../godot.h".} - -proc deinit*(o: ptr GodotObject) {. - importc: "godot_object_destroy", header: "../godot.h".} - -# print using Godot's error handler list - -proc godotPrintError(description: cstring; function: cstring; file: cstring; - line: cint) {. - importc: "godot_print_error", header: "../godot.h".} - -proc godotPrintWarning(description: cstring; function: cstring; - file: cstring; line: cint) {. - importc: "godot_print_warning", header: "../godot.h".} - -proc godotPrint(message: GodotString) {. - importc: "godot_print", header: "../godot.h".} - -proc print*(message: string) {.inline.} = - let s = message.toGodotString() - godotPrint(s) - -template printWarning*(warn: typed) = - let (filename, line) = instantiationInfo() - godotPrintWarning(cstring($warn), nil, cstring(filename), line.cint) - -template printError*(err: typed) = - let (filename, line) = instantiationInfo() - godotPrintError(cstring($err), nil, cstring(filename), line.cint) diff --git a/godot/core/godotcoretypes.nim b/godot/core/godotcoretypes.nim new file mode 100644 index 0000000..c4c4b71 --- /dev/null +++ b/godot/core/godotcoretypes.nim @@ -0,0 +1,102 @@ +# Copyright 2018 Xored Software, Inc. + +type + Color* {.byref.} = object + r*: float32 + g*: float32 + b*: float32 + a*: float32 + + Vector3* {.byref.} = object + x*: float32 + y*: float32 + z*: float32 + + Vector2* {.byref.} = object + x*: float32 + y*: float32 + + Plane* {.byref.} = object + normal*: Vector3 + d*: float32 + + Basis* {.byref.} = object + elements*: array[3, Vector3] + + Quat* {.byref.} = object + x*: float32 + y*: float32 + z*: float32 + w*: float32 + + AABB* {.byref.} = object + position*: Vector3 + size*: Vector3 + + Rect2* {.byref.} = object + position*: Vector2 + size*: Vector2 + + Transform2D* {.byref.} = object + elements*: array[3, Vector2] + + Transform* {.byref.} = object + basis*: Basis + origin*: Vector3 + + RID* {.byref.} = object + data: array[sizeof(int), byte] + + Error* {.size: sizeof(cint), pure.} = enum + OK, + Failed, ## Generic fail error + Unavailable, ## What is requested is unsupported/unavailable + Unconfigured, ## The object being used hasnt been properly set up yet + Unauthorized, ## Missing credentials for requested resource + ParameterRangeError, ## Parameter given out of range (5) + OutOfMemory, ## Out of memory + FileNotFound, + FileBadDrive, + FileBadPath, + FileNoPermission, ## (10) + FileAlreadyInUse, + FileCantOpen, + FileCantWrite, + FileCantRead, + FileUnrecognized, ## (15) + FileCorrupt, + FileMissingDependencies, + FileEOF, + CantOpen, ## Can't open a resource/socket/file + CantCreate, ## (20) + QueryFailed, + AlreadyInUse, + Locked, ## resource is locked + Timeout, + CantConnect, ## (25) + CantResolve, + ConnectionError, + CantAquireResource, + CantFork, + InvalidData, ## Data passed is invalid (30) + InvalidParameter, ## Parameter passed is invalid + AlreadyExists, ## When adding, item already exists + DoesNotExist, ## When retrieving/erasing, it item does not exist + DatabaseCantRead, ## Database is full + DatabaseCantWrite, ## Database is full (35) + CompilationFailed, + MethodNotFound, + LinkFailed, + ScriptFailed, + CyclicLink, ## (40) + InvalidDeclaration, + DuplicateSymbol, + PauseError, + Busy, + Skip, ## (45) + Help, ## user requested help!! + Bug, + ## a bug in the software certainly happened, due to a double + ## check failing or unexpected behavior. + PrinterOnFire, ## the parallel port printer is engulfed in flames + WTF ## shit happens, has never been used, though diff --git a/godot/core/nim.cfg b/godot/core/nim.cfg new file mode 100644 index 0000000..f1fb6a7 --- /dev/null +++ b/godot/core/nim.cfg @@ -0,0 +1 @@ +--path:"$projectdir/../" \ No newline at end of file diff --git a/godot/core/nodepath.nim b/godot/core/nodepath.nim deleted file mode 100644 index 0dbd307..0000000 --- a/godot/core/nodepath.nim +++ /dev/null @@ -1,55 +0,0 @@ -# Copyright (c) 2017 Xored Software, Inc. - -import godotbase, strings - -type - NodePath* {.importc: "godot_node_path", - header: "godot_node_path.h", byref.} = object - -proc initNodePath(dest: var NodePath; s: GodotString) {. - importc: "godot_node_path_new", header: "godot_node_path.h".} -proc initNodePath(dest: var NodePath; - src: NodePath) {. - importc: "godot_node_path_new_copy", header: "godot_node_path.h".} -proc deinit(self: var NodePath) {. - importc: "godot_node_path_destroy", header: "godot_node_path.h".} - -proc initNodePath*(s: string): NodePath {.inline.} = - initNodePath(result, s.toGodotString()) - -proc `=destroy`(self: NodePath) {.inline.} = - unsafeAddr(self).deinit() - -proc `=`(self: var NodePath, other: NodePath) {.inline.} = - initNodePath(self, other) - -proc toGodotString*(self: NodePath): GodotString {. - importc: "godot_node_path_as_string", header: "godot_node_path.h".} -proc `$`*(self: NodePath): string {.inline.} = - let s = self.toGodotString() - result = $s - -proc isAbsolute*(self: NodePath): bool {. - importc: "godot_node_path_is_absolute", header: "godot_node_path.h".} -proc nameCount*(self: NodePath): cint {. - importc: "godot_node_path_get_name_count", - header: "godot_node_path.h".} -proc getName*(self: NodePath; idx: cint): GodotString {. - importc: "godot_node_path_get_name", header: "godot_node_path.h".} -proc subnameCount*(self: NodePath): cint {. - importc: "godot_node_path_get_subname_count", - header: "godot_node_path.h".} -proc getSubname*(self: NodePath; idx: cint): GodotString {. - importc: "godot_node_path_get_subname", - header: "godot_node_path.h".} -proc property*(self: NodePath): GodotString {. - importc: "godot_node_path_get_property", header: "godot_node_path.h".} -proc isEmpty*(self: NodePath): bool {. - importc: "godot_node_path_is_empty", header: "godot_node_path.h".} - -proc `==`*(a, b: NodePath): bool {. - importc: "godot_node_path_operator_equal", - header: "godot_node_path.h".} - -converter fromString*(s: string): NodePath = - initNodePath(result, s.toGodotString()) diff --git a/godot/core/nodepaths.nim b/godot/core/nodepaths.nim new file mode 100644 index 0000000..bf690d7 --- /dev/null +++ b/godot/core/nodepaths.nim @@ -0,0 +1,73 @@ +# Copyright 2018 Xored Software, Inc. + +import hashes + +import internal/godotinternaltypes, internal/godotnodepaths, + internal/godotstrings + +type + NodePath* = ref object + path: GodotNodePath + +proc nodePathFinalizer(path: NodePath) = + path.path.deinit() + +proc newNodePath*(path: GodotNodePath): NodePath = + ## Moves the GodotNodePath into Nim wrapper. The ``path`` will be destroyed + ## automatically when the result is no longer referenced. + new(result, nodePathFinalizer) + result.path = path + +proc newNodePath*(s: string): NodePath = + new(result, nodePathFinalizer) + var str = s.toGodotString() + initGodotNodePath(result.path, str) + str.deinit() + +proc godotNodePath*(path: NodePath): ptr GodotNodePath {.inline.} = + ## WARNING: do not keep the returned value for longer than the lifetime of + ## ``path`` + result = addr path.path + +proc `$`*(self: NodePath): string {.inline.} = + var s = self.path.toGodotString() + result = $s + s.deinit() + +proc hash*(self: NodePath): Hash {.inline.} = + ($self).hash() + +proc isAbsolute*(self: NodePath): bool {.inline.} = + self.path.isAbsolute() + +proc nameCount*(self: NodePath): int {.inline.} = + int(self.path.nameCount()) + +proc getName*(self: NodePath; idx: int): string {.inline.} = + var s = self.path.getName(idx.cint) + result = $s + s.deinit() + +proc subnameCount*(self: NodePath): int {.inline.} = + int(self.path.subnameCount()) + +proc getSubname*(self: NodePath; idx: int): string {.inline.} = + var s = self.path.getSubname(idx.cint) + result = $s + s.deinit() + +proc getConcatenatedSubnames*(self: NodePath): string {.inline.} = + var s = self.path.getConcatenatedSubnames() + result = $s + s.deinit() + +proc isEmpty*(self: NodePath): bool {.inline.} = + self.path.isEmpty() + +proc `==`*(a, b: NodePath): bool = + if a.isNil and b.isNil: return true + if a.isNil != b.isNil: return false + result = a.path == b.path + +converter fromString*(s: string): NodePath = + newNodePath(s) diff --git a/godot/core/plane.nim b/godot/core/plane.nim deleted file mode 100644 index 91f6389..0000000 --- a/godot/core/plane.nim +++ /dev/null @@ -1,84 +0,0 @@ -# Copyright (c) 2017 Xored Software, Inc. - -import godotbase, vector3, strings - -type - Plane* {.importc: "godot_plane", header: "godot_plane.h", byref.} = object - -proc initPlane(dest: var Plane; a, b, c, d: float32) {. - importc: "godot_plane_new_with_reals", header: "godot_plane.h".} -proc initPlane(dest: var Plane; v1, v2, v3: Vector3) {. - importc: "godot_plane_new_with_vectors", - header: "godot_plane.h".} -proc initPlane(dest: var Plane; normal: Vector3; d: float32) {. - importc: "godot_plane_new_with_normal", - header: "godot_plane.h".} - -proc initPlane*(a, b, c, d: float32): Plane = - initPlane(result, a, b, c, d) - -proc initPlane*(v1, v2, v3: Vector3): Plane = - initPlane(result, v1, v2, v3) - -proc initPlane*(normal: Vector3; d: float32): Plane = - initPlane(result, normal, d) - -proc toGodotString*(self: Plane): GodotString {. - noSideEffect, - importc: "godot_plane_as_string", header: "godot_plane.h".} -proc `$`*(self: Plane): string {.inline.} = - $self.toGodotString() - -proc normalized*(self: Plane): Plane {. - noSideEffect, - importc: "godot_plane_normalized", header: "godot_plane.h".} -proc center*(self: Plane): Vector3 {. - noSideEffect, - importc: "godot_plane_center", header: "godot_plane.h".} -proc getAnyPoint*(self: Plane): Vector3 {. - noSideEffect, - importc: "godot_plane_get_any_point", header: "godot_plane.h".} -proc isPointOver*(self: Plane; point: Vector3): bool {. - noSideEffect, - importc: "godot_plane_is_point_over", - header: "godot_plane.h".} -proc distanceTo*(self: Plane; point: Vector3): float32 {. - noSideEffect, - importc: "godot_plane_distance_to", header: "godot_plane.h".} -proc contains*(self: Plane; point: Vector3; - epsilon: float32): bool {. - noSideEffect, - importc: "godot_plane_has_point", header: "godot_plane.h".} -proc project*(self: Plane; point: Vector3): Vector3 {. - noSideEffect, - importc: "godot_plane_project", header: "godot_plane.h".} -proc intersect3*(self: Plane; dest: var Vector3; - b, c: Plane): bool {. - noSideEffect, - importc: "godot_plane_intersect_3", - header: "godot_plane.h".} -proc intersectsRay*(self: Plane; dest: var Vector3; - v, dir: Vector3): bool {. - noSideEffect, - importc: "godot_plane_intersects_ray", - header: "godot_plane.h".} -proc intersectsSegment*(self: Plane; dest: var Vector3; - segmentBegin, segmentEnd: Vector3): bool {. - noSideEffect, importc: "godot_plane_intersects_segment", - header: "godot_plane.h".} -proc `-`*(self: Plane): Plane {. - noSideEffect, - importc: "godot_plane_operator_neg", header: "godot_plane.h".} -proc `==`*(a, b: Plane): bool {. - noSideEffect, - importc: "godot_plane_operator_equal", header: "godot_plane.h".} -proc normal*(self: Plane): Vector3 {. - noSideEffect, - importc: "godot_plane_get_normal", header: "godot_plane.h".} -proc `normal=`*(self: var Plane; normal: Vector3) {. - importc: "godot_plane_set_normal", header: "godot_plane.h".} -proc d*(self: Plane): float32 {. - noSideEffect, - importc: "godot_plane_get_d", header: "godot_plane.h".} -proc `d=`*(self: var Plane; d: float32) {. - importc: "godot_plane_set_d", header: "godot_plane.h".} \ No newline at end of file diff --git a/godot/core/planes.nim b/godot/core/planes.nim new file mode 100644 index 0000000..2d15c79 --- /dev/null +++ b/godot/core/planes.nim @@ -0,0 +1,66 @@ +# Copyright (c) 2018 Xored Software, Inc. + +import hashes + +import vector3 + +import internal/godotinternaltypes, internal/godotstrings +import godotcoretypes, gdnativeapi + +proc initPlane*(a, b, c, d: float32): Plane {.inline.} = + getGDNativeAPI().planeNewWithReals(result, a, b, c, d) + +proc initPlane*(v1, v2, v3: Vector3): Plane {.inline.} = + getGDNativeAPI().planeNewWithVectors(result, v1, v2, v3) + +proc initPlane*(normal: Vector3; d: float32): Plane {.inline.} = + result = Plane( + normal: normal, + d: d + ) + +proc `$`*(self: Plane): string {.inline.} = + $getGDNativeAPI().planeAsString(self) + +proc hash*(self: Plane): Hash {.inline, noinit.} = + !$(self.normal.hash() !& self.d.hash()) + +proc normalized*(self: Plane): Plane {.inline.} = + getGDNativeAPI().planeNormalized(self).toPlane() + +proc center*(self: Plane): Vector3 {.inline.} = + getGDNativeAPI().planeCenter(self).toVector3() + +proc getAnyPoint*(self: Plane): Vector3 {.inline.} = + getGDNativeAPI().planeGetAnyPoint(self).toVector3() + +proc isPointOver*(self: Plane; point: Vector3): bool {.inline.} = + getGDNativeAPI().planeIsPointOver(self, point) + +proc distanceTo*(self: Plane; point: Vector3): float32 {.inline.} = + getGDNativeAPI().planeDistanceTo(self, point) + +proc contains*(self: Plane; point: Vector3; + epsilon: float32): bool {.inline.} = + getGDNativeAPI().planeHasPoint(self, point, epsilon) + +proc project*(self: Plane; point: Vector3): Vector3 {.inline.} = + getGDNativeAPI().planeProject(self, point).toVector3() + +proc intersect3*(self: Plane; dest: var Vector3; + b, c: Plane): bool {.inline.} = + getGDNativeAPI().planeIntersect3(self, dest, b, c) + +proc intersectsRay*(self: Plane; dest: var Vector3; + v, dir: Vector3): bool {.inline.} = + getGDNativeAPI().planeIntersectsRay(self, dest, v, dir) + +proc intersectsSegment*(self: Plane; dest: var Vector3; + segmentBegin, segmentEnd: Vector3): bool {.inline.} = + getGDNativeAPI().planeIntersectsSegment(self, dest, segmentBegin, segmentEnd) + +proc `-`*(self: Plane): Plane {.inline.} = + getGDNativeAPI().planeOperatorNeg(self).toPlane() + +proc `==`*(a, b: Plane): bool {.inline.} = + getGDNativeAPI().planeOperatorEqual(a, b) diff --git a/godot/core/poolarray.nim b/godot/core/poolarray.nim deleted file mode 100644 index 2fda61b..0000000 --- a/godot/core/poolarray.nim +++ /dev/null @@ -1,476 +0,0 @@ -# Copyright (c) 2017 Xored Software, Inc. - -import godotbase, color, vector2, vector3, strings - -type - PoolByteArray* {.importc: "godot_pool_byte_array", - header: "godot_pool_arrays.h", byref.} = object - PoolIntArray* {.importc: "godot_pool_int_array", - header: "godot_pool_arrays.h", byref.} = object - PoolRealArray* {.importc: "godot_pool_real_array", - header: "godot_pool_arrays.h", byref.} = object - PoolStringArray* {.importc: "godot_pool_string_array", - header: "godot_pool_arrays.h", byref.} = object - PoolVector2Array* {.importc: "godot_pool_vector2_array", - header: "godot_pool_arrays.h", byref.} = object - PoolVector3Array* {.importc: "godot_pool_vector3_array", - header: "godot_pool_arrays.h", byref.} = object - PoolColorArray* {.importc: "godot_pool_color_array", - header: "godot_pool_arrays.h", byref.} = object - -# byte - -proc initPoolByteArray(dest: var PoolByteArray) {. - importc: "godot_pool_byte_array_new", header: "godot_pool_arrays.h".} -proc initPoolByteArray(dest: var PoolByteArray; - src: PoolByteArray) {. - importc: "godot_pool_byte_array_new_copy", - header: "godot_pool_arrays.h".} -proc initPoolByteArray(dest: var PoolByteArray; arr: Array) {. - importc: "godot_pool_byte_array_new_with_array", - header: "godot_pool_arrays.h".} - -proc deinit(self: var PoolByteArray) {. - importc: "godot_pool_byte_array_destroy", header: "godot_pool_arrays.h".} - -proc initPoolByteArray*(): PoolByteArray {.inline.} = - initPoolByteArray(result) - -proc initPoolByteArray*(arr: Array): PoolByteArray {.inline.} = - initPoolByteArray(result, arr) - -proc `=`(self: var PoolByteArray, other: PoolByteArray) {.inline.} = - initPoolByteArray(self, other) - -proc `=destroy`(self: PoolByteArray) {.inline.} = - unsafeAddr(self).deinit() - -proc add*(self: var PoolByteArray; - data: uint8) {. - importc: "godot_pool_byte_array_append", header: "godot_pool_arrays.h".} -proc addFirst*(self: var PoolByteArray, data: uint8) {. - importc: "godot_pool_byte_array_push_back", header: "godot_pool_arrays.h".} -proc add*(self: var PoolByteArray; - arr: PoolByteArray) {. - importc: "godot_pool_byte_array_append_array", - header: "godot_pool_arrays.h".} -proc insert*(self: var PoolByteArray; idx: cint; - data: uint8): Error {. - importc: "godot_pool_byte_array_insert", header: "godot_pool_arrays.h".} -proc delete*(self: var PoolByteArray; idx: cint) {. - importc: "godot_pool_byte_array_remove", header: "godot_pool_arrays.h".} - -proc reverse*(self: var PoolByteArray) {. - importc: "godot_pool_byte_array_invert", header: "godot_pool_arrays.h".} -proc setLen*(self: var PoolByteArray; size: cint) {. - importc: "godot_pool_byte_array_resize", header: "godot_pool_arrays.h".} - -proc `[]=`*(self: var PoolByteArray; idx: cint; data: uint8) {. - importc: "godot_pool_byte_array_set", header: "godot_pool_arrays.h".} -proc `[]`*(self: PoolByteArray; idx: cint): uint8 {. - noSideEffect, - importc: "godot_pool_byte_array_get", - header: "godot_pool_arrays.h".} -proc len*(self: PoolByteArray): cint {. - noSideEffect, - importc: "godot_pool_byte_array_size", header: "godot_pool_arrays.h".} - -iterator items*(arr: PoolByteArray): byte = - for i in 0..= low(cint) and idxFrom <= high(cint) and + idxTo >= low(cint) and idxTo <= high(cint)) + newProcName(self.fieldName.subarray(idxFrom.cint, idxTo.cint)) + + when not noData: + proc add*(self: T; data: DataT) {.inline.} = + self.fieldName.add(data) + + proc insert*(self: T; idx: int; data: DataT): Error {.inline.} = + self.fieldName.insert(idx.cint, data) + + proc `[]=`*(self: T; idx: int; data: DataT) {.inline.} = + self.fieldName[idx.cint] = data + + proc `[]`*(self: T; idx: int): DataT {.inline.} = + self.fieldName[idx.cint] + + iterator items*(arr: T): DataT = + for item in arr.fieldName.items: + yield item + + iterator pairs*(arr: T): tuple[key: int, val: DataT] = + for pair in arr.fieldName.pairs: + yield (pair[0].int, pair[1]) + + iterator mitems*(arr: T): var DataT = + for item in arr.fieldName.mitems: + yield item + + iterator mpairs*(arr: T): tuple[key: int, val: var DataT] = + for pair in arr.fieldName.mpairs: + yield (pair[0].int, pair[1]) + +definePoolArray(PoolByteArray, GodotPoolByteArray, uint8, + godotPoolByteArray, newPoolByteArray, + initGodotPoolByteArray) +definePoolArray(PoolIntArray, GodotPoolIntArray, cint, + godotPoolIntArray, newPoolIntArray, + initGodotPoolIntArray) +definePoolArray(PoolRealArray, GodotPoolRealArray, float32, + godotPoolRealArray, newPoolRealArray, + initGodotPoolRealArray) +definePoolArray(PoolVector2Array, GodotPoolVector2Array, Vector2, + godotPoolVector2Array, newPoolVector2Array, + initGodotPoolVector2Array) +definePoolArray(PoolVector3Array, GodotPoolVector3Array, Vector3, + godotPoolVector3Array, newPoolVector3Array, + initGodotPoolVector3Array) +definePoolArray(PoolColorArray, GodotPoolColorArray, Color, + godotPoolColorArray, newPoolColorArray, + initGodotPoolColorArray) +definePoolArray(PoolStringArray, GodotPoolStringArray, string, + godotPoolStringArray, newPoolStringArray, + initGodotPoolStringArray, true) + +proc add*(self: PoolStringArray; data: string) = + var s = data.toGodotString() + self.godotPoolStringArray.add(s) + s.deinit() + +proc insert*(self: PoolStringArray; idx: int; data: string): Error = + var s = data.toGodotString() + result = self.godotPoolStringArray.insert(idx.cint, s) + s.deinit() + +proc `[]=`*(self: PoolStringArray; idx: int; data: string) = + var s = data.toGodotString() + self.godotPoolStringArray[idx.cint] = s + s.deinit() + +proc `[]`*(self: PoolStringArray; idx: int): string = + var s = self.godotPoolStringArray[idx.cint] + result = $s + s.deinit() + +iterator items*(arr: PoolStringArray): string = + for i in 0..= (b.position.x + b.size.x): + return false + if a.position.x + a.size.x <= b.position.x: + return false + if a.position.y >= (b.position.y + b.size.y): + return false + if a.position.y + a.size.y <= b.position.y: + return false + result = true + +proc distanceTo*(self: Rect2, p: Vector2): float32 {.noinit.} = + var inside = true + if p.x < self.position.x: + let d = self.position.x - p.x + result = d + inside = false + if p.y < self.position.y: + let d = self.position.y - p.y + result = if inside: d else: min(result, d) + inside = false + if p.x >= (self.position.x + self.size.x): + let d = p.x - (self.position.x + self.size.x) + result = if inside: d else: min(result, d) + inside = false + if p.y >= (self.position.y + self.size.y): + let d = p.y - (self.position.y + self.size.y) + result = if inside: d else: min(result, d) + inside = false + + if inside: + result = 0'f32 + +proc encloses*(a, b: Rect2): bool {.inline, noinit.} = + b.position.x >= a.position.x and b.position.y >= a.position.y and + (b.position.x + b.size.x) < (a.position.x + a.size.x) and + (b.position.y + b.size.y) < (a.position.y + a.size.y) + +proc hasNoArea*(self: Rect2): bool {.inline, noinit.} = + self.size.x <= 0 or self.size.y <= 0 + +proc clip*(self, b: Rect2): Rect2 {.inline, noinit.} = + if not self.intersects(b): + return initRect2() + + result = self + + result.position.x = max(b.position.x, self.position.x) + result.position.y = max(b.position.y, self.position.y) + + let bEnd = b.position + b.size + let selfEnd = self.position + self.size + + result.size.x = min(bEnd.x, selfEnd.x) - result.position.x + result.size.y = min(bEnd.y, selfEnd.y) - result.position.y + +proc merge*(self, b: Rect2): Rect2 {.inline, noinit.} = + result.position.x = min(b.position.x, self.position.x) + result.position.y = min(b.position.y, self.position.y) + + result.size.x = max(b.position.x + b.size.x, self.position.x + self.size.x) + result.size.y = max(b.position.y + b.size.y, self.position.y + self.size.y) + result.size -= result.position + +proc contains*(self: Rect2; point: Vector2): bool {.inline, noinit.} = + if point.x < self.position.x: + return false + if point.y < self.position.y: + return false + + if point.x >= self.position.x + self.size.x: + return false + if point.y >= self.position.y + self.size.y: + return false + + result = true + +proc grow*(self: Rect2; by: float32): Rect2 {.inline, noinit.} = + ## Returns Rect2 enlarged by the specified size in every direction. + result = self + + result.position.x -= by + result.position.y -= by + + result.size.x += by * 2 + result.size.y += by * 2 + +proc growIndividual*(self: Rect2, left, top: float32, + right, bottom: float32): Rect2 {.inline, noinit.} = + result = self + result.position.x -= left + result.position.y -= top + result.size.x += left + right + result.size.y += top + bottom + +proc expandTo*(self: var Rect2, to: Vector2) {.inline.} = + var startPoint = self.position + var endPoint = self.position + self.size + + if to.x < startPoint.x: + startPoint.x = to.x + if to.y < startPoint.y: + startPoint.y = to.y + + if to.x > endPoint.x: + endPoint.x = to.x + if to.y > endPoint.y: + endPoint.y = to.y + + self.position = startPoint + self.size = endPoint - startPoint + +proc expand*(self: Rect2; to: Vector2): Rect2 {.inline, noinit.} = + result = self + result.expandTo(to) + +proc abs*(self: Rect2): Rect2 {.inline, noinit.} = + Rect2(position: vec2(self.position.x + min(self.size.x, 0'f32), + self.position.y + min(self.size.y, 0'f32)), + size: abs(self.size)) + +proc `==`*(a, b: Rect2): bool {.inline, noinit.} = + a.position == b.position and a.size == b.size + +{.pop.} # stackTrace: off \ No newline at end of file diff --git a/godot/core/rect3.nim b/godot/core/rect3.nim deleted file mode 100644 index e9d93f6..0000000 --- a/godot/core/rect3.nim +++ /dev/null @@ -1,100 +0,0 @@ -# Copyright (c) 2017 Xored Software, Inc. - -import godotbase, plane, vector3, strings - -type - Rect3* {.importc: "godot_rect3", header: "godot_rect3.h", byref.} = object - -proc initRect3(dest: var Rect3; pos, size: Vector3) {. - importc: "godot_rect3_new", header: "godot_rect3.h".} - -proc initRect3*(pos, size: Vector3): Rect3 {.inline.} = - initRect3(result, pos, size) - -proc position*(self: Rect3): Vector3 {. - noSideEffect, - importc: "godot_rect3_get_position", header: "godot_rect3.h".} -proc setPosition*(self: var Rect3; v: Vector3) {. - noSideEffect - importc: "godot_rect3_set_position", header: "godot_rect3.h".} -proc size*(self: Rect3): Vector3 {. - noSideEffect, - importc: "godot_rect3_get_size", header: "godot_rect3.h".} -proc setSize*(self: var Rect3; v: Vector3) {. - noSideEffect, - importc: "godot_rect3_set_size", header: "godot_rect3.h".} -proc toGodotString*(self: Rect3): GodotString {. - noSideEffect, - importc: "godot_rect3_as_string", header: "godot_rect3.h".} -proc `$`*(self: Rect3): string {.inline.} = - $self.toGodotString() -proc area*(self: Rect3): float32 {. - noSideEffect, - importc: "godot_rect3_get_area", header: "godot_rect3.h".} -proc hasNoArea*(self: Rect3): bool {. - noSideEffect, - importc: "godot_rect3_has_no_area", header: "godot_rect3.h".} -proc hasNoSurface*(self: Rect3): bool {. - noSideEffect, - importc: "godot_rect3_has_no_surface", header: "godot_rect3.h".} -proc intersects*(a, b: Rect3): bool {. - noSideEffect, - importc: "godot_rect3_intersects", header: "godot_rect3.h".} -proc encloses*(self, other: Rect3): bool {. - noSideEffect, - importc: "godot_rect3_encloses", header: "godot_rect3.h".} -proc merge*(self, other: Rect3): Rect3 {. - noSideEffect, - importc: "godot_rect3_merge", header: "godot_rect3.h".} -proc intersection*(self, other: Rect3): Rect3 {. - noSideEffect, - importc: "godot_rect3_intersection", header: "godot_rect3.h".} -proc intersectsPlane*(self: Rect3; plane: Plane): bool {. - noSideEffect, - importc: "godot_rect3_intersects_plane", - header: "godot_rect3.h".} -proc intersectsSegment*(self: Rect3; start, to: Vector3): bool {. - noSideEffect, - importc: "godot_rect3_intersects_segment", - header: "godot_rect3.h".} -proc contains*(self: Rect3; point: Vector3): bool {. - noSideEffect, - importc: "godot_rect3_has_point", header: "godot_rect3.h".} -proc getSupport*(self: Rect3; dir: Vector3): Vector3 {. - noSideEffect, - importc: "godot_rect3_get_support", header: "godot_rect3.h".} -proc getLongestAxis*(self: Rect3): Vector3 {. - noSideEffect, - importc: "godot_rect3_get_longest_axis", header: "godot_rect3.h".} -proc getLongestAxisIndex*(self: Rect3): cint {. - noSideEffect, - importc: "godot_rect3_get_longest_axis_index", - header: "godot_rect3.h".} -proc getLongestAxisSize*(self: Rect3): float32 {. - noSideEffect, - importc: "godot_rect3_get_longest_axis_size", - header: "godot_rect3.h".} -proc getShortestAxis*(self: Rect3): Vector3 {. - noSideEffect, - importc: "godot_rect3_get_shortest_axis", header: "godot_rect3.h".} -proc getShortestAxisIndex*(self: Rect3): cint {. - noSideEffect, - importc: "godot_rect3_get_shortest_axis_index", - header: "godot_rect3.h".} -proc getShortestAxisSize*(self: Rect3): float32 {. - noSideEffect, - importc: "godot_rect3_get_shortest_axis_size", - header: "godot_rect3.h".} -proc expand*(self: Rect3; toPoint: Vector3): Rect3 {. - noSideEffect, - importc: "godot_rect3_expand", header: "godot_rect3.h".} -proc grow*(self: Rect3; by: float32): Rect3 {. - noSideEffect, - importc: "godot_rect3_grow", header: "godot_rect3.h".} -proc getEndpoint*(self: Rect3; idx: cint): Vector3 {. - noSideEffect, - importc: "godot_rect3_get_endpoint", header: "godot_rect3.h".} -proc `==`*(a, b: Rect3): bool {. - noSideEffect, - importc: "godot_rect3_operator_equal", - header: "godot_rect3.h".} diff --git a/godot/core/rid.nim b/godot/core/rid.nim deleted file mode 100644 index d8381d6..0000000 --- a/godot/core/rid.nim +++ /dev/null @@ -1,28 +0,0 @@ -import godotbase - -type - RID* {.importc: "godot_rid", header: "godot_rid.h", byref.} = object - -proc initRID(dest: var RID) {. - importc: "godot_rid_new", - header: "godot_rid.h".} -proc initRID(dest: var RID; obj: ptr GodotObject) {. - importc: "godot_rid_new_with_resource", header: "godot_rid.h".} - -proc initRID*(): RID {.inline.} = - initRID(result) - -proc initRID*(obj: ptr GodotObject): RID {.inline.} = - initRID(result, obj) - -proc idCInt(self: RID): cint {. - noSideEffect, - importc: "godot_rid_get_id", header: "godot_rid.h".} - -proc id*(self: RID): uint32 {.inline.} = - cast[uint32](self.idCInt()) - -proc `==`*(a, b: RID): bool {. - importc: "godot_rid_operator_equal", header: "godot_rid.h".} -proc `<`*(a, b: RID): bool {. - importc: "godot_rid_operator_less", header: "godot_rid.h".} diff --git a/godot/core/rids.nim b/godot/core/rids.nim new file mode 100644 index 0000000..a64137d --- /dev/null +++ b/godot/core/rids.nim @@ -0,0 +1,26 @@ +# Copyright (c) 2018 Xored Software, Inc. + +import hashes + +import godotcoretypes, internal/godotinternaltypes, gdnativeapi + +proc initRID*(): RID {.inline.} = + getGDNativeAPI().ridNew(result) + +proc initRID*(obj: ptr GodotObject): RID {.inline.} = + getGDNativeAPI().ridNewWithResource(result, obj) + +proc id*(self: RID): uint32 {.inline.} = + cast[uint32](getGDNativeAPI().ridGetId(self)) + +proc `$`*(self: RID): string {.inline.} = + $self.id + +proc hash*(self: RID): Hash {.inline.} = + self.id.hash() + +proc `==`*(a, b: RID): bool {.inline.} = + getGDNativeAPI().ridOperatorEqual(a, b) + +proc `<`*(a, b: RID): bool {.inline.} = + getGDNativeAPI().ridOperatorLess(a, b) diff --git a/godot/core/strings.nim b/godot/core/strings.nim deleted file mode 100644 index 5684eb5..0000000 --- a/godot/core/strings.nim +++ /dev/null @@ -1,58 +0,0 @@ -# Copyright (c) 2017 Xored Software, Inc. - -import godotbase - -type - GodotString* {.importc: "godot_string", header: "godot_string.h", - byref.} = object - -proc initGodotString(dest: var GodotString) {. - importc: "godot_string_new", header: "godot_string.h".} -proc initGodotString(dest: var GodotString; src: GodotString) {. - importc: "godot_string_new_copy", header: "godot_string.h".} -proc initGodotString(dest: var GodotString; contents: cstring; - size: cint) {. - importc: "godot_string_new_data", header: "godot_string.h".} - ## Initializes ``dest`` from UTF-8 ``contents`` -proc getData(self: GodotString; dest: cstring; - size: var cint) {. - noSideEffect - importc: "godot_string_get_data", - header: "godot_string.h".} - ## Converts ``self`` into UTF-8 encoding, putting the result into ``dest``. - -proc len*(self: GodotString): cint {.inline.} = - ## Returns the length of string in bytes if it is represented as UTF-8. - getData(self, nil, result) - -proc cstring*(self: GodotString): cstring {. - importc: "godot_string_c_str", header: "godot_string.h".} -proc `==`*(self, b: GodotString): bool {. - importc: "godot_string_operator_equal", - header: "godot_string.h".} -proc `<`*(self, b: GodotString): bool {. - importc: "godot_string_operator_less", - header: "godot_string.h".} -proc `&`*(self, b: GodotString): GodotString {. - importc: "godot_string_operator_plus", - header: "godot_string.h".} - -proc deinit*(self: var GodotString) {.importc: "godot_string_destroy", - header: "godot_string.h".} -proc `=destroy`(self: GodotString) {.inline.} = - unsafeAddr(self).deinit() - -proc `=`(self: var GodotString, other: GodotString) {.inline.} = - initGodotString(self, other) - -proc `$`*(self: GodotString): string = - ## Converts the ``GodotString`` into Nim string - var length = self.len - result = newStringOfCap(length) - getData(self, addr result[0], length) - result.setLen(length) - assert(result[length] == '\0') - -proc toGodotString*(s: string): GodotString {.inline.} = - ## Converts the Nim string into ``GodotString`` - initGodotString(result, unsafeAddr s[0], cint(s.len + 1)) diff --git a/godot/core/transform.nim b/godot/core/transform.nim deleted file mode 100644 index 7c3f001..0000000 --- a/godot/core/transform.nim +++ /dev/null @@ -1,82 +0,0 @@ -# Copyright (c) 2017 Xored Software, Inc. - -type - Transform* {.importc: "godot_transform", header: "godot_transform.h", - byref.} = object - -import godotbase, basis, variant, vector3, strings, plane, rect3 - -proc initTransform(dest: var Transform) {. - importc: "godot_transform_new_identity", header: "godot_transform.h".} - ## Initializes the ``dest`` as identity transform. -proc initTransform(dest: var Transform; - xAxis, yAxis, zAxis, origin: Vector3) {. - importc: "godot_transform_new_with_axis_origin", - header: "godot_transform.h".} -proc initTransform(dest: var Transform; basis: Basis; - origin: Vector3) {. - importc: "godot_transform_new", - header: "godot_transform.h".} - -proc initTransform*(): Transform {.inline.} = - initTransform(result) - -proc initTransform*(xAxis, yAxis, zAxis, - origin: Vector3): Transform {.inline.} = - initTransform(result, xAxis, yAxis, zAxis, origin) - -proc initTransform*(basis: Basis, origin: Vector3): Transform {.inline.} = - initTransform(result, basis, origin) - -proc basis*(self: Transform): Basis {. - importc: "godot_transform_get_basis", header: "godot_transform.h".} -proc `basis=`*(self: var Transform; v: Basis) {. - importc: "godot_transform_set_basis", header: "godot_transform.h".} -proc origin*(self: Transform): Vector3 {. - importc: "godot_transform_get_origin", header: "godot_transform.h".} -proc `origin=`*(self: var Transform; v: Vector3) {. - importc: "godot_transform_set_origin", header: "godot_transform.h".} - -proc toGodotString*(self: Transform): GodotString {. - importc: "godot_transform_as_string", header: "godot_transform.h".} -proc `$`*(self: Transform): string {.inline.} = - $self.toGodotString() - -proc inverse*(self: Transform): Transform {. - importc: "godot_transform_inverse", header: "godot_transform.h".} -proc affineInverse*(self: Transform): Transform {. - importc: "godot_transform_affine_inverse", - header: "godot_transform.h".} -proc orthonormalized*(self: Transform): Transform {. - importc: "godot_transform_orthonormalized", - header: "godot_transform.h".} -proc rotated*(self: Transform; axis: Vector3; - phi: float32): Transform {. - importc: "godot_transform_rotated", header: "godot_transform.h".} -proc scaled*(self: Transform; scale: Vector3): Transform {. - importc: "godot_transform_scaled", header: "godot_transform.h".} -proc translated*(self: Transform; offset: Vector3): Transform {. - importc: "godot_transform_translated", header: "godot_transform.h".} -proc lookingAt*(self: Transform; - target, up: Vector3): Transform {. - importc: "godot_transform_looking_at", header: "godot_transform.h".} - -proc xformPlane*(self: Transform; v: Plane): Plane {. - importc: "godot_transform_xform_plane", header: "godot_transform.h".} -proc xformInvPlane*(self: Transform; v: Plane): Plane {. - importc: "godot_transform_xform_inv_plane", header: "godot_transform.h".} -proc xformVector3*(self: Transform; v: Vector3): Vector3 {. - importc: "godot_transform_xform_vector3", header: "godot_transform.h".} -proc xformInvVector3*(self: Transform; v: Vector3): Vector3 {. - importc: "godot_transform_xform_inv_vector3", header: "godot_transform.h".} -proc xformRect3*(self: Transform; v: Vector3): Rect3 {. - importc: "godot_transform_xform_rect3", header: "godot_transform.h".} -proc xformInvRect3*(self: Transform; v: Vector3): Vector3 {. - importc: "godot_transform_xform_inv_rect3", header: "godot_transform.h".} - -proc `==`*(self: Transform; b: Transform): bool {. - importc: "godot_transform_operator_equal", header: "godot_transform.h".} -proc `*`*(a, b: Transform): Transform {. - importc: "godot_transform_operator_multiply", header: "godot_transform.h".} -proc `*=`*(a: var Transform, b: Transform) {.inline.} = - a = a * b diff --git a/godot/core/transform2d.nim b/godot/core/transform2d.nim index 047b95d..a8db09e 100644 --- a/godot/core/transform2d.nim +++ b/godot/core/transform2d.nim @@ -1,92 +1,79 @@ -# Copyright (c) 2017 Xored Software, Inc. +# Copyright (c) 2018 Xored Software, Inc. -type - Transform2D* {.importc: "godot_transform2d", header: "godot_transform2d.h", - byref.} = object +import hashes, vector2 -import godotbase, strings, variant, vector2, rect2 - -proc initTransform2D(dest: var Transform2D) {. - importc: "godot_transform2d_new_identity", header: "godot_transform2d.h".} -proc initTransform2D(dest: var Transform2D; rot: float32; pos: Vector2) {. - importc: "godot_transform2d_new", header: "godot_transform2d.h".} -proc initTransform2D(dest: var Transform2D; xAxis, yAxis, origin: Vector2) {. - importc: "godot_transform2d_new_axis_origin", - header: "godot_transform2d.h".} +import internal/godotinternaltypes, internal/godotstrings +import godotcoretypes, gdnativeapi proc initTransform2D*(): Transform2D {.inline.} = - initTransform2D(result) + getGDNativeAPI().transform2DNewIdentity(result) proc initTransform2D*(rot: float32; pos: Vector2): Transform2D {.inline.} = - initTransform2D(result, rot, pos) + getGDNativeAPI().transform2DNew(result, rot, pos) proc initTransform2D*(xAxis, yAxis, origin: Vector2): Transform2D {.inline.} = - initTransform2D(result, xAxis, yAxis, origin) + getGDNativeAPI().transform2DNewAxisOrigin(result, xAxis, yAxis, origin) -proc toGodotString*(self: Transform2D): GodotString {. - importc: "godot_transform2d_as_string", - header: "godot_transform2d.h".} proc `$`*(self: Transform2D): string {.inline.} = - $self.toGodotString() + $getGDNativeAPI().transform2DAsString(self) -proc inverse*(self: Transform2D): Transform2D {. - importc: "godot_transform2d_inverse", header: "godot_transform2d.h".} -proc affineInverse*(self: Transform2D): Transform2D {. - importc: "godot_transform2d_affine_inverse", - header: "godot_transform2d.h".} -proc rotation*(self: Transform2D): float32 {. - importc: "godot_transform2d_get_rotation", - header: "godot_transform2d.h".} -proc origin*(self: Transform2D): Vector2 {. - importc: "godot_transform2d_get_origin", - header: "godot_transform2d.h".} -proc scale*(self: Transform2D): Vector2 {. - importc: "godot_transform2d_get_scale", - header: "godot_transform2d.h".} -proc orthonormalized*(self: Transform2D): Transform2D {. - importc: "godot_transform2d_orthonormalized", - header: "godot_transform2d.h".} -proc rotated*(self: Transform2D; phi: float32): Transform2D {. - importc: "godot_transform2d_rotated", - header: "godot_transform2d.h".} -proc scaled*(self: Transform2D; scale: Vector2): Transform2D {. - importc: "godot_transform2d_scaled", - header: "godot_transform2d.h".} -proc translated*(self: Transform2D; - offset: Vector2): Transform2D {. - importc: "godot_transform2d_translated", - header: "godot_transform2d.h".} -proc xformVector2*(self: Transform2D; v: Vector2): Vector2 {. - importc: "godot_transform2d_xform_vector2", - header: "godot_transform2d.h".} -proc xformInvVector2*(self: Transform2D; v: Vector2): Vector2 {. - importc: "godot_transform2d_xform_inv_vector2", - header: "godot_transform2d.h".} -proc basisXformVector2*(self: Transform2D; - v: Vector2): Vector2 {. - importc: "godot_transform2d_basis_xform_vector2", - header: "godot_transform2d.h".} -proc basisXformInvVector2*(self: Transform2D; - v: Vector2): Vector2 {. - importc: "godot_transform2d_basis_xform_inv_vector2", - header: "godot_transform2d.h".} -proc xformRect2*(self: Transform2D; v: Rect2): Rect2 {. - importc: "godot_transform2d_xform_rect2", header: "godot_transform2d.h".} -proc xformInvRect2*(self: Transform2D; v: Rect2): Rect2 {. - importc: "godot_transform2d_xform_inv_rect2", - header: "godot_transform2d.h".} +proc hash*(self: Transform2D): Hash {.inline, noinit.} = + !$(self.elements[0].hash() !& self.elements[1].hash() !& self.elements[2].hash()) + +proc inverse*(self: Transform2D): Transform2D {.inline.} = + getGDNativeAPI().transform2DInverse(self).toTransform2D() + +proc affineInverse*(self: Transform2D): Transform2D {.inline.} = + getGDNativeAPI().transform2DAffineInverse(self).toTransform2D() + +proc rotation*(self: Transform2D): float32 {.inline.} = + getGDNativeAPI().transform2DGetRotation(self) + +proc origin*(self: Transform2D): Vector2 {.inline.} = + getGDNativeAPI().transform2DGetOrigin(self).toVector2() + +proc scale*(self: Transform2D): Vector2 {.inline.} = + getGDNativeAPI().transform2DGetScale(self).toVector2() + +proc orthonormalized*(self: Transform2D): Transform2D {.inline.} = + getGDNativeAPI().transform2DOrthonormalized(self).toTransform2D() + +proc rotated*(self: Transform2D; phi: float32): Transform2D {.inline.} = + getGDNativeAPI().transform2DRotated(self, phi).toTransform2D() + +proc scaled*(self: Transform2D; scale: Vector2): Transform2D {.inline.} = + getGDNativeAPI().transform2DScaled(self, scale).toTransform2D() + +proc translated*(self: Transform2D; offset: Vector2): Transform2D {.inline.} = + getGDNativeAPI().transform2DTranslated(self, offset).toTransform2D() + +proc xformVector2*(self: Transform2D; v: Vector2): Vector2 {.inline.} = + getGDNativeAPI().transform2DXformVector2(self, v).toVector2() + +proc xformInvVector2*(self: Transform2D; v: Vector2): Vector2 {.inline.} = + getGDNativeAPI().transform2DXformInvVector2(self, v).toVector2() + +proc basisXformVector2*(self: Transform2D; v: Vector2): Vector2 {.inline.} = + getGDNativeAPI().transform2DBasisXformVector2(self, v).toVector2() + +proc basisXformInvVector2*(self: Transform2D; v: Vector2): Vector2 {.inline.} = + getGDNativeAPI().transform2DBasisXformInvVector2(self, v).toVector2() + +proc xformRect2*(self: Transform2D; rect: Rect2): Rect2 {.inline.} = + getGDNativeAPI().transform2DXformRect2(self, rect).toRect2() + +proc xformInvRect2*(self: Transform2D; rect: Rect2): Rect2 {.inline.} = + getGDNativeAPI().transform2DXformInvRect2(self, rect).toRect2() proc interpolateWith*(self, m: Transform2D; - c: float32): Transform2D {. - importc: "godot_transform2d_interpolate_with", - header: "godot_transform2d.h".} -proc `==`*(a, b: Transform2D): bool {. - importc: "godot_transform2d_operator_equal", - header: "godot_transform2d.h".} -proc `*`*(a, b: Transform2D): Transform2D {. - importc: "godot_transform2d_operator_multiply", - header: "godot_transform2d.h".} + c: float32): Transform2D {.inline.} = + getGDNativeAPI().transform2DInterpolateWith(self, m, c).toTransform2D() + +proc `==`*(a, b: Transform2D): bool {.inline.} = + getGDNativeAPI().transform2DOperatorEqual(a, b) + +proc `*`*(a, b: Transform2D): Transform2D {.inline.} = + getGDNativeAPI().transform2DOperatorMultiply(a, b).toTransform2D() proc `*=`*(a: var Transform2D, b: Transform2D) {.inline.} = a = a * b - diff --git a/godot/core/transforms.nim b/godot/core/transforms.nim new file mode 100644 index 0000000..501f743 --- /dev/null +++ b/godot/core/transforms.nim @@ -0,0 +1,76 @@ +# Copyright (c) 2018 Xored Software, Inc. + +import hashes + +import internal/godotinternaltypes, internal/godotstrings +import godotcoretypes, gdnativeapi +import basis, vector3 + +proc initTransform*(): Transform {.inline.} = + result.basis = initBasis() + +proc initTransform*(xAxis, yAxis, zAxis, + origin: Vector3): Transform {.inline.} = + var basis: Basis + basis.setAxis(0, xAxis) + basis.setAxis(1, yAxis) + basis.setAxis(2, zAxis) + Transform(basis: basis, origin: origin) + +proc initTransform*(basis: Basis, origin: Vector3): Transform {.inline.} = + Transform(basis: basis, origin: origin) + +proc `$`*(self: Transform): string {.inline.} = + $getGDNativeAPI().transformAsString(self) + +proc hash*(self: Transform): Hash {.inline.} = + !$(self.basis.hash() !& self.origin.hash()) + +proc inverse*(self: Transform): Transform {.inline.} = + getGDNativeAPI().transformInverse(self).toTransform() + +proc affineInverse*(self: Transform): Transform {.inline.} = + getGDNativeAPI().transformAffineInverse(self).toTransform() + +proc orthonormalized*(self: Transform): Transform {.inline.} = + getGDNativeAPI().transformOrthonormalized(self).toTransform() + +proc rotated*(self: Transform; axis: Vector3; + phi: float32): Transform {.inline.} = + getGDNativeAPI().transformRotated(self, axis, phi).toTransform() + +proc scaled*(self: Transform; scale: Vector3): Transform {.inline.} = + getGDNativeAPI().transformScaled(self, scale).toTransform() + +proc translated*(self: Transform; offset: Vector3): Transform {.inline.} = + getGDNativeAPI().transformTranslated(self, offset).toTransform() + +proc lookingAt*(self: Transform; target, up: Vector3): Transform {.inline.} = + getGDNativeAPI().transformLookingAt(self, target, up).toTransform() + +proc xformPlane*(self: Transform; plane: Plane): Plane {.inline.} = + getGDNativeAPI().transformXformPlane(self, plane).toPlane() + +proc xformInvPlane*(self: Transform; plane: Plane): Plane {.inline.} = + getGDNativeAPI().transformXformInvPlane(self, plane).toPlane() + +proc xformVector3*(self: Transform; v: Vector3): Vector3 {.inline.} = + getGDNativeAPI().transformXformVector3(self, v).toVector3() + +proc xformInvVector3*(self: Transform; v: Vector3): Vector3 {.inline.} = + getGDNativeAPI().transformXformInvVector3(self, v).toVector3() + +proc xformAABB*(self: Transform; rect: AABB): AABB {.inline.} = + getGDNativeAPI().transformXformAABB(self, rect).toAABB() + +proc xformInvAABB*(self: Transform; rect: AABB): AABB {.inline.} = + getGDNativeAPI().transformXformInvAABB(self, rect).toAABB() + +proc `==`*(self: Transform; b: Transform): bool {.inline.} = + getGDNativeAPI().transformOperatorEqual(self, b) + +proc `*`*(self, other: Transform): Transform {.inline.} = + getGDNativeAPI().transformOperatorMultiply(self, other).toTransform() + +proc `*=`*(self: var Transform, other: Transform) {.inline.} = + self = self * other diff --git a/godot/core/variant.nim b/godot/core/variant.nim deleted file mode 100644 index 56e5eb5..0000000 --- a/godot/core/variant.nim +++ /dev/null @@ -1,291 +0,0 @@ -import godotbase - -import arrays, basis, nodepath -import plane, poolarray, quat, rect2, rect3, rid -import strings, transform, transform2d, vector2 -import vector3, color - -type - VariantType* {.importc: "godot_variant_type", header: "godot_variant.h", - size: sizeof(cint), pure.} = enum - Nil, ## atomic types - Bool, - Int, - Real, - String, - # math types - Vector2, ## 5 - Rect2, - Vector3, - Transform2D, - Plane, - Quat, ## 10 - Rect3, - Basis, - Transform, ## misc types - Color, - NodePath, ## 15 - RID, - Object, - Dictionary, - Array, ## 20 - # arrays - PoolByteArray, - PoolIntArray, - PoolRealArray, - PoolStringArray, - PoolVector2Array, ## 25 - PoolVector3Array, - PoolColorArray - - VariantCallErrorType* {.importc: "godot_variant_call_error_error", - header: "godot_variant.h", - size: sizeof(cint), - pure.} = enum - OK, - InvalidMethod, - InvalidArgument, - TooManyArguments, - TooFewArguments, - InstanceIsNull - - VariantCallError* {.importc: "godot_variant_call_error", - header: "godot_variant.h".} = object - error* {.importc: "error".}: VariantCallErrorType - argument* {.importc: "argument".}: cint - expected* {.importc: "expected".}: VariantType - -proc getType*(p: Variant): VariantType {. - importc: "godot_variant_get_type", header: "godot_variant.h".} - -proc initNilVariant(dest: var Variant) {. - importc: "godot_variant_new_nil", header: "godot_variant.h".} -proc initVariant(dest: var Variant; b: bool) {. - importc: "godot_variant_new_bool", header: "godot_variant.h".} -proc initVariant(dest: var Variant; i: uint64) {. - importc: "godot_variant_new_uint", header: "godot_variant.h".} -proc initVariant(dest: var Variant; i: int64) {. - importc: "godot_variant_new_int", header: "godot_variant.h".} -proc initVariant(dest: var Variant; r: cdouble) {. - importc: "godot_variant_new_real", header: "godot_variant.h".} -proc initVariant(dest: var Variant; s: GodotString) {. - importc: "godot_variant_new_string", header: "godot_variant.h".} -proc initVariant(dest: var Variant; v2: Vector2) {. - importc: "godot_variant_new_vector2", header: "godot_variant.h".} -proc initVariant(dest: var Variant; rect2: Rect2) {. - importc: "godot_variant_new_rect2", header: "godot_variant.h".} -proc initVariant(dest: var Variant; v3: Vector3) {. - importc: "godot_variant_new_vector3", header: "godot_variant.h".} -proc initVariant(dest: var Variant; t2d: Transform2D) {. - importc: "godot_variant_new_transform2d", - header: "godot_variant.h".} -proc initVariant(dest: var Variant; plane: Plane) {. - importc: "godot_variant_new_plane", header: "godot_variant.h".} -proc initVariant(dest: var Variant; quat: Quat) {. - importc: "godot_variant_new_quat", header: "godot_variant.h".} -proc initVariant(dest: var Variant; rect3: Rect3) {. - importc: "godot_variant_new_rect3", header: "godot_variant.h".} -proc initVariant(dest: var Variant; basis: Basis) {. - importc: "godot_variant_new_basis", header: "godot_variant.h".} -proc initVariant(dest: var Variant; - trans: Transform) {. - importc: "godot_variant_new_transform", - header: "godot_variant.h".} -proc initVariant(dest: var Variant; color: Color) {. - importc: "godot_variant_new_color", header: "godot_variant.h".} -proc initVariant(dest: var Variant; nodePath: NodePath) {. - importc: "godot_variant_new_node_path", - header: "godot_variant.h".} -proc initVariant(dest: var Variant; rid: RID) {. - importc: "godot_variant_new_rid", header: "godot_variant.h".} -proc initVariant(dest: var Variant; obj: ptr GodotObject) {. - importc: "godot_variant_new_object", header: "godot_variant.h".} -proc initVariant(dest: var Variant; arr: Array) {. - importc: "godot_variant_new_array", header: "godot_variant.h".} -proc initVariant(dest: var Variant; pba: PoolByteArray) {. - importc: "godot_variant_new_pool_byte_array", - header: "godot_variant.h".} -proc initVariant(dest: var Variant; pia: PoolIntArray) {. - importc: "godot_variant_new_pool_int_array", - header: "godot_variant.h".} -proc initVariant(dest: var Variant; pra: PoolRealArray) {. - importc: "godot_variant_new_pool_real_array", - header: "godot_variant.h".} -proc initVariant(dest: var Variant; psa: PoolStringArray) {. - importc: "godot_variant_new_pool_string_array", - header: "godot_variant.h".} -proc initVariant(dest: var Variant; pv2a: PoolVector2Array) {. - importc: "godot_variant_new_pool_vector2_array", - header: "godot_variant.h".} -proc initVariant(dest: var Variant; pv3a: PoolVector3Array) {. - importc: "godot_variant_new_pool_vector3_array", - header: "godot_variant.h".} -proc initVariant(dest: var Variant; pca: PoolColorArray) {. - importc: "godot_variant_new_pool_color_array", - header: "godot_variant.h".} - -proc variant*(): Variant {.inline.} = - initNilVariant(result) - -proc variant*(b: bool): Variant {.inline.} = - initVariant(result, b) - -proc variant*(i: uint64): Variant {.inline.} = - initVariant(result, i) - -proc variant*(i: int64): Variant {.inline.} = - initVariant(result, i) - -proc variant*(r: cdouble): Variant {.inline.} = - initVariant(result, r) - -proc variant*(s: GodotString): Variant {.inline.} = - initVariant(result, s) - -proc variant*(s: string): Variant {.inline.} = - let godotStr = s.toGodotString() - initVariant(result, godotStr) - -proc variant*(v2: Vector2): Variant {.inline.} = - initVariant(result, v2) - -proc variant*(rect2: Rect2): Variant {.inline.} = - initVariant(result, rect2) - -proc variant*(v3: Vector3): Variant {.inline.} = - initVariant(result, v3) - -proc variant*(t2d: Transform2D): Variant {.inline.} = - initVariant(result, t2d) - -proc variant*(plane: Plane): Variant {.inline.} = - initVariant(result, plane) - -proc variant*(quat: Quat): Variant {.inline.} = - initVariant(result, quat) - -proc variant*(rect3: Rect3): Variant {.inline.} = - initVariant(result, rect3) - -proc variant*(basis: Basis): Variant {.inline.} = - initVariant(result, basis) - -proc variant*(trans: Transform): Variant {.inline.} = - initVariant(result, trans) - -proc variant*(color: Color): Variant {.inline.} = - initVariant(result, color) - -proc variant*(nodePath: NodePath): Variant {.inline.} = - initVariant(result, nodePath) - -proc variant*(rid: RID): Variant {.inline.} = - initVariant(result, rid) - -proc variant*(obj: ptr GodotObject): Variant {.inline.} = - initVariant(result, obj) - -proc variant*(arr: Array): Variant {.inline.} = - initVariant(result, arr) - -proc variant*(pba: PoolByteArray): Variant {.inline.} = - initVariant(result, pba) - -proc variant*(pia: PoolIntArray): Variant {.inline.} = - initVariant(result, pia) - -proc variant*(pra: PoolRealArray): Variant {.inline.} = - initVariant(result, pra) - -proc variant*(psa: PoolStringArray): Variant {.inline.} = - initVariant(result, psa) - -proc variant*(pv2a: PoolVector2Array): Variant {.inline.} = - initVariant(result, pv2a) - -proc variant*(pv3a: PoolVector3Array): Variant {.inline.} = - initVariant(result, pv3a) - -proc variant*(pca: PoolColorArray): Variant {.inline.} = - initVariant(result, pca) - -proc asBool*(self: Variant): bool {. - importc: "godot_variant_as_bool", header: "godot_variant.h".} -proc asUint*(self: Variant): uint64 {. - importc: "godot_variant_as_uint", header: "godot_variant.h".} -proc asInt*(self: Variant): int64 {. - importc: "godot_variant_as_int", header: "godot_variant.h".} -proc asReal*(self: Variant): cdouble {. - importc: "godot_variant_as_real", header: "godot_variant.h".} -proc asGodotString*(self: Variant): GodotString {. - importc: "godot_variant_as_string", header: "godot_variant.h".} - -proc asString*(self: Variant): string = - let s = self.asGodotString() - result = $s - -proc asVector2*(self: Variant): Vector2 {. - importc: "godot_variant_as_vector2", header: "godot_variant.h".} -proc asRect2*(self: Variant): Rect2 {. - importc: "godot_variant_as_rect2", header: "godot_variant.h".} -proc asVector3*(self: Variant): Vector3 {. - importc: "godot_variant_as_vector3", header: "godot_variant.h".} -proc asTransform2D*(self: Variant): Transform2D {. - importc: "godot_variant_as_transform2d", header: "godot_variant.h".} -proc asPlane*(self: Variant): Plane {. - importc: "godot_variant_as_plane", header: "godot_variant.h".} -proc asQuat*(self: Variant): Quat {. - importc: "godot_variant_as_quat", header: "godot_variant.h".} -proc asRect3*(self: Variant): Rect3 {. - importc: "godot_variant_as_rect3", header: "godot_variant.h".} -proc asBasis*(self: Variant): Basis {. - importc: "godot_variant_as_basis", header: "godot_variant.h".} -proc asTransform*(self: Variant): Transform {. - importc: "godot_variant_as_transform", header: "godot_variant.h".} -proc asColor*(self: Variant): Color {. - importc: "godot_variant_as_color", header: "godot_variant.h".} -proc asNodePath*(self: Variant): NodePath {. - importc: "godot_variant_as_node_path", header: "godot_variant.h".} -proc asRid*(self: Variant): RID {. - importc: "godot_variant_as_rid", header: "godot_variant.h".} -proc asObject*(self: Variant): ptr GodotObject {. - importc: "godot_variant_as_object", header: "godot_variant.h".} -proc asArray*(self: Variant): Array {. - importc: "godot_variant_as_array", header: "godot_variant.h".} -proc asPoolByteArray*(self: Variant): PoolByteArray {. - importc: "godot_variant_as_pool_byte_array", - header: "godot_variant.h".} -proc asPoolIntArray*(self: Variant): PoolIntArray {. - importc: "godot_variant_as_pool_int_array", - header: "godot_variant.h".} -proc asPoolRealArray*(self: Variant): PoolRealArray {. - importc: "godot_variant_as_pool_real_array", - header: "godot_variant.h".} -proc asPoolStringArray*(self: Variant): PoolStringArray {. - importc: "godot_variant_as_pool_string_array", - header: "godot_variant.h".} -proc asPoolVector2Array*(self: Variant): PoolVector2Array {. - importc: "godot_variant_as_pool_vector2_array", - header: "godot_variant.h".} -proc asPoolVector3Array*(self: Variant): PoolVector3Array {. - importc: "godot_variant_as_pool_vector3_array", - header: "godot_variant.h".} -proc asPoolColorArray*(self: Variant): PoolColorArray {. - importc: "godot_variant_as_pool_color_array", - header: "godot_variant.h".} - -proc call*(self: Variant; meth: GodotString; - args: var array[MAX_ARG_COUNT, Variant]; argCount: cint; - error: var VariantCallError): Variant {. - importc: "godot_variant_call", header: "godot_variant.h".} - -proc hasMethod*(self: Variant; meth: GodotString): bool {. - importc: "godot_variant_has_method", header: "godot_variant.h".} -proc `==`*(self, other: Variant): bool {. - importc: "godot_variant_operator_equal", header: "godot_variant.h".} -proc `<`*(self, other: Variant): bool {. - importc: "godot_variant_operator_less", header: "godot_variant.h".} -proc hashCompare*(self, other: Variant): bool {. - importc: "godot_variant_hash_compare", header: "godot_variant.h".} -proc booleanize*(self: Variant; isValid: var bool): bool {. - importc: "godot_variant_booleanize", header: "godot_variant.h".} diff --git a/godot/core/variants.nim b/godot/core/variants.nim new file mode 100644 index 0000000..fcb2b04 --- /dev/null +++ b/godot/core/variants.nim @@ -0,0 +1,308 @@ +import tables, hashes + +import godotcoretypes +import internal/godotinternaltypes, internal/godotvariants, + internal/godotstrings, internal/godotdictionaries, + internal/godotarrays + +type + Variant* = ref object + godotVariant: GodotVariant + noDeinit: bool # used to avoid copying when passing the variant to Godot + +export VariantType, VariantCallErrorType, VariantCallError + +proc markNoDeinit*(v: Variant) {.inline.} = + ## Makes it so that internal GodotVariant object will not be destroyed + ## when the reference is gone. Use only if you know what you are doing. + v.noDeinit = true + +proc godotVariant*(v: Variant): ptr GodotVariant {.inline.} = + ## WARNING: do not keep the returned value for longer than the lifetime of + ## ``v`` + addr v.godotVariant + +proc getType*(v: Variant): VariantType = + v.godotVariant.getType() + +proc variantFinalizer*(v: Variant) = + if not v.noDeinit: + v.godotVariant.deinit() + +proc `$`*(self: Variant): string {.inline.} = + $self.godotVariant + +proc newVariant*(): Variant {.inline.} = + new(result, variantFinalizer) + initGodotVariant(result.godotVariant) + +proc newVariant*(v: Variant): Variant {.inline.} = + ## Makes a copy + new(result, variantFinalizer) + initGodotVariant(result.godotVariant, v.godotVariant) + +proc newVariant*(v: GodotVariant): Variant {.inline.} = + new(result, variantFinalizer) + result.godotVariant = v + +proc newVariant*(b: bool): Variant {.inline.} = + new(result, variantFinalizer) + initGodotVariant(result.godotVariant, b) + +# resolves Nim call ambiguities well +template numConstructor(T, ConvT) = + proc newVariant*(i: T): Variant {.inline.} = + new(result, variantFinalizer) + initGodotVariant(result.godotVariant, ConvT(i)) + +numConstructor(uint8, uint64) +numConstructor(uint16, uint64) +numConstructor(uint32, uint64) +numConstructor(uint64, uint64) +numConstructor(uint, uint64) + +numConstructor(int8, int64) +numConstructor(int16, int64) +numConstructor(int32, int64) +numConstructor(int64, int64) +numConstructor(int, int64) + +proc newVariant*(r: cdouble): Variant {.inline.} = + new(result, variantFinalizer) + initGodotVariant(result.godotVariant, r) + +proc newVariant*(s: string): Variant {.inline.} = + new(result, variantFinalizer) + when (NimMajor, NimMinor, NimPatch) < (0, 19, 0): + if s.isNil: + initGodotVariant(result.godotVariant) + return + var godotStr = s.toGodotString() + initGodotVariant(result.godotVariant, godotStr) + godotStr.deinit() + +import basis, nodepaths +import planes, quats, rect2, aabb, rids +import transforms, transform2d, vector2 +import vector3, colors + +proc newVariant*(v2: Vector2): Variant {.inline.} = + new(result, variantFinalizer) + initGodotVariant(result.godotVariant, v2) + +proc newVariant*(rect2: Rect2): Variant {.inline.} = + new(result, variantFinalizer) + initGodotVariant(result.godotVariant, rect2) + +proc newVariant*(v3: Vector3): Variant {.inline.} = + new(result, variantFinalizer) + initGodotVariant(result.godotVariant, v3) + +proc newVariant*(t2d: Transform2D): Variant {.inline.} = + new(result, variantFinalizer) + initGodotVariant(result.godotVariant, t2d) + +proc newVariant*(plane: Plane): Variant {.inline.} = + new(result, variantFinalizer) + initGodotVariant(result.godotVariant, plane) + +proc newVariant*(quat: Quat): Variant {.inline.} = + new(result, variantFinalizer) + initGodotVariant(result.godotVariant, quat) + +proc newVariant*(aabb: AABB): Variant {.inline.} = + new(result, variantFinalizer) + initGodotVariant(result.godotVariant, aabb) + +proc newVariant*(basis: Basis): Variant {.inline.} = + new(result, variantFinalizer) + initGodotVariant(result.godotVariant, basis) + +proc newVariant*(trans: Transform): Variant {.inline.} = + new(result, variantFinalizer) + initGodotVariant(result.godotVariant, trans) + +proc newVariant*(color: Color): Variant {.inline.} = + new(result, variantFinalizer) + initGodotVariant(result.godotVariant, color) + +proc newVariant*(nodePath: NodePath): Variant {.inline.} = + new(result, variantFinalizer) + initGodotVariant(result.godotVariant, nodePath.godotNodePath[]) + +proc newVariant*(godotNodePath: GodotNodePath): Variant {.inline.} = + new(result, variantFinalizer) + initGodotVariant(result.godotVariant, godotNodePath) + +proc newVariant*(rid: RID): Variant {.inline.} = + new(result, variantFinalizer) + initGodotVariant(result.godotVariant, rid) + +proc newVariant*(obj: ptr GodotObject): Variant {.inline.} = + new(result, variantFinalizer) + initGodotVariant(result.godotVariant, obj) + +import poolarrays + +proc newVariant*(pba: PoolByteArray): Variant {.inline.} = + new(result, variantFinalizer) + initGodotVariant(result.godotVariant, pba.godotPoolByteArray[]) + +proc newVariant*(pia: PoolIntArray): Variant {.inline.} = + new(result, variantFinalizer) + initGodotVariant(result.godotVariant, pia.godotPoolIntArray[]) + +proc newVariant*(pra: PoolRealArray): Variant {.inline.} = + new(result, variantFinalizer) + initGodotVariant(result.godotVariant, pra.godotPoolRealArray[]) + +proc newVariant*(psa: PoolStringArray): Variant {.inline.} = + new(result, variantFinalizer) + initGodotVariant(result.godotVariant, psa.godotPoolStringArray[]) + +proc newVariant*(pv2a: PoolVector2Array): Variant {.inline.} = + new(result, variantFinalizer) + initGodotVariant(result.godotVariant, pv2a.godotPoolVector2Array[]) + +proc newVariant*(pv3a: PoolVector3Array): Variant {.inline.} = + new(result, variantFinalizer) + initGodotVariant(result.godotVariant, pv3a.godotPoolVector3Array[]) + +proc newVariant*(pca: PoolColorArray): Variant {.inline.} = + new(result, variantFinalizer) + initGodotVariant(result.godotVariant, pca.godotPoolColorArray[]) + +proc asBool*(self: Variant): bool {.inline.} = + self.godotVariant.asBool() + +proc asUInt*(self: Variant): uint64 {.inline.} = + self.godotVariant.asUInt() + +proc asInt*(self: Variant): int64 {.inline.} = + self.godotVariant.asInt() + +proc asReal*(self: Variant): cdouble {.inline.} = + self.godotVariant.asReal() + +proc asString*(self: Variant): string {.inline.} = + $self + +proc asVector2*(self: Variant): Vector2 {.inline.} = + self.godotVariant.asVector2() + +proc asRect2*(self: Variant): Rect2 {.inline.} = + self.godotVariant.asRect2() + +proc asVector3*(self: Variant): Vector3 {.inline.} = + self.godotVariant.asVector3() + +proc asTransform2D*(self: Variant): Transform2D {.inline.} = + self.godotVariant.asTransform2D() + +proc asPlane*(self: Variant): Plane {.inline.} = + self.godotVariant.asPlane() + +proc asQuat*(self: Variant): Quat {.inline.} = + self.godotVariant.asQuat() + +proc asAABB*(self: Variant): AABB {.inline.} = + self.godotVariant.asAABB() + +proc asBasis*(self: Variant): Basis {.inline.} = + self.godotVariant.asBasis() + +proc asTransform*(self: Variant): Transform {.inline.} = + self.godotVariant.asTransform() + +proc asColor*(self: Variant): Color {.inline.} = + self.godotVariant.asColor() + +proc asNodePath*(self: Variant): NodePath {.inline.} = + result = newNodePath(self.godotVariant.asNodePath()) + +proc asRID*(self: Variant): RID {.inline.} = + self.godotVariant.asRID() + +proc asGodotObject*(self: Variant): ptr GodotObject {.inline.} = + self.godotVariant.asGodotObject() + +proc asPoolByteArray*(self: Variant): PoolByteArray {.inline.} = + newPoolByteArray(self.godotVariant.asGodotPoolByteArray()) + +proc asPoolIntArray*(self: Variant): PoolIntArray {.inline.} = + newPoolIntArray(self.godotVariant.asGodotPoolIntArray()) + +proc asPoolRealArray*(self: Variant): PoolRealArray {.inline.} = + newPoolRealArray(self.godotVariant.asGodotPoolRealArray()) + +proc asPoolStringArray*(self: Variant): PoolStringArray {.inline.} = + newPoolStringArray(self.godotVariant.asGodotPoolStringArray()) + +proc asPoolVector2Array*(self: Variant): PoolVector2Array {.inline.} = + newPoolVector2Array(self.godotVariant.asGodotPoolVector2Array()) + +proc asPoolVector3Array*(self: Variant): PoolVector3Array {.inline.} = + newPoolVector3Array(self.godotVariant.asGodotPoolVector3Array()) + +proc asPoolColorArray*(self: Variant): PoolColorArray {.inline.} = + newPoolColorArray(self.godotVariant.asGodotPoolColorArray()) + +proc hash*(self: Variant): Hash = + proc objectHash(obj: ptr GodotObject): Hash = + if not obj.isNil: cast[int](obj).hash() else: 0.hash() + result = case self.getType(): + of VariantType.Nil: Hash(0) + of VariantType.Bool: self.asBool().hash() + of VariantType.Int: self.asInt().hash() + of VariantType.Real: self.asReal().hash() + of VariantType.String: self.asString().hash() + of VariantType.Vector2: self.asVector2().hash() + of VariantType.Rect2: self.asRect2().hash() + of VariantType.Vector3: self.asVector3().hash() + of VariantType.Transform2D: self.asTransform2D().hash() + of VariantType.Plane: self.asPlane().hash() + of VariantType.Quat: self.asQuat().hash() + of VariantType.AABB: self.asAABB().hash() + of VariantType.Basis: self.asBasis().hash() + of VariantType.Transform: self.asTransform().hash() + of VariantType.Color: self.asColor().hash() + of VariantType.NodePath: self.asNodePath().hash() + of VariantType.RID: self.asRID().hash() + of VariantType.Object: self.asGodotObject().objectHash() + of VariantType.Dictionary: hash(self.godotVariant.asGodotDictionary().godotHash()) + of VariantType.Array: hash(self.godotVariant.asGodotArray().godotHash()) + of VariantType.PoolByteArray: self.asPoolByteArray().hash() + of VariantType.PoolIntArray: self.asPoolIntArray().hash() + of VariantType.PoolRealArray: self.asPoolRealArray().hash() + of VariantType.PoolStringArray: self.asPoolStringArray().hash() + of VariantType.PoolVector2Array: self.asPoolVector2Array().hash() + of VariantType.PoolVector3Array: self.asPoolVector3Array().hash() + of VariantType.PoolColorArray: self.asPoolColorArray().hash() + +import arrays + +proc newVariant*(arr: Array): Variant {.inline.} = + new(result, variantFinalizer) + initGodotVariant(result.godotVariant, arr.godotArray[]) + +proc asArray*(self: Variant): Array {.inline.} = + newArray(self.godotVariant.asGodotArray()) + +proc hasMethod*(self: Variant; meth: string): bool = + var s = meth.toGodotString() + result = self.godotVariant.hasMethod(s) + s.deinit() + +proc `==`*(self, other: Variant): bool = + if self.isNil and other.isNil: return true + if self.isNil != other.isNil: return false + result = self.godotVariant == other.godotVariant + +proc `<`*(self, other: Variant): bool = + result = self.godotVariant < other.godotVariant + +proc hashCompare*(self, other: Variant): bool = + self.godotVariant.hashCompare(other.godotVariant) + +proc booleanize*(self: Variant): bool = + self.godotVariant.booleanize() diff --git a/godot/core/vector2.nim b/godot/core/vector2.nim index ae6ef0c..390f1f6 100644 --- a/godot/core/vector2.nim +++ b/godot/core/vector2.nim @@ -1,117 +1,214 @@ -# Copyright (c) 2017 Xored Software, Inc. +# Copyright (c) 2018 Xored Software, Inc. -type - Vector2* {.importc: "godot_vector2", header: "godot_vector2.h", - byref.} = object +import math, godotbase, hashes -import godotbase, strings +import internal/godotinternaltypes, internal/godotstrings +import godotcoretypes, gdnativeapi -proc initVector2(dest: var Vector2; x, y: float32) {. - importc: "godot_vector2_new", header: "godot_vector2.h".} +const EPSILON = 0.00001'f32 -proc vec2*(x, y: float32): Vector2 {.inline.} = - initVector2(result, x, y) +{.push stackTrace: off.} -proc toGodotString*(self: Vector2): GodotString {. - importc: "godot_vector2_as_string", header: "godot_vector2.h".} -proc `$`*(self: Vector2): string {.inline.} = - $self.toGodotString() +proc vec2*(): Vector2 {.inline, noinit.} = + Vector2() -proc normalized*(self: Vector2): Vector2 {. - importc: "godot_vector2_normalized", header: "godot_vector2.h".} -proc length*(self: Vector2): float32 {. - importc: "godot_vector2_length", header: "godot_vector2.h".} -proc angle*(self: Vector2): float32 {. - importc: "godot_vector2_angle", header: "godot_vector2.h".} -proc lengthSquared*(self: Vector2): float32 {. - importc: "godot_vector2_length_squared", header: "godot_vector2.h".} -proc isNormalized*(self: Vector2): bool {. - importc: "godot_vector2_is_normalized", header: "godot_vector2.h".} -proc distanceTo*(self, to: Vector2): float32 {. - importc: "godot_vector2_distance_to", - header: "godot_vector2.h".} -proc distanceSquaredTo*(self, to: Vector2): float32 {. - importc: "godot_vector2_distance_squared_to", - header: "godot_vector2.h".} -proc angleTo*(self, to: Vector2): float32 {. - importc: "godot_vector2_angle_to", header: "godot_vector2.h".} -proc angleToPoint*(self, to: Vector2): float32 {. - importc: "godot_vector2_angle_to_point", - header: "godot_vector2.h".} -proc lerp*(self, b: Vector2; t: float32): Vector2 {. - importc: "godot_vector2_linear_interpolate", - header: "godot_vector2.h".} -proc cubicInterpolate*(self, b, pre_a, post_b: Vector2; t: float32): Vector2 {. - importc: "godot_vector2_cubic_interpolate", - header: "godot_vector2.h".} -proc rotated*(self: Vector2; phi: float32): Vector2 {. - importc: "godot_vector2_rotated", header: "godot_vector2.h".} -proc tangent*(self: Vector2): Vector2 {. - importc: "godot_vector2_tangent", header: "godot_vector2.h".} -proc floor*(self: Vector2): Vector2 {. - importc: "godot_vector2_floor", header: "godot_vector2.h".} -proc snapped*(self: Vector2; by: Vector2): Vector2 {. - importc: "godot_vector2_snapped", header: "godot_vector2.h".} -proc aspect*(self: Vector2): float32 {. - importc: "godot_vector2_aspect", header: "godot_vector2.h".} -proc dot*(a, b: Vector2): float32 {. - importc: "godot_vector2_dot", header: "godot_vector2.h".} -proc slide*(self, n: Vector2): Vector2 {. - importc: "godot_vector2_slide", header: "godot_vector2.h".} -proc bounce*(self, n: Vector2): Vector2 {. - importc: "godot_vector2_bounce", header: "godot_vector2.h".} -proc reflect*(self, n: Vector2): Vector2 {. - importc: "godot_vector2_reflect", header: "godot_vector2.h".} -proc abs*(self: Vector2): Vector2 {. - importc: "godot_vector2_abs", header: "godot_vector2.h".} -proc clamped*(self: Vector2; length: float32): Vector2 {. - importc: "godot_vector2_clamped", header: "godot_vector2.h".} +proc vec2*(x, y: float32): Vector2 {.inline, noinit.} = + Vector2(x: x, y: y) -proc `+`*(a, b: Vector2): Vector2 {. - importc: "godot_vector2_operator_add", header: "godot_vector2.h".} -proc `+=`*(a: var Vector2, b: Vector2) {.inline.} = - a += b +proc `$`*(self: Vector2): string {.inline, noinit.} = + $getGDNativeAPI().vector2AsString(self) -proc `-`*(a, b: Vector2): Vector2 {. - importc: "godot_vector2_operator_substract", header: "godot_vector2.h".} -proc `-=`*(a: var Vector2, b: Vector2) {.inline.} = - a = a - b +proc hash*(self: Vector2): Hash {.inline, noinit.} = + !$(self.x.hash() !& self.y.hash()) -proc `*`*(a, b: Vector2): Vector2 {. - importc: "godot_vector2_operator_multiply_vector", - header: "godot_vector2.h".} +proc `+`*(self, other: Vector2): Vector2 {.inline, noinit.} = + Vector2(x: self.x + other.x, y: self.y + other.y) -proc `*=`*(a: var Vector2, b: Vector2) {.inline.} = - a = a * b +proc `+=`*(self: var Vector2, other: Vector2) {.inline, noinit.} = + self.x += other.x + self.y += other.y -proc `*`*(self: Vector2, scalar: float32): Vector2 {. - importc: "godot_vector2_operator_multiply_scalar", - header: "godot_vector2.h".} -proc `*=`*(self: var Vector2, scalar: float32) {.inline.} = - self = self * scalar +proc `-`*(self, other: Vector2): Vector2 {.inline, noinit.} = + Vector2(x: self.x - other.x, y: self.y - other.y) -proc `/`*(a, b: Vector2): Vector2 {. - importc: "godot_vector2_operator_divide_vector", header: "godot_vector2.h".} -proc `/=`*(a: var Vector2, b: Vector2) {.inline.} = - a = a / b +proc `-=`*(self: var Vector2, other: Vector2) {.inline, noinit.} = + self.x -= other.x + self.y -= other.y -proc `/`*(self: Vector2; scalar: float32): Vector2 {. - importc: "godot_vector2_operator_divide_scalar", header: "godot_vector2.h".} -proc `/=`*(self: var Vector2; scalar: float32) {.inline.} = +proc `*`*(self, other: Vector2): Vector2 {.inline, noinit.} = + Vector2(x: self.x * other.x, y: self.y * other.y) + +proc `*=`*(self: var Vector2, other: Vector2) {.inline, noinit.} = + self.x *= other.x + self.y *= other.y + +proc `*`*(self: Vector2, scalar: float32): Vector2 {.inline, noinit.} = + Vector2(x: self.x * scalar, y: self.y * scalar) + +proc `*`*(scalar: float32, v: Vector2): Vector2 {.inline, noinit.} = + v * scalar + +proc `*=`*(self: var Vector2, scalar: float32) {.inline, noinit.} = + self.x *= scalar + self.y *= scalar + +proc `/`*(self, other: Vector2): Vector2 {.inline, noinit.} = + Vector2(x: self.x / other.x, y: self.y / other.y) + +proc `/=`*(self: var Vector2, other: Vector2) {.inline, noinit.} = + self.x /= other.x + self.y /= other.y + +proc `/`*(self: Vector2; scalar: float32): Vector2 {.inline, noinit.} = + Vector2(x: self.x / scalar, y: self.y / scalar) + +proc `/=`*(self: var Vector2; scalar: float32) {.inline, noinit.} = self = self / scalar -proc `==`*(a, b: Vector2): bool {. - importc: "godot_vector2_operator_equal", header: "godot_vector2.h".} -proc `<`*(a, b: Vector2): bool {. - importc: "godot_vector2_operator_less", header: "godot_vector2.h".} -proc `-`*(self: Vector2): Vector2 {. - importc: "godot_vector2_operator_neg", header: "godot_vector2.h".} +proc `==`*(self, other: Vector2): bool {.inline, noinit.} = + self.x == other.x and self.y == other.y -proc `x=`*(self: var Vector2; x: float32) {. - importc: "godot_vector2_set_x", header: "godot_vector2.h".} -proc `y=`*(self: var Vector2; y: float32) {. - importc: "godot_vector2_set_y", header: "godot_vector2.h".} -proc x*(self: Vector2): float32 {. - importc: "godot_vector2_get_x", header: "godot_vector2.h".} -proc y*(self: Vector2): float32 {. - importc: "godot_vector2_get_y", header: "godot_vector2.h".} +proc `<`*(self, other: Vector2): bool {.inline, noinit.} = + if self.x == other.x: + self.y < other.y + else: + self.x < other.x + +proc `>`*(self, other: Vector2): bool {.inline, noinit.} = + if self.x == other.x: + self.y > other.y + else: + self.x > other.x + +proc `-`*(self: Vector2): Vector2 {.inline, noinit.} = + Vector2(x: -self.x, y: -self.y) + +proc length*(self: Vector2): float32 {.inline, noinit.} = + sqrt(self.x * self.x + self.y * self.y) + +proc lengthSquared*(self: Vector2): float32 {.inline, noinit.} = + self.x * self.x + self.y * self.y + +proc normalize*(self: var Vector2) {.inline.} = + var len = self.x * self.x + self.y * self.y + if len != 0: + len = sqrt(len) + self.x /= len + self.y /= len + +proc normalized*(self: Vector2): Vector2 {.inline, noinit.} = + result = self + result.normalize() + +proc angle*(self: Vector2): float32 {.inline, noinit.} = + arctan2(self.y, self.x) + +proc isNormalized*(self: Vector2): bool {.inline, noinit.} = + isEqualApprox(self.lengthSquared(), 1.0) + +proc distanceTo*(self, to: Vector2): float32 {.inline, noinit.} = + sqrt((self.x - to.x) * (self.x - to.x) + (self.y - to.y) * (self.y - to.y)) + +proc distanceSquaredTo*(self, to: Vector2): float32 {.inline, noinit.} = + (self.x - to.x) * (self.x - to.x) + (self.y - to.y) * (self.y - to.y) + +proc dot*(a, b: Vector2): float32 {.inline, noinit.} = + a.x * b.x + a.y * b.y + +proc cross*(a, b: Vector2): float32 {.inline, noinit.} = + a.x * b.y - a.y * b.x + +proc cross*(self: Vector2, scalar: float32): Vector2 {.inline, noinit.} = + Vector2(x: scalar * self.y, y: -scalar * self.x) + +proc angleTo*(self, to: Vector2): float32 {.noinit.} = + arctan2(cross(self, to), dot(self, to)) + +proc angleToPoint*(self, to: Vector2): float32 {.inline, noinit.} = + arctan2(self.y - to.y, self.x - to.x) + +proc floor*(self: Vector2): Vector2 {.inline, noinit.} = + Vector2(x: floor(self.x), y: floor(self.y)) + +proc planeProject*(self: Vector2, d: float32, + vec: Vector2): Vector2 {.noinit.} = + vec - self * (self.dot(vec) - d) + +proc project*(self, other: Vector2): Vector2 {.noinit.} = + self * (other.dot(self) / self.dot(self)) + +proc lerp*(self, b: Vector2; t: float32): Vector2 {.inline, noinit.} = + result = self + result.x += t * (b.x - self.x) + result.y += t * (b.y - self.y) + +proc cubicInterpolate*(self, b, preA, postB: Vector2; + t: float32): Vector2 {.noinit.} = + let p0 = preA + let p1 = self + let p2 = b + let p3 = postB + + let t2 = t * t + let t3 = t2 * t + + result = 0.5'f32 * ((p1 * 2.0'f32)) + + (-p0 + p2) * t + + (2.0 * p0 - 5.0 * p1 + 4 * p2 - p3) * t2 + + (-p0 + 3.0 * p1 - 3.0 * p2 + p3) * t3 + +proc setRotation*(self: var Vector2, radians: float32) {.inline, noinit.} = + self.x = cos(radians) + self.y = sin(radians) + +proc rotated*(self: Vector2; phi: float32): Vector2 {.inline, noinit.} = + result.setRotation(phi) + result *= self.length() + +proc tangent*(self: Vector2): Vector2 {.inline, noinit.} = + Vector2(x: self.y, y: -self.x) + +proc snapped*(self: Vector2; by: Vector2): Vector2 {.inline, noinit.} = + Vector2(x: stepify(self.x, by.x), y: stepify(self.y, by.y)) + +proc aspect*(self: Vector2): float32 {.inline, noinit.} = + self.x / self.y + +proc slide*(self, n: Vector2): Vector2 {.noinit.} = + when not defined(release): + if not n.isNormalized(): + printError("Normal not normalized in slide. " & getStackTrace()) + return vec2() + result = self - n * self.dot(n) + +proc reflect*(self, n: Vector2): Vector2 {.noinit.} = + when not defined(release): + if not n.isNormalized(): + printError("Normal not normalized in bounce. " & getStackTrace()) + return vec2() + result = 2.0 * n * self.dot(n) - self + +proc bounce*(self, n: Vector2): Vector2 {.inline, noinit.} = + -self.reflect(n) + +proc abs*(self: Vector2): Vector2 {.inline, noinit.} = + Vector2(x: abs(self.x), y: abs(self.y)) + +proc clamped*(self: Vector2; length: float32): Vector2 {.noinit.} = + let len = self.length() + result = self + if len > 0 and length < len: + result /= len + result *= length + +proc moveToward*(vFrom, to: Vector2, delta: float32): Vector2 = + let + vd = to - vFrom + vLen = vd.length + + if vLen <= delta or vLen < EPSILON: + result = to + else: + result = vFrom + (vd / vLen) * delta + +{.pop.} # stackTrace: off diff --git a/godot/core/vector3.nim b/godot/core/vector3.nim index 79492eb..ed2903a 100644 --- a/godot/core/vector3.nim +++ b/godot/core/vector3.nim @@ -1,148 +1,254 @@ -# Copyright (c) 2017 Xored Software, Inc. +# Copyright (c) 2018 Xored Software, Inc. -type - Vector3* {.importc: "godot_vector3", header: "godot_vector3.h", - byref.} = object +import math, hashes +import godotbase, godotcoretypes -import godotbase, basis, strings +const EPSILON = 0.00001'f32 -type - Vector3Axis {.importc: "godot_vector3_axis", header: "godot_vector3.h", - size: sizeof(cint), pure.} = enum - X, - Y, - Z +{.push stackTrace: off.} -proc initVector3*(dest: var Vector3; x, y, z: float32) {. - importc: "godot_vector3_new", header: "godot_vector3.h".} +proc vec3*(): Vector3 {.inline.} = + Vector3() proc vec3*(x, y, z: float32): Vector3 {.inline.} = - initVector3(result, x, y, z) + Vector3(x: x, y: y, z: z) -proc toGodotString*(self: Vector3): GodotString {. - importc: "godot_vector3_as_string", header: "godot_vector3.h".} proc `$`*(self: Vector3): string {.inline.} = - $self.toGodotString() + result = newStringOfCap(40) + result.add('(') + result.add($self.x) + result.add(", ") + result.add($self.y) + result.add(", ") + result.add($self.z) + result.add(')') -proc minAxis*(self: Vector3): cint {. - importc: "godot_vector3_min_axis", header: "godot_vector3.h".} -proc maxAxis*(self: Vector3): cint {. - importc: "godot_vector3_max_axis", header: "godot_vector3.h".} -proc length*(self: Vector3): float32 {. - importc: "godot_vector3_length", header: "godot_vector3.h".} -proc lengthSquared*(self: Vector3): float32 {. - importc: "godot_vector3_length_squared", header: "godot_vector3.h".} -proc isNormalized*(self: Vector3): bool {. - importc: "godot_vector3_is_normalized", header: "godot_vector3.h".} -proc normalized*(self: Vector3): Vector3 {. - importc: "godot_vector3_normalized", header: "godot_vector3.h".} -proc inverse*(self: Vector3): Vector3 {. - importc: "godot_vector3_inverse", header: "godot_vector3.h".} -proc snapped*(self: Vector3; by: float32): Vector3 {. - importc: "godot_vector3_snapped", header: "godot_vector3.h".} -proc rotated*(self: Vector3; axis: Vector3; - phi: float32): Vector3 {. - importc: "godot_vector3_rotated", header: "godot_vector3.h".} -proc lerp*(self: Vector3; b: Vector3; t: float32): Vector3 {. - importc: "godot_vector3_linear_interpolate", header: "godot_vector3.h".} -proc cubicInterpolate*(self, b, preA, postB: Vector3; - t: float32): Vector3 {. - importc: "godot_vector3_cubic_interpolate", header: "godot_vector3.h".} -proc dot*(a, b: Vector3): float32 {. - importc: "godot_vector3_dot", header: "godot_vector3.h".} -proc cross*(a, b: Vector3): Vector3 {. - importc: "godot_vector3_cross", header: "godot_vector3.h".} -proc outer*(a, b: Vector3): Basis {. - importc: "godot_vector3_outer", header: "godot_vector3.h".} -proc toDiagonalMatrix*(self: Vector3): Basis {. - importc: "godot_vector3_to_diagonal_matrix", header: "godot_vector3.h".} -proc abs*(self: Vector3): Vector3 {. - importc: "godot_vector3_abs", header: "godot_vector3.h".} -proc floor*(self: Vector3): Vector3 {. - importc: "godot_vector3_floor", header: "godot_vector3.h".} -proc ceil*(self: Vector3): Vector3 {. - importc: "godot_vector3_ceil", header: "godot_vector3.h".} -proc distanceTo*(a, b: Vector3): float32 {. - importc: "godot_vector3_distance_to", header: "godot_vector3.h".} -proc distanceSquaredTo*(a, b: Vector3): float32 {. - importc: "godot_vector3_distance_squared_to", header: "godot_vector3.h".} -proc angleTo*(self, to: Vector3): float32 {. - importc: "godot_vector3_angle_to", header: "godot_vector3.h".} -proc slide*(self, n: Vector3): Vector3 {. - importc: "godot_vector3_slide", header: "godot_vector3.h".} -proc bounce*(self, n: Vector3): Vector3 {. - importc: "godot_vector3_bounce", header: "godot_vector3.h".} -proc reflect*(self, b: Vector3): Vector3 {. - importc: "godot_vector3_reflect", header: "godot_vector3.h".} +proc hash*(self: Vector3): Hash {.inline, noinit.} = + !$(self.x.hash() !& self.y.hash() !& self.z.hash()) + +proc `+`*(a, b: Vector3): Vector3 {.inline.} = + result.x = a.x + b.x + result.y = a.y + b.y + result.z = a.z + b.z -proc `+`*(a, b: Vector3): Vector3 {. - importc: "godot_vector3_operator_add", header: "godot_vector3.h".} proc `+=`*(a: var Vector3, b: Vector3) {.inline.} = - a = a + b + a.x += b.x + a.y += b.y + a.z += b.z + +proc `-`*(a, b: Vector3): Vector3 {.inline.} = + result.x = a.x - b.x + result.y = a.y - b.y + result.z = a.z - b.z -proc `-`*(a, b: Vector3): Vector3 {. - importc: "godot_vector3_operator_substract", header: "godot_vector3.h".} proc `-=`*(a: var Vector3, b: Vector3) {.inline.} = - a = a - b + a.x -= b.x + a.y -= b.y + a.z -= b.z + +proc `*`*(a, b: Vector3): Vector3 {.inline.} = + result.x = a.x * b.x + result.y = a.y * b.y + result.z = a.z * b.z -proc `*`*(a, b: Vector3): Vector3 {. - importc: "godot_vector3_operator_multiply_vector", - header: "godot_vector3.h".} proc `*=`*(a: var Vector3, b: Vector3) {.inline.}= - a = a * b + a.x *= b.x + a.y *= b.y + a.z *= b.z + +proc `*`*(a: Vector3; b: float32): Vector3 {.inline.} = + result.x = a.x * b + result.y = a.y * b + result.z = a.z * b + +proc `*`*(b: float32; a: Vector3): Vector3 {.inline.} = + a * b -proc `*`*(self: Vector3; b: float32): Vector3 {. - importc: "godot_vector3_operator_multiply_scalar", - header: "godot_vector3.h".} proc `*=`*(a: var Vector3; b: float32) {.inline.} = - a = a * b + a.x *= b + a.y *= b + a.z *= b + +proc `/`*(a, b: Vector3): Vector3 = + result.x = a.x / b.x + result.y = a.y / b.y + result.z = a.z / b.z -proc `/`*(a, b: Vector3): Vector3 {. - importc: "godot_vector3_operator_divide_vector", - header: "godot_vector3.h".} proc `/=`*(a: var Vector3; b: Vector3) {.inline.} = - a = a / b + a.x /= b.x + a.y /= b.y + a.z /= b.z + +proc `/`*(a: Vector3; b: float32): Vector3 = + result.x = a.x / b + result.y = a.y / b + result.z = a.z / b -proc `/`*(self: Vector3; b: float32): Vector3 {. - importc: "godot_vector3_operator_divide_scalar", - header: "godot_vector3.h".} proc `/=`*(a: var Vector3; b: float32) {.inline.} = - a = a / b + a.x /= b + a.y /= b + a.z /= b -proc `==`*(a, b: Vector3): bool {. - importc: "godot_vector3_operator_equal", header: "godot_vector3.h".} -proc `<`*(a, b: Vector3): bool {. - importc: "godot_vector3_operator_less", header: "godot_vector3.h".} -proc `-`*(self: Vector3): Vector3 {. - importc: "godot_vector3_operator_neg", header: "godot_vector3.h".} +proc `==`*(a, b: Vector3): bool {.inline.} = + a.x == b.x and a.y == b.y and a.z == b.z -proc setAxis(self: var Vector3; axis: Vector3Axis; - val: float32) {. - importc: "godot_vector3_set_axis", header: "godot_vector3.h".} -proc getAxis(self: Vector3; axis: Vector3Axis): float32 {. - importc: "godot_vector3_get_axis", header: "godot_vector3.h".} +proc `<`*(a, b: Vector3): bool = + if a.x == b.x: + if a.y == b.y: + return a.z < b.z + return a.y < b.y + return a.x < b.x -proc `[]`(self: Vector3, idx: range[0..2]): float32 {.inline.} = - self.getAxis(Vector3Axis(idx)) +proc `-`*(self: Vector3): Vector3 = + result.x = -self.x + result.y = -self.y + result.z = -self.z -proc `[]=`(self: var Vector3, idx: range[0..2], - val: float32): float32 {.inline.} = - self.setAxis(Vector3Axis(idx), val) +proc `[]`*(self: Vector3, idx: range[0..2]): float32 {.inline.} = + cast[array[3, float32]](self)[idx] -proc x*(self: Vector3): float32 {.inline.} = - self.getAxis(Vector3Axis.X) +proc `[]`*(self: var Vector3, idx: range[0..2]): var float32 {.inline.} = + cast[ptr array[3, float32]](addr self)[][idx] -proc `x=`*(self: var Vector3, val: float32) {.inline.} = - self.setAxis(Vector3Axis.X, val) +proc `[]=`*(self: var Vector3, idx: range[0..2], + val: float32) {.inline.} = + case idx: + of 0: self.x = val + of 1: self.y = val + of 2: self.z = val -proc y*(self: Vector3): float32 {.inline.} = - self.getAxis(Vector3Axis.Y) +proc minAxis*(self: Vector3): int {.inline.} = + if self.x < self.y: + if self.x < self.z: 0 else: 2 + else: + if self.y < self.z: 1 else: 2 -proc `y=`*(self: var Vector3, val: float32) {.inline.} = - self.setAxis(Vector3Axis.Y, val) +proc maxAxis*(self: Vector3): int {.inline.} = + if self.x < self.y: + if self.y < self.z: 2 else: 1 + else: + if self.x < self.z: 2 else: 0 -proc z*(self: Vector3): float32 {.inline.} = - self.getAxis(Vector3Axis.Z) +proc length*(self: Vector3): float32 {.inline.} = + let x2 = self.x * self.x + let y2 = self.y * self.y + let z2 = self.z * self.z -proc `z=`*(self: var Vector3, val: float32) {.inline.} = - self.setAxis(Vector3Axis.Z, val) + result = sqrt(x2 + y2 + z2) + +proc lengthSquared*(self: Vector3): float32 {.inline.} = + let x2 = self.x * self.x + let y2 = self.y * self.y + let z2 = self.z * self.z + + result = x2 + y2 + z2 + +proc normalize*(self: var Vector3) {.inline.} = + let len = self.length() + if len == 0: + self.x = 0 + self.y = 0 + self.z = 0 + else: + self.x /= len + self.y /= len + self.z /= len + +proc normalized*(self: Vector3): Vector3 {.inline.} = + result = self + result.normalize() + +proc isNormalized*(self: Vector3): bool {.inline.} = + self.lengthSquared().isEqualApprox(1.0'f32) + +proc zero*(self: var Vector3) {.inline.} = + self.x = 0 + self.y = 0 + self.z = 0 + +proc inverse*(self: Vector3): Vector3 {.inline.} = + vec3(1.0'f32 / self.x, 1.0'f32 / self.y, 1.0'f32 / self.z) + +proc cross*(self, other: Vector3): Vector3 {.inline.} = + vec3( + self.y * other.z - self.z * other.y, + self.z * other.x - self.x * other.z, + self.x * other.y - self.y * other.x) + +proc dot*(self, other: Vector3): float32 {.inline.} = + self.x * other.x + self.y * other.y + self.z * other.z + +proc abs*(self: Vector3): Vector3 {.inline.} = + vec3(abs(self.x), abs(self.y), abs(self.z)) + +proc sign*(self: Vector3): Vector3 {.inline.} = + vec3(sign(self.x), sign(self.y), sign(self.z)) + +proc floor*(self: Vector3): Vector3 {.inline.} = + vec3(floor(self.x), floor(self.y), floor(self.z)) + +proc ceil*(self: Vector3): Vector3 {.inline.} = + vec3(ceil(self.x), ceil(self.y), ceil(self.z)) + +proc lerp*(self: Vector3, other: Vector3, t: float32): Vector3 {.inline.} = + vec3( + self.x + t * (other.x - self.x), + self.y + t * (other.y - self.y), + self.z + t * (other.z - self.z) + ) + +proc distanceTo*(self, other: Vector3): float32 {.inline.} = + (other - self).length() + +proc distanceSquaredTo*(self, other: Vector3): float32 {.inline.} = + (other - self).lengthSquared() + +proc angleTo*(self, other: Vector3): float32 {.inline.} = + arctan2(self.cross(other).length(), self.dot(other)) + +proc slide*(self, n: Vector3): Vector3 {.inline.} = + assert(n.isNormalized()) + result = self - n * self.dot(n) + +proc reflect*(self, n: Vector3): Vector3 {.inline.} = + assert(n.isNormalized()) + result = 2.0'f32 * n * self.dot(n) - self + +proc bounce*(self, n: Vector3): Vector3 {.inline.} = + -self.reflect(n) + +proc snap*(self: var Vector3, other: Vector3) = + self.x = stepify(self.x, other.x) + self.y = stepify(self.y, other.y) + self.z = stepify(self.z, other.z) + +proc snapped*(self: Vector3, other: Vector3): Vector3 = + result = self + result.snap(other) + +proc cubicInterpolate*(self, b, preA, postB: Vector3; + t: float32): Vector3 = + let p0 = preA + let p1 = self + let p2 = b + let p3 = postB + + let t2 = t * t + let t3 = t2 * t + + result = 0.5 * ((p1 * 2.0) + + (-p0 + p2) * t + + (2.0 * p0 - 5.0 * p1 + 4 * p2 - p3) * t2 + + (-p0 + 3.0 * p1 - 3.0 * p2 + p3) * t3) + +proc moveToward*(vFrom, to: Vector3, delta: float32): Vector3 = + let + vd = to - vFrom + vLen = vd.length + + if vLen <= delta or vLen < EPSILON: + result = to + else: + result = vFrom + (vd / vLen) * delta + +{.pop.} # stackTrace: off \ No newline at end of file diff --git a/godot/gdnativeapi.nim b/godot/gdnativeapi.nim new file mode 100644 index 0000000..bb05425 --- /dev/null +++ b/godot/gdnativeapi.nim @@ -0,0 +1,3617 @@ +# Copyright 2018 Xored Software, Inc. + +import internal/godotinternaltypes, core/godotcoretypes, macros + +type + ColorData* {.byref.} = object + data: array[16, uint8] + + Vector3Data* {.byref.} = object + data: array[12, uint8] + + Vector2Data* {.byref.} = object + data: array[8, uint8] + + PlaneData* {.byref.} = object + data: array[16, uint8] + + BasisData* {.byref.} = object + data: array[36, uint8] + + QuatData* {.byref.} = object + data: array[16, uint8] + + AABBData* {.byref.} = object + data: array[24, uint8] + + Rect2Data* {.byref.} = object + data: array[16, uint8] + + Transform2DData* {.byref.} = object + data: array[24, uint8] + + TransformData* {.byref.} = object + data: array[48, uint8] + + GDNativeAPIType {.size: sizeof(cuint).} = enum + GDNativeCore, + GDNativeExtNativeScript, + GDNativeExtPluginScript, + GDNativeExtNativeARVR + + GDNativeAPIHeader = object + typ: cuint + version: GDNativeAPIVersion + next: pointer + + GDNativeNativeScriptAPI1 = object + typ: cuint + version: GDNativeAPIVersion + next: pointer + nativeScriptRegisterClass: proc (gdnativeHandle: pointer, + name, base: cstring, + createFunc: GodotInstanceCreateFunc, + destroyFunc: GodotInstanceDestroyFunc) + {.noconv, raises: [], gcsafe, tags: [], + locks: 0.} + nativeScriptRegisterToolClass: proc (gdnativeHandle: pointer, + name, base: cstring, + createFunc: GodotInstanceCreateFunc, + destroyFunc: GodotInstanceDestroyFunc) + {.noconv, raises: [], gcsafe, tags: [], + locks: 0.} + nativeScriptRegisterMethod: proc (gdnativeHandle: pointer, + name, functionName: cstring, + attr: GodotMethodAttributes, + meth: GodotInstanceMethod) + {.noconv, raises: [], gcsafe, tags: [], + locks: 0.} + nativeScriptRegisterProperty: proc (gdnativeHandle: pointer, + name, path: cstring, + attr: ptr GodotPropertyAttributes, + setFunc: GodotPropertySetFunc, + getFunc: GodotPropertyGetFunc) + {.noconv, raises: [], gcsafe, tags: [], + locks: 0.} + nativeScriptRegisterSignal: proc (gdnativeHandle: pointer, name: cstring, + signal: GodotSignal) + {.noconv, raises: [], gcsafe, tags: [], + locks: 0.} + nativeScriptGetUserdata: proc (obj: ptr GodotObject): pointer + {.noconv, raises: [], gcsafe, tags: [], + locks: 0.} + + GDNativeCoreAPI1 = object + typ: cuint + version: GDNativeAPIVersion + next: pointer + numExtensions: cuint + extensions: ptr array[100_000, pointer] + + # Color API + colorNewRGBA: proc (dest: var Color, r, g, b, a: float32) + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + colorNewRGB: proc (dest: var Color, r, g, b: float32) + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + colorGetR: proc (self: Color): float32 + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + colorSetR: proc (self: var Color, r: float32) + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + colorGetG: proc (self: Color): float32 + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + colorSetG: proc (self: var Color, g: float32) + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + colorGetB: proc (self: Color): float32 + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + colorSetB: proc (self: var Color, b: float32) + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + colorGetA: proc (self: Color): float32 + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + colorSetA: proc (self: var Color, a: float32) + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + colorGetH: proc (self: Color): float32 + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + colorGetS: proc (self: Color): float32 + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + colorGetV: proc (self: Color): float32 + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + colorAsString: proc (self: Color): GodotString + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + colorToRGBA32: proc (self: Color): cint + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + colorAsARGB32: proc (self: Color): cint + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + colorGray: proc (self: Color): float32 + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + colorInverted: proc (self: Color): ColorData + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + colorContrasted: proc (self: Color): ColorData + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + colorLinearInterpolate: proc (self, other: Color, t: float32): ColorData + {.noconv, raises: [], gcsafe, tags: [], + locks: 0.} + colorBlend: proc (self, other: Color): ColorData + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + colorToHtml: proc (self: Color, withAlpha: bool): GodotString + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + colorOperatorEqual: proc (self, other: Color): bool + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + colorOperatorLess: proc (self, other: Color): bool + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + + # Vector2 API + vector2New: proc (dest: var Vector2, x, y: float32) + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + vector2AsString: proc (self: Vector2): GodotString + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + vector2Normalized: proc (self: Vector2): Vector2Data + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + vector2Length: proc (self: Vector2): float32 + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + vector2Angle: proc (self: Vector2): float32 + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + vector2LengthSquared: proc (self: Vector2): float32 + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + vector2IsNormalized: proc (self: Vector2): bool + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + vector2DistanceTo: proc (self, to: Vector2): float32 + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + vector2DistanceSquaredTo: proc (self, to: Vector2): float32 + {.noconv, raises: [], gcsafe, tags: [], + locks: 0.} + vector2AngleTo: proc (self, to: Vector2): float32 + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + vector2AngleToPoint: proc (self, to: Vector2): float32 + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + vector2LinearInterpolate: proc (self, b: Vector2, t: float32): Vector2Data + {.noconv, raises: [], gcsafe, tags: [], + locks: 0.} + vector2CubicInterpolate: proc (self, b, preA, postB: Vector2, + t: float32): Vector2Data + {.noconv, raises: [], gcsafe, tags: [], + locks: 0.} + vector2Rotated: proc (self: Vector2, phi: float32): Vector2Data + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + vector2Tangent: proc (self: Vector2): Vector2Data + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + vector2Floor: proc (self: Vector2): Vector2Data + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + vector2Snapped: proc (self, by: Vector2): Vector2Data + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + vector2Aspect: proc (self: Vector2): float32 + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + vector2Dot: proc (self, other: Vector2): float32 + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + vector2Slide: proc (self, n: Vector2): Vector2Data + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + vector2Bounce: proc (self, n: Vector2): Vector2Data + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + vector2Reflect: proc (self, n: Vector2): Vector2Data + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + vector2Abs: proc (self: Vector2): Vector2Data + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + vector2Clamped: proc (self: Vector2, length: float32): Vector2Data + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + vector2OperatorAdd: proc (self, other: Vector2): Vector2Data + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + vector2OperatorSubtract: proc (self, other: Vector2): Vector2Data + {.noconv, raises: [], gcsafe, tags: [], + locks: 0.} + vector2OperatorMultiplyVector: proc (self, other: Vector2): Vector2Data + {.noconv, raises: [], gcsafe, tags: [], + locks: 0.} + vector2OperatorMultiplyScalar: proc (self: Vector2, scalar: float32): Vector2Data + {.noconv, raises: [], gcsafe, tags: [], + locks: 0.} + vector2OperatorDivideVector: proc (self, other: Vector2): Vector2Data + {.noconv, raises: [], gcsafe, tags: [], + locks: 0.} + vector2OperatorDivideScalar: proc (self: Vector2, scalar: float32): Vector2Data + {.noconv, raises: [], gcsafe, tags: [], + locks: 0.} + vector2OperatorEqual: proc (self, other: Vector2): bool + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + vector2OperatorLess: proc (self, other: Vector2): bool + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + vector2OperatorNeg: proc (self: Vector2): Vector2Data + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + vector2SetX: pointer + vector2SetY: pointer + vector2GetX: pointer + vector2GetY: pointer + + # Quat API + quatNew: proc (dest: var Quat, x, y, z, w: float32) + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + quatNewWithAxisAngle: proc (dest: Quat, axis: Vector3, + angle: float32) + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + quatGetX: proc (self: Quat): float32 + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + quatSetX: proc (self: var Quat, val: float32) + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + quatGetY: proc (self: Quat): float32 + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + quatSetY: proc (self: var Quat, val: float32) + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + quatGetZ: proc (self: Quat): float32 + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + quatSetZ: proc (self: var Quat, val: float32) + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + quatGetW: proc (self: Quat): float32 + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + quatSetW: proc (self: var Quat, val: float32) + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + quatAsString: proc (self: Quat): GodotString + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + quatLength: proc (self: Quat): float32 + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + quatLengthSquared: proc (self: Quat): float32 + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + quatNormalized: proc (self: Quat): QuatData + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + quatIsNormalized: proc (self: Quat): bool + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + quatInverse: proc (self: Quat): QuatData + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + quatDot: proc (self, other: Quat): float32 + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + quatXform: proc (self: Quat, v: Vector3): Vector3Data + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + quatSlerp: proc (self, other: Quat, t: float32): QuatData + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + quatSlerpni: proc (self, other: Quat, t: float32): QuatData + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + quatCubicSlerp: proc (self, other, preA, postB: Quat, t: float32): QuatData + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + quatOperatorMultiply: proc (self: Quat, b: float32): QuatData + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + quatOperatorAdd: proc (self, other: Quat): QuatData + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + quatOperatorSubtract: proc (self, other: Quat): QuatData + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + quatOperatorDivide: proc (self: Quat, divider: float32): QuatData + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + quatOperatorEqual: proc (self, other: Quat): bool + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + quatOperatorNeg: proc (self: Quat): QuatData + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + + # Basis API + basisNewWithRows: pointer + basisNewWithAxisAndAngle: pointer + basisNewWithEuler: pointer + basisAsString: pointer + basisInverse: pointer + basisTransposed: pointer + basisOrthonormalized: pointer + basisDeterminant: pointer + basisRotated: pointer + basisScaled: pointer + basisGetScale: pointer + basisGetEuler: pointer + basisTdotx: pointer + basisTdoty: pointer + basisTdotz: pointer + basisXform: pointer + basisXformInv: pointer + basisGetOrthogonalIndex: pointer + basisNew: pointer + basisNewWithEulerQuat: pointer + basisGetElements: pointer + basisGetAxis: pointer + basisSetAxis: pointer + basisGetRow: pointer + basisSetRow: pointer + basisOperatorEqual: pointer + basisOperatorAdd: pointer + basisOperatorSubstract: pointer + basisOperatorMultiplyVector: pointer + basisOperatorMultiplyScalar: pointer + + # Vector3 API + vector3New: pointer + vector3AsString: pointer + vector3MinAxis: pointer + vector3MaxAxis: pointer + vector3Length: pointer + vector3Length_squared: pointer + vector3IsNormalized: pointer + vector3Normalized: pointer + vector3Inverse: pointer + vector3Snapped: pointer + vector3Rotated: pointer + vector3LinearInterpolate: pointer + vector3CubicInterpolate: pointer + vector3Dot: pointer + vector3Cross: pointer + vector3Outer: pointer + vector3ToDiagonalMatrix: pointer + vector3Abs: pointer + vector3Floor: pointer + vector3Ceil: pointer + vector3DistanceTo: pointer + vector3DistanceSquaredTo: pointer + vector3AngleTo: pointer + vector3Slide: pointer + vector3Bounce: pointer + vector3Reflect: pointer + vector3OperatorAdd: pointer + vector3OperatorSubstract: pointer + vector3OperatorMultiplyVector: pointer + vector3OperatorMultiplyScalar: pointer + vector3OperatorDivideVector: pointer + vector3OperatorDivideScalar: pointer + vector3OperatorEqual: pointer + vector3OperatorLess: pointer + vector3OperatorNeg: pointer + vector3SetAxis: pointer + vector3GetAxis: pointer + + # PoolByteArray API + poolByteArrayNew: proc (dest: var GodotPoolByteArray) + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + poolByteArrayNewCopy: proc (dest: var GodotPoolByteArray, + src: GodotPoolByteArray) + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + poolByteArrayNewWithArray: proc (dest: var GodotPoolByteArray, + src: GodotArray) + {.noconv, raises: [], gcsafe, tags: [], + locks: 0.} + poolByteArrayAppend: proc (self: var GodotPoolByteArray, + val: byte) + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + poolByteArrayAppendArray: proc (self: var GodotPoolByteArray, + arr: GodotPoolByteArray) + {.noconv, raises: [], gcsafe, tags: [], + locks: 0.} + poolByteArrayInsert: proc (self: var GodotPoolByteArray, + idx: cint, val: byte): Error + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + poolByteArrayInvert: proc (self: var GodotPoolByteArray) + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + poolByteArrayPushBack: proc (self: var GodotPoolByteArray, val: byte) + {.noconv, raises: [], gcsafe, tags: [], + locks: 0.} + poolByteArrayRemove: proc (self: var GodotPoolByteArray, idx: cint) + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + poolByteArrayResize: proc (self: var GodotPoolByteArray, size: cint) + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + poolByteArrayRead: proc (self: GodotPoolByteArray): ptr GodotPoolByteArrayReadAccess + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + poolByteArrayWrite: proc (self: var GodotPoolByteArray): ptr GodotPoolByteArrayWriteAccess + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + poolByteArraySet: proc (self: var GodotPoolByteArray, idx: cint, data: byte) + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + poolByteArrayGet: proc (self: GodotPoolByteArray, idx: cint): byte + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + poolByteArraySize: proc (self: GodotPoolByteArray): cint + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + poolByteArrayDestroy: proc (self: GodotPoolByteArray) + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + + # PoolIntArray API + poolIntArrayNew: proc (dest: var GodotPoolIntArray) + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + poolIntArrayNewCopy: proc (dest: var GodotPoolIntArray, + src: GodotPoolIntArray) + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + poolIntArrayNewWithArray: proc (dest: var GodotPoolIntArray, src: GodotArray) + {.noconv, raises: [], gcsafe, tags: [], + locks: 0.} + poolIntArrayAppend: proc (self: var GodotPoolIntArray, val: cint) + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + poolIntArrayAppendArray: proc (self: var GodotPoolIntArray, + arr: GodotPoolIntArray) + {.noconv, raises: [], gcsafe, tags: [], + locks: 0.} + poolIntArrayInsert: proc (self: var GodotPoolIntArray, idx: cint, + val: cint): Error + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + poolIntArrayInvert: proc (self: var GodotPoolIntArray) + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + poolIntArrayPushBack: proc (self: var GodotPoolIntArray, val: cint) + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + poolIntArrayRemove: proc (self: var GodotPoolIntArray, idx: cint) + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + poolIntArrayResize: proc (self: var GodotPoolIntArray, size: cint) + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + poolIntArrayRead: proc (self: GodotPoolIntArray): ptr GodotPoolIntArrayReadAccess + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + poolIntArrayWrite: proc (self: var GodotPoolIntArray): ptr GodotPoolIntArrayWriteAccess + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + poolIntArraySet: proc (self: var GodotPoolIntArray, idx: cint, data: cint) + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + poolIntArrayGet: proc (self: GodotPoolIntArray, idx: cint): cint + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + poolIntArraySize: proc (self: GodotPoolIntArray): cint + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + poolIntArrayDestroy: proc (self: GodotPoolIntArray) + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + + # PoolRealArray API + poolRealArrayNew: proc (dest: var GodotPoolRealArray) + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + poolRealArrayNewCopy: proc (dest: var GodotPoolRealArray, + src: GodotPoolRealArray) + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + poolRealArrayNewWithArray: proc (dest: var GodotPoolRealArray, + src: GodotArray) + {.noconv, raises: [], gcsafe, tags: [], + locks: 0.} + poolRealArrayAppend: proc (self: var GodotPoolRealArray, val: float32) + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + poolRealArrayAppendArray: proc (self: var GodotPoolRealArray, + arr: GodotPoolRealArray) + {.noconv, raises: [], gcsafe, tags: [], + locks: 0.} + poolRealArrayInsert: proc (self: var GodotPoolRealArray, + idx: cint, val: float32): Error + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + poolRealArrayInvert: proc (self: var GodotPoolRealArray) + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + poolRealArrayPushBack: proc (self: var GodotPoolRealArray, val: float32) + {.noconv, raises: [], gcsafe, tags: [], + locks: 0.} + poolRealArrayRemove: proc (self: var GodotPoolRealArray, idx: cint) + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + poolRealArrayResize: proc (self: var GodotPoolRealArray, size: cint) + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + poolRealArrayRead: proc (self: GodotPoolRealArray): ptr GodotPoolRealArrayReadAccess + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + poolRealArrayWrite: proc (self: var GodotPoolRealArray): ptr GodotPoolRealArrayWriteAccess + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + poolRealArraySet: proc (self: var GodotPoolRealArray, idx: cint, + data: float32) + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + poolRealArrayGet: proc (self: GodotPoolRealArray, idx: cint): float32 + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + poolRealArraySize: proc (self: GodotPoolRealArray): cint + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + poolRealArrayDestroy: proc (self: GodotPoolRealArray) + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + + # PoolStringArray API + poolStringArrayNew: proc (dest: var GodotPoolStringArray) + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + poolStringArrayNewCopy: proc (dest: var GodotPoolStringArray, + src: GodotPoolStringArray) + {.noconv, raises: [], gcsafe, tags: [], + locks: 0.} + poolStringArrayNewWithArray: proc (dest: var GodotPoolStringArray, + src: GodotArray) + {.noconv, raises: [], gcsafe, tags: [], + locks: 0.} + poolStringArrayAppend: proc (self: var GodotPoolStringArray, + val: GodotString) + {.noconv, raises: [], gcsafe, tags: [], + locks: 0.} + poolStringArrayAppendArray: proc (self: var GodotPoolStringArray, + arr: GodotPoolStringArray) + {.noconv, raises: [], gcsafe, tags: [], + locks: 0.} + poolStringArrayInsert: proc (self: var GodotPoolStringArray, + idx: cint, val: GodotString): Error + {.noconv, raises: [], gcsafe, tags: [], + locks: 0.} + poolStringArrayInvert: proc (self: var GodotPoolStringArray) + {.noconv, raises: [], gcsafe, tags: [], + locks: 0.} + poolStringArrayPushBack: proc (self: var GodotPoolStringArray, + val: GodotString) + {.noconv, raises: [], gcsafe, tags: [], + locks: 0.} + poolStringArrayRemove: proc (self: var GodotPoolStringArray, idx: cint) + {.noconv, raises: [], gcsafe, tags: [], + locks: 0.} + poolStringArrayResize: proc (self: var GodotPoolStringArray, size: cint) + {.noconv, raises: [], gcsafe, tags: [], + locks: 0.} + poolStringArrayRead: proc (self: GodotPoolStringArray): ptr GodotPoolStringArrayReadAccess + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + poolStringArrayWrite: proc (self: var GodotPoolStringArray): ptr GodotPoolStringArrayWriteAccess + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + poolStringArraySet: proc (self: var GodotPoolStringArray, idx: cint, + data: GodotString) + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + poolStringArrayGet: proc (self: GodotPoolStringArray, idx: cint): GodotString + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + poolStringArraySize: proc (self: GodotPoolStringArray): cint + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + poolStringArrayDestroy: proc (self: GodotPoolStringArray) + {.noconv, raises: [], gcsafe, tags: [], + locks: 0.} + + # PoolVector2 API + poolVector2ArrayNew: proc (dest: var GodotPoolVector2Array) + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + poolVector2ArrayNewCopy: proc (dest: var GodotPoolVector2Array, + src: GodotPoolVector2Array) + {.noconv, raises: [], gcsafe, tags: [], + locks: 0.} + poolVector2ArrayNewWithArray: proc (dest: var GodotPoolVector2Array, + src: GodotArray) + {.noconv, raises: [], gcsafe, tags: [], + locks: 0.} + poolVector2ArrayAppend: proc (self: var GodotPoolVector2Array, val: Vector2) + {.noconv, raises: [], gcsafe, tags: [], + locks: 0.} + poolVector2ArrayAppendArray: proc (self: var GodotPoolVector2Array, + arr: GodotPoolVector2Array) + {.noconv, raises: [], gcsafe, tags: [], + locks: 0.} + poolVector2ArrayInsert: proc (self: var GodotPoolVector2Array, idx: cint, + val: Vector2): Error + {.noconv, raises: [], gcsafe, tags: [], + locks: 0.} + poolVector2ArrayInvert: proc (self: var GodotPoolVector2Array) + {.noconv, raises: [], gcsafe, tags: [], + locks: 0.} + poolVector2ArrayPushBack: proc (self: var GodotPoolVector2Array, + val: Vector2) + {.noconv, raises: [], gcsafe, tags: [], + locks: 0.} + poolVector2ArrayRemove: proc (self: var GodotPoolVector2Array, idx: cint) + {.noconv, raises: [], gcsafe, tags: [], + locks: 0.} + poolVector2ArrayResize: proc (self: var GodotPoolVector2Array, size: cint) + {.noconv, raises: [], gcsafe, tags: [], + locks: 0.} + poolVector2ArrayRead: proc (self: GodotPoolVector2Array): ptr GodotPoolVector2ArrayReadAccess + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + poolVector2ArrayWrite: proc (self: var GodotPoolVector2Array): ptr GodotPoolVector2ArrayWriteAccess + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + poolVector2ArraySet: proc (self: var GodotPoolVector2Array, idx: cint, + data: Vector2) + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + poolVector2ArrayGet: proc (self: GodotPoolVector2Array, idx: cint): Vector2Data + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + poolVector2ArraySize: proc (self: GodotPoolVector2Array): cint + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + poolVector2ArrayDestroy: proc (self: GodotPoolVector2Array) + {.noconv, raises: [], gcsafe, tags: [], + locks: 0.} + + # PoolVector3 API + poolVector3ArrayNew: proc (dest: var GodotPoolVector3Array) + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + poolVector3ArrayNewCopy: proc (dest: var GodotPoolVector3Array, + src: GodotPoolVector3Array) + {.noconv, raises: [], gcsafe, tags: [], + locks: 0.} + poolVector3ArrayNewWithArray: proc (dest: var GodotPoolVector3Array, + src: GodotArray) + {.noconv, raises: [], gcsafe, tags: [], + locks: 0.} + poolVector3ArrayAppend: proc (self: var GodotPoolVector3Array, val: Vector3) + {.noconv, raises: [], gcsafe, tags: [], + locks: 0.} + poolVector3ArrayAppendArray: proc (self: var GodotPoolVector3Array, + arr: GodotPoolVector3Array) + {.noconv, raises: [], gcsafe, tags: [], + locks: 0.} + poolVector3ArrayInsert: proc (self: var GodotPoolVector3Array, idx: cint, + val: Vector3): Error + {.noconv, raises: [], gcsafe, tags: [], + locks: 0.} + poolVector3ArrayInvert: proc (self: var GodotPoolVector3Array) + {.noconv, raises: [], gcsafe, tags: [], + locks: 0.} + poolVector3ArrayPushBack: proc (self: var GodotPoolVector3Array, + val: Vector3) {.noconv, raises: [], gcsafe, + tags: [], locks: 0.} + poolVector3ArrayRemove: proc (self: var GodotPoolVector3Array, + idx: cint) {.noconv, raises: [], gcsafe, + tags: [], locks: 0.} + poolVector3ArrayResize: proc (self: var GodotPoolVector3Array, + size: cint) {.noconv, raises: [], gcsafe, + tags: [], locks: 0.} + poolVector3ArrayRead: proc (self: GodotPoolVector3Array): ptr GodotPoolVector3ArrayReadAccess + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + poolVector3ArrayWrite: proc (self: var GodotPoolVector3Array): ptr GodotPoolVector3ArrayWriteAccess + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + poolVector3ArraySet: proc (self: var GodotPoolVector3Array, idx: cint, + data: Vector3) {.noconv, raises: [], gcsafe, + tags: [], locks: 0.} + poolVector3ArrayGet: proc (self: GodotPoolVector3Array, idx: cint): Vector3Data + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + poolVector3ArraySize: proc (self: GodotPoolVector3Array): cint + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + poolVector3ArrayDestroy: proc (self: GodotPoolVector3Array) + {.noconv, raises: [], gcsafe, tags: [], + locks: 0.} + + # PoolColorArray API + poolColorArrayNew: proc (dest: var GodotPoolColorArray) + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + poolColorArrayNewCopy: proc (dest: var GodotPoolColorArray, + src: GodotPoolColorArray) + {.noconv, raises: [], gcsafe, tags: [], + locks: 0.} + poolColorArrayNewWithArray: proc (dest: var GodotPoolColorArray, + src: GodotArray) + {.noconv, raises: [], gcsafe, tags: [], + locks: 0.} + poolColorArrayAppend: proc (self: var GodotPoolColorArray, + val: Color) + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + poolColorArrayAppendArray: proc (self: var GodotPoolColorArray, + arr: GodotPoolColorArray) + {.noconv, raises: [], gcsafe, tags: [], + locks: 0.} + poolColorArrayInsert: proc (self: var GodotPoolColorArray, + idx: cint, val: Color): Error + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + poolColorArrayInvert: proc (self: var GodotPoolColorArray) + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + poolColorArrayPushBack: proc (self: var GodotPoolColorArray, val: Color) + {.noconv, raises: [], gcsafe, tags: [], + locks: 0.} + poolColorArrayRemove: proc (self: var GodotPoolColorArray, idx: cint) + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + poolColorArrayResize: proc (self: var GodotPoolColorArray, size: cint) + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + poolColorArrayRead: proc (self: GodotPoolColorArray): ptr GodotPoolColorArrayReadAccess + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + poolColorArrayWrite: proc (self: var GodotPoolColorArray): ptr GodotPoolColorArrayWriteAccess + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + poolColorArraySet: proc (self: var GodotPoolColorArray, idx: cint, + data: Color) + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + poolColorArrayGet: proc (self: GodotPoolColorArray, idx: cint): ColorData + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + poolColorArraySize: proc (self: GodotPoolColorArray): cint + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + poolColorArrayDestroy: proc (self: GodotPoolColorArray) + {.noconv, raises: [], gcsafe, tags: [], + locks: 0.} + + # Pool Array Read/Write Access API + + poolByteArrayReadAccessCopy: proc (self: ptr GodotPoolByteArrayReadAccess): ptr GodotPoolByteArrayReadAccess + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + poolByteArrayReadAccessPtr: proc (self: ptr GodotPoolByteArrayReadAccess): ptr byte + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + poolByteArrayReadAccessOperatorAssign: proc (self, other: ptr GodotPoolByteArrayReadAccess) + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + poolByteArrayReadAccessDestroy: proc (self: ptr GodotPoolByteArrayReadAccess) + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + + poolIntArrayReadAccessCopy: proc (self: ptr GodotPoolIntArrayReadAccess): ptr GodotPoolIntArrayReadAccess + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + poolIntArrayReadAccessPtr: proc (self: ptr GodotPoolIntArrayReadAccess): ptr cint + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + poolIntArrayReadAccessOperatorAssign: proc (self, other: ptr GodotPoolIntArrayReadAccess) + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + poolIntArrayReadAccessDestroy: proc (self: ptr GodotPoolIntArrayReadAccess) + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + + poolRealArrayReadAccessCopy: proc (self: ptr GodotPoolRealArrayReadAccess): ptr GodotPoolRealArrayReadAccess + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + poolRealArrayReadAccessPtr: proc (self: ptr GodotPoolRealArrayReadAccess): ptr float32 + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + poolRealArrayReadAccessOperatorAssign: proc (self, other: ptr GodotPoolRealArrayReadAccess) + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + poolRealArrayReadAccessDestroy: proc (self: ptr GodotPoolRealArrayReadAccess) + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + + poolStringArrayReadAccessCopy: proc (self: ptr GodotPoolStringArrayReadAccess): ptr GodotPoolStringArrayReadAccess + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + poolStringArrayReadAccessPtr: proc (self: ptr GodotPoolStringArrayReadAccess): ptr GodotString + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + poolStringArrayReadAccessOperatorAssign: proc (self, other: ptr GodotPoolStringArrayReadAccess) + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + poolStringArrayReadAccessDestroy: proc (self: ptr GodotPoolStringArrayReadAccess) + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + + poolVector2ArrayReadAccessCopy: proc (self: ptr GodotPoolVector2ArrayReadAccess): ptr GodotPoolVector2ArrayReadAccess + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + poolVector2ArrayReadAccessPtr: proc (self: ptr GodotPoolVector2ArrayReadAccess): ptr Vector2 + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + poolVector2ArrayReadAccessOperatorAssign: proc (self, other: ptr GodotPoolVector2ArrayReadAccess) + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + poolVector2ArrayReadAccessDestroy: proc (self: ptr GodotPoolVector2ArrayReadAccess) + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + + poolVector3ArrayReadAccessCopy: proc (self: ptr GodotPoolVector3ArrayReadAccess): ptr GodotPoolVector3ArrayReadAccess + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + poolVector3ArrayReadAccessPtr: proc (self: ptr GodotPoolVector3ArrayReadAccess): ptr Vector3 + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + poolVector3ArrayReadAccessOperatorAssign: proc (self, other: ptr GodotPoolVector3ArrayReadAccess) + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + poolVector3ArrayReadAccessDestroy: proc (self: ptr GodotPoolVector3ArrayReadAccess) + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + + poolColorArrayReadAccessCopy: proc (self: ptr GodotPoolColorArrayReadAccess): ptr GodotPoolColorArrayReadAccess + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + poolColorArrayReadAccessPtr: proc (self: ptr GodotPoolColorArrayReadAccess): ptr Color + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + poolColorArrayReadAccessOperatorAssign: proc (self, other: ptr GodotPoolColorArrayReadAccess) + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + poolColorArrayReadAccessDestroy: proc (self: ptr GodotPoolColorArrayReadAccess) + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + + poolByteArrayWriteAccessCopy: proc (self: ptr GodotPoolByteArrayWriteAccess): ptr GodotPoolByteArrayWriteAccess + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + poolByteArrayWriteAccessPtr: proc (self: ptr GodotPoolByteArrayWriteAccess): ptr byte + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + poolByteArrayWriteAccessOperatorAssign: proc (self, other: ptr GodotPoolByteArrayWriteAccess) + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + poolByteArrayWriteAccessDestroy: proc (self: ptr GodotPoolByteArrayWriteAccess) + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + + poolIntArrayWriteAccessCopy: proc (self: ptr GodotPoolIntArrayWriteAccess): ptr GodotPoolIntArrayWriteAccess + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + poolIntArrayWriteAccessPtr: proc (self: ptr GodotPoolIntArrayWriteAccess): ptr cint + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + poolIntArrayWriteAccessOperatorAssign: proc (self, other: ptr GodotPoolIntArrayWriteAccess) + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + poolIntArrayWriteAccessDestroy: proc (self: ptr GodotPoolIntArrayWriteAccess) + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + + poolRealArrayWriteAccessCopy: proc (self: ptr GodotPoolRealArrayWriteAccess): ptr GodotPoolRealArrayWriteAccess + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + poolRealArrayWriteAccessPtr: proc (self: ptr GodotPoolRealArrayWriteAccess): ptr float32 + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + poolRealArrayWriteAccessOperatorAssign: proc (self, other: ptr GodotPoolRealArrayWriteAccess) + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + poolRealArrayWriteAccessDestroy: proc (self: ptr GodotPoolRealArrayWriteAccess) + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + + poolStringArrayWriteAccessCopy: proc (self: ptr GodotPoolStringArrayWriteAccess): ptr GodotPoolStringArrayWriteAccess + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + poolStringArrayWriteAccessPtr: proc (self: ptr GodotPoolStringArrayWriteAccess): ptr GodotString + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + poolStringArrayWriteAccessOperatorAssign: proc (self, other: ptr GodotPoolStringArrayWriteAccess) + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + poolStringArrayWriteAccessDestroy: proc (self: ptr GodotPoolStringArrayWriteAccess) + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + + poolVector2ArrayWriteAccessCopy: proc (self: ptr GodotPoolVector2ArrayWriteAccess): ptr GodotPoolVector2ArrayWriteAccess + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + poolVector2ArrayWriteAccessPtr: proc (self: ptr GodotPoolVector2ArrayWriteAccess): ptr Vector2 + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + poolVector2ArrayWriteAccessOperatorAssign: proc (self, other: ptr GodotPoolVector2ArrayWriteAccess) + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + poolVector2ArrayWriteAccessDestroy: proc (self: ptr GodotPoolVector2ArrayWriteAccess) + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + + poolVector3ArrayWriteAccessCopy: proc (self: ptr GodotPoolVector3ArrayWriteAccess): ptr GodotPoolVector3ArrayWriteAccess + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + poolVector3ArrayWriteAccessPtr: proc (self: ptr GodotPoolVector3ArrayWriteAccess): ptr Vector3 + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + poolVector3ArrayWriteAccessOperatorAssign: proc (self, other: ptr GodotPoolVector3ArrayWriteAccess) + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + poolVector3ArrayWriteAccessDestroy: proc (self: ptr GodotPoolVector3ArrayWriteAccess) + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + + poolColorArrayWriteAccessCopy: proc (self: ptr GodotPoolColorArrayWriteAccess): ptr GodotPoolColorArrayWriteAccess + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + poolColorArrayWriteAccessPtr: proc (self: ptr GodotPoolColorArrayWriteAccess): ptr Color + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + poolColorArrayWriteAccessOperatorAssign: proc (self, other: ptr GodotPoolColorArrayWriteAccess) + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + poolColorArrayWriteAccessDestroy: proc (self: ptr GodotPoolColorArrayWriteAccess) + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + + # Array API + arrayNew: proc (dest: var GodotArray) + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + arrayNewCopy: proc (dest: var GodotArray, src: GodotArray) + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + arrayNewPoolColorArray: proc (dest: var GodotArray, src: GodotPoolColorArray) + {.noconv, raises: [], gcsafe, tags: [], + locks: 0.} + arrayNewPoolVector3Array: proc (dest: var GodotArray, + src: GodotPoolVector3Array) + {.noconv, raises: [], gcsafe, tags: [], + locks: 0.} + arrayNewPoolVector2Array: proc (dest: var GodotArray, + src: GodotPoolVector2Array) + {.noconv, raises: [], gcsafe, tags: [], + locks: 0.} + arrayNewPoolStringArray: proc (dest: var GodotArray, + src: GodotPoolStringArray) + {.noconv, raises: [], gcsafe, tags: [], + locks: 0.} + arrayNewPoolRealArray: proc (dest: var GodotArray, src: GodotPoolRealArray) + {.noconv, raises: [], gcsafe, tags: [], + locks: 0.} + arrayNewPoolIntArray: proc (dest: var GodotArray, src: GodotPoolIntArray) + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + arrayNewPoolByteArray: proc (dest: var GodotArray, src: GodotPoolByteArray) + {.noconv, raises: [], gcsafe, tags: [], + locks: 0.} + arraySet: proc (self: var GodotArray, idx: cint, val: GodotVariant) + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + arrayGet: proc (self: GodotArray, idx: cint): GodotVariant + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + arrayOperatorIndex: proc (self: var GodotArray, idx: cint): ptr GodotVariant + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + arrayOperatorIndexConst: pointer + arrayAppend: proc (self: var GodotArray, val: GodotVariant) + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + arrayClear: proc (self: var GodotArray) + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + arrayCount: proc (self: GodotArray, val: GodotVariant): cint + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + arrayEmpty: proc (self: GodotArray): bool + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + arrayErase: proc (self: var GodotArray, val: GodotVariant) + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + arrayFront: proc (self: GodotArray): GodotVariant + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + arrayBack: proc (self: GodotArray): GodotVariant + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + arrayFind: proc (self: GodotArray, what: GodotVariant, fromIdx: cint): cint + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + arrayFindLast: proc (self: GodotArray, what: GodotVariant): cint + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + arrayHas: proc (self: GodotArray, val: GodotVariant): bool + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + arrayHash: proc (self: GodotArray): cint + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + arrayInsert: proc (self: var GodotArray, pos: cint, val: GodotVariant): Error + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + arrayInvert: proc (self: var GodotArray) + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + arrayPopBack: proc (self: GodotArray): GodotVariant + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + arrayPopFront: proc (self: GodotArray): GodotVariant + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + arrayPushBack: proc (self: var GodotArray, val: GodotVariant) + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + arrayPushFront: proc (self: var GodotArray, val: GodotVariant) + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + arrayRemove: proc (self: var GodotArray, idx: cint) + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + arrayResize: proc (self: var GodotArray, size: cint) + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + arrayRFind: proc (self: GodotArray, what: GodotVariant, fromIdx: cint): cint + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + arraySize: proc (self: GodotArray): cint + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + arraySort: proc (self: var GodotArray) + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + arraySortCustom: proc (self: var GodotArray, obj: ptr GodotObject, + f: GodotString) + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + arrayBSearch: proc (self: var GodotArray, val: ptr GodotVariant, + before: bool) + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + arrayBSearchCustom: proc (self: var GodotArray, val: ptr GodotVariant, + obj: ptr GodotObject, f: GodotString, + before: bool) + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + arrayDestroy: proc (self: var GodotArray) + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + + # Dictionary API + dictionaryNew: proc (dest: var GodotDictionary) + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + dictionaryNewCopy: proc (dest: var GodotDictionary, src: GodotDictionary) + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + dictionaryDestroy: proc (self: var GodotDictionary) + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + dictionarySize: proc (self: GodotDictionary): cint + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + dictionaryEmpty: proc (self: GodotDictionary): bool + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + dictionaryClear: proc (self: var GodotDictionary) + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + dictionaryHas: proc (self: GodotDictionary, key: GodotVariant): bool + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + dictionaryHasAll: proc (self: GodotDictionary, keys: GodotArray): bool + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + dictionaryErase: proc (self: var GodotDictionary, key: GodotVariant) + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + dictionaryHash: proc (self: GodotDictionary): cint + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + dictionaryKeys: proc (self: GodotDictionary): GodotArray + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + dictionaryValues: proc (self: GodotDictionary): GodotArray + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + dictionaryGet: proc (self: GodotDictionary, key: GodotVariant): GodotVariant + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + dictionarySet: proc (self: var GodotDictionary, key, value: GodotVariant) + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + dictionaryOperatorIndex: proc (self: var GodotDictionary, + key: GodotVariant): ptr GodotVariant + {.noconv, raises: [], gcsafe, tags: [], + locks: 0.} + dictionaryOperatorIndexConst: pointer + dictionaryNext: proc (self: GodotDictionary, + key: GodotVariant): ptr GodotVariant + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + dictionaryOperatorEqual: proc (self, other: GodotDictionary): bool + {.noconv, raises: [], gcsafe, tags: [], + locks: 0.} + dictionaryToJson: proc (self: GodotDictionary): GodotString + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + + # NodePath API + nodePathNew: proc (dest: var GodotNodePath, src: GodotString) + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + nodePathNewCopy: proc (dest: var GodotNodePath, src: GodotNodePath) + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + nodePathDestroy: proc (self: var GodotNodePath) + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + nodePathAsString: proc (self: GodotNodePath): GodotString + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + nodePathIsAbsolute: proc (self: GodotNodePath): bool + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + nodePathGetNameCount: proc (self: GodotNodePath): cint + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + nodePathGetName: proc (self: GodotNodePath, idx: cint): GodotString + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + nodePathGetSubnameCount: proc (self: GodotNodePath): cint + {.noconv, raises: [], gcsafe, tags: [], + locks: 0.} + nodePathGetSubname: proc (self: GodotNodePath, idx: cint): GodotString + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + nodePathGetConcatenatedSubnames: proc (self: GodotNodePath): GodotString + {.noconv, raises: [], gcsafe, + tags: [], locks: 0.} + nodePathIsEmpty: proc (self: GodotNodePath): bool + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + nodePathOperatorEqual: proc (self, other: GodotNodePath): bool + {.noconv, raises: [], gcsafe, tags: [], + locks: 0.} + + # Plane API + planeNewWithReals: proc (dest: var Plane, a, b, c, d: float32) + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + planeNewWithVectors: proc (dest: var Plane, v1, v2, v3: Vector3) + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + planeNewWithNormal: proc (dest: var Plane, normal: Vector3, d: float32) + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + planeAsString: proc (self: Plane): GodotString + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + planeNormalized: proc (self: Plane): PlaneData + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + planeCenter: proc (self: Plane): Vector3Data + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + planeGetAnyPoint: proc (self: Plane): Vector3Data + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + planeIsPointOver: proc (self: Plane, point: Vector3): bool + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + planeDistanceTo: proc (self: Plane, point: Vector3): float32 + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + planeHasPoint: proc (self: Plane, point: Vector3, epsilon: float32): bool + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + planeProject: proc (self: Plane, point: Vector3): Vector3Data + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + planeIntersect3: proc (self: Plane, dest: var Vector3, b, c: Plane): bool + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + planeIntersectsRay: proc (self: Plane, dest: var Vector3, + point, dir: Vector3): bool + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + planeIntersectsSegment: proc (self: Plane, dest: var Vector3, + segmentBegin, segmentEnd: Vector3): bool + {.noconv, raises: [], gcsafe, tags: [], + locks: 0.} + planeOperatorNeg: proc (self: Plane): PlaneData + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + planeOperatorEqual: proc (self, other: Plane): bool + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + planeSetNormal: proc (self: var Plane, normal: Vector3) + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + planeGetNormal: proc (self: Plane): Vector3Data + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + planeGetD: proc (self: Plane): float32 + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + planeSetD: proc (self: var Plane, d: float32) + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + + # Rect2 API + rect2NewWithPositionAndSize: proc (dest: var Rect2, pos, size: Vector2) + {.noconv, raises: [], gcsafe, tags: [], + locks: 0.} + rect2New: proc (dest: var Rect2, x, y, width, height: float32) + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + rect2AsString: proc (self: Rect2): GodotString + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + rect2GetArea: proc (self: Rect2): float32 + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + rect2Intersects: proc (self, other: Rect2): bool + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + rect2Encloses: proc (self, other: Rect2): bool + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + rect2HasNoArea: proc (self: Rect2): bool + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + rect2Clip: proc (self, other: Rect2): Rect2Data + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + rect2Merge: proc (self, other: Rect2): Rect2Data + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + rect2HasPoint: proc (self: Rect2, point: Vector2): bool + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + rect2Grow: proc (self: Rect2, by: float32): Rect2Data + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + rect2Expand: proc (self: Rect2, to: Vector2): Rect2Data + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + rect2OperatorEqual: proc (self, other: Rect2): bool + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + rect2GetPosition: proc (self: Rect2): Vector2Data + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + rect2GetSize: proc (self: Rect2): Vector2Data + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + rect2SetPosition: proc (self: var Rect2, pos: Vector2) + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + rect2SetSize: proc (self: var Rect2, size: Vector2) + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + + # AABB API + aabbNew: proc (dest: var AABB, pos, size: Vector3) + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + aabbGetPosition: proc (self: AABB): Vector3Data + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + aabbSetPosition: proc (self: var AABB, pos: Vector3) + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + aabbGetSize: proc (self: AABB): Vector3Data + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + aabbSetSize: proc (self: var AABB, pos: Vector3) + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + aabbAsString: proc (self: AABB): GodotString + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + aabbGetArea: proc (self: AABB): float32 + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + aabbHasNoArea: proc (self: AABB): bool + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + aabbHasNoSurface: proc (self: AABB): bool + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + aabbIntersects: proc (self, other: AABB): bool + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + aabbEncloses: proc (self, other: AABB): bool + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + aabbMerge: proc (self, other: AABB): AABBData + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + aabbIntersection: proc (self, other: AABB): AABBData + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + aabbIntersectsPlane: proc (self: AABB, plane: Plane): bool + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + aabbIntersectsSegment: proc (self: AABB, vFrom, vTo: Vector3): bool + {.noconv, raises: [], gcsafe, tags: [], + locks: 0.} + aabbHasPoint: proc (self: AABB, point: Vector3): bool + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + aabbGetSupport: proc (self: AABB, dir: Vector3): Vector3Data + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + aabbGetLongestAxis: proc (self: AABB): Vector3Data + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + aabbGetLongestAxisIndex: proc (self: AABB): cint + {.noconv, raises: [], gcsafe, tags: [], + locks: 0.} + aabbGetLongestAxisSize: proc (self: AABB): float32 + {.noconv, raises: [], gcsafe, tags: [], + locks: 0.} + aabbGetShortestAxis: proc (self: AABB): Vector3Data + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + aabbGetShortestAxisIndex: proc (self: AABB): cint + {.noconv, raises: [], gcsafe, tags: [], + locks: 0.} + aabbGetShortestAxisSize: proc (self: AABB): float32 + {.noconv, raises: [], gcsafe, tags: [], + locks: 0.} + aabbExpand: proc (self: AABB, toPoint: Vector3): AABBData + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + aabbGrow: proc (self: AABB, by: float32): AABBData + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + aabbGetEndpoint: proc (self: AABB, idx: cint): Vector3Data + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + aabbOperatorEqual: proc (self, other: AABB): bool + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + + # RID API + ridNew: proc (dest: var RID) + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + ridGetID: proc (self: RID): cint + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + ridNewWithResource: proc (dest: var RID, obj: ptr GodotObject) + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + ridOperatorEqual: proc (self, other: RID): bool + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + ridOperatorLess: proc (self, other: RID): bool + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + + # Transform API + transformNewWithAxisOrigin: proc (dest: var Transform, + xAxis, yAxis, zAxis, origin: Vector3) + {.noconv, raises: [], gcsafe, tags: [], + locks: 0.} + transformNew: proc (dest: var Transform, basis: Basis, origin: Vector3) + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + transformGetBasis: proc (self: Transform): BasisData + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + transformSetBasis: proc (self: var Transform, basis: Basis) + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + transformGetOrigin: proc (self: Transform): Vector3Data + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + transformSetOrigin: proc (self: var Transform, v: Vector3) + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + transformAsString: proc (self: Transform): GodotString + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + transformInverse: proc (self: Transform): TransformData + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + transformAffineInverse: proc (self: Transform): TransformData + {.noconv, raises: [], gcsafe, tags: [], + locks: 0.} + transformOrthonormalized: proc (self: Transform): TransformData + {.noconv, raises: [], gcsafe, tags: [], + locks: 0.} + transformRotated: proc (self: Transform, axis: Vector3, + phi: float32): TransformData + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + transformScaled: proc (self: Transform, scale: Vector3): TransformData + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + transformTranslated: proc (self: Transform, offset: Vector3): TransformData + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + transformLookingAt: proc (self: Transform, target, up: Vector3): TransformData + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + transformXformPlane: proc (self: Transform, plane: Plane): PlaneData + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + transformXformInvPlane: proc (self: Transform, plane: Plane): PlaneData + {.noconv, raises: [], gcsafe, tags: [], + locks: 0.} + transformNewIdentity: proc (dest: var Transform) + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + transformOperatorEqual: proc (self, other: Transform): bool + {.noconv, raises: [], gcsafe, tags: [], + locks: 0.} + transformOperatorMultiply: proc (self, other: Transform): TransformData + {.noconv, raises: [], gcsafe, tags: [], + locks: 0.} + transformXformVector3: proc (self: Transform, v: Vector3): Vector3Data + {.noconv, raises: [], gcsafe, tags: [], + locks: 0.} + transformXformInvVector3: proc (self: Transform, v: Vector3): Vector3Data + {.noconv, raises: [], gcsafe, tags: [], + locks: 0.} + transformXformAABB: proc (self: Transform, v: AABB): AABBData + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + transformXformInvAABB: proc (self: Transform, v: AABB): AABBData + {.noconv, raises: [], gcsafe, tags: [], + locks: 0.} + + # Transform2D API + transform2DNew: proc (dest: var Transform2D, rot: float32, pos: Vector2) + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + transform2DNewAxisOrigin: proc (dest: var Transform2D, + xAxis, yAxis, origin: Vector2) + {.noconv, raises: [], gcsafe, tags: [], + locks: 0.} + transform2DAsString: proc (self: Transform2D): GodotString + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + transform2DInverse: proc (self: Transform2D): Transform2DData + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + transform2DAffineInverse: proc (self: Transform2D): Transform2DData + {.noconv, raises: [], gcsafe, tags: [], + locks: 0.} + transform2DGetRotation: proc (self: Transform2D): float32 + {.noconv, raises: [], gcsafe, tags: [], + locks: 0.} + transform2DGetOrigin: proc (self: Transform2D): Vector2Data + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + transform2DGetScale: proc (self: Transform2D): Vector2Data + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + transform2DOrthonormalized: proc (self: Transform2D): Transform2DData + {.noconv, raises: [], gcsafe, tags: [], + locks: 0.} + transform2DRotated: proc (self: Transform2D, phi: float32): Transform2DData + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + transform2DScaled: proc (self: Transform2D, scale: Vector2): Transform2DData + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + transform2DTranslated: proc (self: Transform2D, offset: Vector2): Transform2DData + {.noconv, raises: [], gcsafe, tags: [], + locks: 0.} + transform2DXformVector2: proc (self: Transform2D, v: Vector2): Vector2Data + {.noconv, raises: [], gcsafe, tags: [], + locks: 0.} + transform2DXformInvVector2: proc (self: Transform2D, v: Vector2): Vector2Data + {.noconv, raises: [], gcsafe, tags: [], + locks: 0.} + transform2DBasisXformVector2: proc (self: Transform2D, v: Vector2): Vector2Data + {.noconv, raises: [], gcsafe, tags: [], + locks: 0.} + transform2DBasisXformInvVector2: proc (self: Transform2D, + v: Vector2): Vector2Data + {.noconv, raises: [], gcsafe, tags: [], + locks: 0.} + transform2DInterpolateWith: proc (self, other: Transform2D, + t: float32): Transform2DData + {.noconv, raises: [], gcsafe, tags: [], + locks: 0.} + transform2DOperatorEqual: proc (self, other: Transform2D): bool + {.noconv, raises: [], gcsafe, tags: [], + locks: 0.} + transform2DOperatorMultiply: proc (self, other: Transform2D): Transform2DData + {.noconv, raises: [], gcsafe, tags: [], + locks: 0.} + transform2DNewIdentity: proc (dest: var Transform2D) + {.noconv, raises: [], gcsafe, tags: [], + locks: 0.} + transform2DXformRect2: proc (self: Transform2D, v: Rect2): Rect2Data + {.noconv, raises: [], gcsafe, tags: [], + locks: 0.} + transform2DXformInvRect2: proc (self: Transform2D, v: Rect2): Rect2Data + {.noconv, raises: [], gcsafe, tags: [], + locks: 0.} + + # Variant API + variantGetType: proc (v: GodotVariant): VariantType + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + variantNewCopy: proc (dest: var GodotVariant, src: GodotVariant) + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + variantNewNil: proc (dest: var GodotVariant) + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + variantNewBool: proc (dest: var GodotVariant, val: bool) + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + variantNewUInt: proc (dest: var GodotVariant, val: uint64) + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + variantNewInt: proc (dest: var GodotVariant, val: int64) + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + variantNewReal: proc (dest: var GodotVariant, val: float64) + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + variantNewString: proc (dest: var GodotVariant, val: GodotString) + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + variantNewVector2: proc (dest: var GodotVariant, val: Vector2) + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + variantNewRect2: proc (dest: var GodotVariant, val: Rect2) + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + variantNewVector3: proc (dest: var GodotVariant, val: Vector3) + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + variantNewTransform2D: proc (dest: var GodotVariant, val: Transform2D) + {.noconv, raises: [], gcsafe, tags: [], + locks: 0.} + variantNewPlane: proc (dest: var GodotVariant, val: Plane) + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + variantNewQuat: proc (dest: var GodotVariant, val: Quat) + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + variantNewAABB: proc (dest: var GodotVariant, val: AABB) + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + variantNewBasis: proc (dest: var GodotVariant, val: Basis) + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + variantNewTransform: proc (dest: var GodotVariant, val: Transform) + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + variantNewColor: proc (dest: var GodotVariant, val: Color) + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + variantNewNodePath: proc (dest: var GodotVariant, val: GodotNodePath) + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + variantNewRID: proc (dest: var GodotVariant, val: RID) + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + variantNewObject: proc (dest: var GodotVariant, val: ptr GodotObject) + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + variantNewDictionary: proc (dest: var GodotVariant, val: GodotDictionary) + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + variantNewArray: proc (dest: var GodotVariant, val: GodotArray) + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + variantNewPoolByteArray: proc (dest: var GodotVariant, + val: GodotPoolByteArray) + {.noconv, raises: [], gcsafe, tags: [], + locks: 0.} + variantNewPoolIntArray: proc (dest: var GodotVariant, val: GodotPoolIntArray) + {.noconv, raises: [], gcsafe, tags: [], + locks: 0.} + variantNewPoolRealArray: proc (dest: var GodotVariant, + val: GodotPoolRealArray) + {.noconv, raises: [], gcsafe, tags: [], + locks: 0.} + variantNewPoolStringArray: proc (dest: var GodotVariant, + val: GodotPoolStringArray) + {.noconv, raises: [], gcsafe, tags: [], + locks: 0.} + variantNewPoolVector2Array: proc (dest: var GodotVariant, + val: GodotPoolVector2Array) + {.noconv, raises: [], gcsafe, tags: [], + locks: 0.} + variantNewPoolVector3Array: proc (dest: var GodotVariant, + val: GodotPoolVector3Array) + {.noconv, raises: [], gcsafe, tags: [], + locks: 0.} + variantNewPoolColorArray: proc (dest: var GodotVariant, + val: GodotPoolColorArray) + {.noconv, raises: [], gcsafe, tags: [], + locks: 0.} + variantAsBool: proc (self: GodotVariant): bool + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + variantAsUInt: proc (self: GodotVariant): uint64 + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + variantAsInt: proc (self: GodotVariant): int64 + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + variantAsReal: proc (self: GodotVariant): float64 + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + variantAsString: proc (self: GodotVariant): GodotString + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + variantAsVector2: proc (self: GodotVariant): Vector2Data + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + variantAsRect2: proc (self: GodotVariant): Rect2Data + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + variantAsVector3: proc (self: GodotVariant): Vector3Data + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + variantAsTransform2D: proc (self: GodotVariant): Transform2DData + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + variantAsPlane: proc (self: GodotVariant): PlaneData + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + variantAsQuat: proc (self: GodotVariant): QuatData + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + variantAsAABB: proc (self: GodotVariant): AABBData + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + variantAsBasis: proc (self: GodotVariant): BasisData + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + variantAsTransform: proc (self: GodotVariant): TransformData + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + variantAsColor: proc (self: GodotVariant): ColorData + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + variantAsNodePath: proc (self: GodotVariant): GodotNodePath + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + variantAsRID: proc (self: GodotVariant): RID + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + variantAsObject: proc (self: GodotVariant): ptr GodotObject + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + variantAsDictionary: proc (self: GodotVariant): GodotDictionary + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + variantAsArray: proc (self: GodotVariant): GodotArray + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + variantAsPoolByteArray: proc (self: GodotVariant): GodotPoolByteArray + {.noconv, raises: [], gcsafe, tags: [], + locks: 0.} + variantAsPoolIntArray: proc (self: GodotVariant): GodotPoolIntArray + {.noconv, raises: [], gcsafe, tags: [], + locks: 0.} + variantAsPoolRealArray: proc (self: GodotVariant): GodotPoolRealArray + {.noconv, raises: [], gcsafe, tags: [], + locks: 0.} + variantAsPoolStringArray: proc (self: GodotVariant): GodotPoolStringArray + {.noconv, raises: [], gcsafe, tags: [], + locks: 0.} + variantAsPoolVector2Array: proc (self: GodotVariant): GodotPoolVector2Array + {.noconv, raises: [], gcsafe, tags: [], + locks: 0.} + variantAsPoolVector3Array: proc (self: GodotVariant): GodotPoolVector3Array + {.noconv, raises: [], gcsafe, tags: [], + locks: 0.} + variantAsPoolColorArray: proc (self: GodotVariant): GodotPoolColorArray + {.noconv, raises: [], gcsafe, tags: [], + locks: 0.} + variantCall: proc (self: var GodotVariant, meth: GodotString, + args: ptr array[MAX_ARG_COUNT, ptr GodotVariant], + argcount: cint, + callError: var VariantCallError): GodotVariant + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + variantHasMethod: proc (self: GodotVariant, meth: GodotString): bool + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + variantOperatorEqual: proc (self, other: GodotVariant): bool + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + variantOperatorLess: proc (self, other: GodotVariant): bool + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + variantHashCompare: proc (self, other: GodotVariant): bool + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + variantBooleanize: proc (self: GodotVariant): bool + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + variantDestroy: proc (self: var GodotVariant) + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + + # String API + charStringLength: proc (self: GodotCharString): cint + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + charStringGetData: proc (self: GodotCharString): cstring + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + charStringDestroy: proc (self: var GodotCharString) + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + stringNew: proc (dest: var GodotString) + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + stringNewCopy: proc (dest: var GodotString, src: GodotString) + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + stringNewWithWideString: pointer + stringOperatorIndex: pointer + stringOperatorIndexConst: pointer + stringWideStr: proc (self: GodotString): ptr cwchar_t + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + stringOperatorEqual: proc (self, other: GodotString): bool + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + stringOperatorLess: proc (self, other: GodotString): bool + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + stringOperatorPlus: proc (self, other: GodotString): GodotString + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + stringLength: proc (self: GodotString): cint + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + stringCasecmpTo: pointer + stringNocasecmpTo: pointer + stringNaturalnocasecmpTo: pointer + stringBeginsWith: pointer + stringBeginsWithCharArray: pointer + stringBigrams: pointer + stringChr: pointer + stringEndsWith: pointer + stringFind: pointer + stringFindFrom: pointer + stringFindmk: pointer + stringFindmkFrom: pointer + stringFindmkFromInPlace: pointer + stringFindn: pointer + stringFindnFrom: pointer + stringFindLast: pointer + stringFormat: pointer + stringFormatWithCustomPlaceholder: pointer + stringHexEncodeBuffer: pointer + stringHexToInt: pointer + stringHexToIntWithoutPrefix: pointer + stringInsert: pointer + stringIsNumeric: pointer + stringIsSubsequenceOf: pointer + stringIsSubsequenceOfi: pointer + stringLpad: pointer + stringLpadWithCustomCharacter: pointer + stringMatch: pointer + stringMatchn: pointer + stringMd5: pointer + stringNum: pointer + stringNumInt64: pointer + stringNumInt64Capitalized: pointer + stringNumReal: pointer + stringNumScientific: pointer + stringNumWithDecimals: pointer + stringPadDecimals: pointer + stringPadZeros: pointer + stringReplaceFirst: pointer + stringReplace: pointer + stringReplacen: pointer + stringRfind: pointer + stringRfindn: pointer + stringRfindFrom: pointer + stringRfindnFrom: pointer + stringRpad: pointer + stringRpadWithCustomCharacter: pointer + stringSimilarity: pointer + stringSprintf: pointer + stringSubstr: pointer + stringToDouble: pointer + stringToFloat: pointer + stringToInt: pointer + stringCamelcaseToUnderscore: pointer + stringCamelcaseToUnderscoreLowercased: pointer + stringCapitalize: pointer + stringCharToDouble: pointer + stringCharToInt: pointer + stringWcharToInt: pointer + stringCharToIntWithLen: pointer + stringCharToInt64WithLen: pointer + stringHexToInt64: pointer + stringHexToInt64WithPrefix: pointer + stringToInt64: pointer + stringUnicodeCharToDouble: pointer + stringGetSliceCount: pointer + stringGetSlice: pointer + stringGetSlicec: pointer + stringSplit: pointer + stringSplitAllowEmpty: pointer + stringSplitFloats: pointer + stringSplitFloatsAllowsEmpty: pointer + stringSplitFloatsMk: pointer + stringSplitFloatsMkAllowsEmpty: pointer + stringSplitInts: pointer + stringSplitIntsAllowsEmpty: pointer + stringSplitIntsMk: pointer + stringSplitIntsMkAllowsEmpty: pointer + stringSplitSpaces: pointer + stringCharLowercase: pointer + stringCharUppercase: pointer + stringToLower: pointer + stringToUpper: pointer + stringGetBasename: pointer + stringGetExtension: pointer + stringLeft: pointer + stringOrdAt: pointer + stringPlusFile: pointer + stringRight: pointer + stringStripEdges: pointer + stringStripEscapes: pointer + stringErase: pointer + stringAscii: pointer + stringAsciiExtended: pointer + stringUtf8: proc (self: GodotString): GodotCharString + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + stringParseUtf8: pointer + stringParseUtf8WithLen: pointer + stringCharsToUtf8: proc (str: cstring): GodotString + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + stringCharsToUtf8WithLen: proc (str: cstring, len: cint): GodotString + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + stringHash: pointer + stringHash64: pointer + stringHashChars: pointer + stringHashCharsWithLen: pointer + stringHashUtf8Chars: pointer + stringHashUtf8CharsWithLen: pointer + stringMd5Buffer: pointer + stringMd5Text: pointer + stringSha256Buffer: pointer + stringSha256Text: pointer + stringEmpty: pointer + stringGetBaseDir: pointer + stringGetFile: pointer + stringHumanizeSize: pointer + stringIsAbsPath: pointer + stringIsRelPath: pointer + stringIsResourceFile: pointer + stringPathTo: pointer + stringPathToFile: pointer + stringSimplifyPath: pointer + stringCEscape: pointer + stringCEscapeMultiline: pointer + stringCUnescape: pointer + stringHttpEscape: pointer + stringHttpUnescape: pointer + stringJsonEscape: pointer + stringWordWrap: pointer + stringXmlEscape: pointer + stringXmlEscapeWithQuotes: pointer + stringXmlUnescape: pointer + stringPercentDecode: pointer + stringPercentEncode: pointer + stringIsValidFloat: pointer + stringIsValidHexNumber: pointer + stringIsValidHtmlColor: pointer + stringIsValidIdentifier: pointer + stringIsValidInteger: pointer + stringIsValidIpAddress: pointer + stringDestroy: proc (self: var GodotString) + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + + # StringName API + stringNameNew: pointer + stringNameNewData: pointer + stringNameGetName: pointer + stringNameGetHash: pointer + stringNameGetDataUniquePointer: pointer + stringNameOperatorEqual: pointer + stringNameOperatorLess: pointer + stringNameDestroy: pointer + + # Misc API + objectDestroy: proc (self: ptr GodotObject) + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + globalGetSingleton: proc (name: cstring): ptr GodotObject + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + methodBindGetMethod: proc (className, + methodName: cstring): ptr GodotMethodBind + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + methodBindPtrCall: proc (methodBind: ptr GodotMethodBind, + obj: ptr GodotObject, + args: ptr array[MAX_ARG_COUNT, pointer], + ret: pointer) + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + methodBindCall: proc (methodBind: ptr GodotMethodBind, obj: ptr GodotObject, + args: ptr array[MAX_ARG_COUNT, ptr GodotVariant], + argCount: cint, + callError: var VariantCallError): GodotVariant + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + getClassConstructor: proc (className: cstring): GodotClassConstructor + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + getGlobalConstants: pointer + registerNativeCallType: proc (callType: cstring, + cb: proc (procHandle: pointer, + args: ptr GodotArray): GodotVariant + {.noconv.}) {.noconv.} + alloc: proc (bytes: cint): pointer + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + realloc: proc (p: pointer, bytes: cint): pointer + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + free: proc (p: pointer) {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + + printError: proc (description, function, file: cstring, line: cint) + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + printWarning: proc (description, function, file: cstring, line: cint) + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + print: proc (message: GodotString) + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + + GDNativeAPI* = object + # Color API + colorNewRGBA*: proc (dest: var Color, r, g, b, a: float32) + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + colorNewRGB*: proc (dest: var Color, r, g, b: float32) + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + colorGetR*: proc (self: Color): float32 + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + colorSetR*: proc (self: var Color, r: float32) + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + colorGetG*: proc (self: Color): float32 + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + colorSetG*: proc (self: var Color, g: float32) + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + colorGetB*: proc (self: Color): float32 + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + colorSetB*: proc (self: var Color, b: float32) + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + colorGetA*: proc (self: Color): float32 + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + colorSetA*: proc (self: var Color, a: float32) + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + colorGetH*: proc (self: Color): float32 + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + colorGetS*: proc (self: Color): float32 + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + colorGetV*: proc (self: Color): float32 + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + colorAsString*: proc (self: Color): GodotString + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + colorToRGBA32*: proc (self: Color): cint + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + colorAsARGB32*: proc (self: Color): cint + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + colorGray*: proc (self: Color): float32 + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + colorInverted*: proc (self: Color): ColorData + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + colorContrasted*: proc (self: Color): ColorData + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + colorLinearInterpolate*: proc (self, other: Color, t: float32): ColorData + {.noconv, raises: [], gcsafe, tags: [], + locks: 0.} + colorBlend*: proc (self, other: Color): ColorData + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + colorToHtml*: proc (self: Color, withAlpha: bool): GodotString + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + colorOperatorEqual*: proc (self, other: Color): bool + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + colorOperatorLess*: proc (self, other: Color): bool + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + + # Vector2 API + vector2New*: proc (dest: var Vector2, x, y: float32) + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + vector2AsString*: proc (self: Vector2): GodotString + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + vector2Normalized*: proc (self: Vector2): Vector2Data + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + vector2Length*: proc (self: Vector2): float32 + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + vector2Angle*: proc (self: Vector2): float32 + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + vector2LengthSquared*: proc (self: Vector2): float32 + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + vector2IsNormalized*: proc (self: Vector2): bool + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + vector2DistanceTo*: proc (self, to: Vector2): float32 + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + vector2DistanceSquaredTo*: proc (self, to: Vector2): float32 + {.noconv, raises: [], gcsafe, tags: [], + locks: 0.} + vector2AngleTo*: proc (self, to: Vector2): float32 + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + vector2AngleToPoint*: proc (self, to: Vector2): float32 + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + vector2LinearInterpolate*: proc (self, b: Vector2, t: float32): Vector2Data + {.noconv, raises: [], gcsafe, tags: [], + locks: 0.} + vector2CubicInterpolate*: proc (self, b, preA, postB: Vector2, + t: float32): Vector2Data + {.noconv, raises: [], gcsafe, tags: [], + locks: 0.} + vector2Rotated*: proc (self: Vector2, phi: float32): Vector2Data + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + vector2Tangent*: proc (self: Vector2): Vector2Data + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + vector2Floor*: proc (self: Vector2): Vector2Data + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + vector2Snapped*: proc (self, by: Vector2): Vector2Data + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + vector2Aspect*: proc (self: Vector2): float32 + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + vector2Dot*: proc (self, other: Vector2): float32 + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + vector2Slide*: proc (self, n: Vector2): Vector2Data + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + vector2Bounce*: proc (self, n: Vector2): Vector2Data + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + vector2Reflect*: proc (self, n: Vector2): Vector2Data + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + vector2Abs*: proc (self: Vector2): Vector2Data + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + vector2Clamped*: proc (self: Vector2, length: float32): Vector2Data + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + vector2OperatorAdd*: proc (self, other: Vector2): Vector2Data + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + vector2OperatorSubtract*: proc (self, other: Vector2): Vector2Data + {.noconv, raises: [], gcsafe, tags: [], + locks: 0.} + vector2OperatorMultiplyVector*: proc (self, other: Vector2): Vector2Data + {.noconv, raises: [], gcsafe, tags: [], + locks: 0.} + vector2OperatorMultiplyScalar*: proc (self: Vector2, scalar: float32): Vector2Data + {.noconv, raises: [], gcsafe, tags: [], + locks: 0.} + vector2OperatorDivideVector*: proc (self, other: Vector2): Vector2Data + {.noconv, raises: [], gcsafe, tags: [], + locks: 0.} + vector2OperatorDivideScalar*: proc (self: Vector2, scalar: float32): Vector2Data + {.noconv, raises: [], gcsafe, tags: [], + locks: 0.} + vector2OperatorEqual*: proc (self, other: Vector2): bool + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + vector2OperatorLess*: proc (self, other: Vector2): bool + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + vector2OperatorNeg*: proc (self: Vector2): Vector2Data + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + + # Quat API + quatNew*: proc (dest: var Quat, x, y, z, w: float32) + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + quatNewWithAxisAngle*: proc (dest: Quat, axis: Vector3, + angle: float32) + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + quatGetX*: proc (self: Quat): float32 + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + quatSetX*: proc (self: var Quat, val: float32) + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + quatGetY*: proc (self: Quat): float32 + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + quatSetY*: proc (self: var Quat, val: float32) + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + quatGetZ*: proc (self: Quat): float32 + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + quatSetZ*: proc (self: var Quat, val: float32) + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + quatGetW*: proc (self: Quat): float32 + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + quatSetW*: proc (self: var Quat, val: float32) + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + quatAsString*: proc (self: Quat): GodotString + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + quatLength*: proc (self: Quat): float32 + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + quatLengthSquared*: proc (self: Quat): float32 + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + quatNormalized*: proc (self: Quat): QuatData + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + quatIsNormalized*: proc (self: Quat): bool + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + quatInverse*: proc (self: Quat): QuatData + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + quatDot*: proc (self, other: Quat): float32 + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + quatXform*: proc (self: Quat, v: Vector3): Vector3Data + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + quatSlerp*: proc (self, other: Quat, t: float32): QuatData + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + quatSlerpni*: proc (self, other: Quat, t: float32): QuatData + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + quatCubicSlerp*: proc (self, other, preA, postB: Quat, t: float32): QuatData + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + quatOperatorMultiply*: proc (self: Quat, b: float32): QuatData + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + quatOperatorAdd*: proc (self, other: Quat): QuatData + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + quatOperatorSubtract*: proc (self, other: Quat): QuatData + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + quatOperatorDivide*: proc (self: Quat, divider: float32): QuatData + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + quatOperatorEqual*: proc (self, other: Quat): bool + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + quatOperatorNeg*: proc (self: Quat): QuatData + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + + # PoolByteArray API + poolByteArrayNew*: proc (dest: var GodotPoolByteArray) + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + poolByteArrayNewCopy*: proc (dest: var GodotPoolByteArray, + src: GodotPoolByteArray) + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + poolByteArrayNewWithArray*: proc (dest: var GodotPoolByteArray, + src: GodotArray) + {.noconv, raises: [], gcsafe, tags: [], + locks: 0.} + poolByteArrayAppend*: proc (self: var GodotPoolByteArray, + val: byte) + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + poolByteArrayAppendArray*: proc (self: var GodotPoolByteArray, + arr: GodotPoolByteArray) + {.noconv, raises: [], gcsafe, tags: [], + locks: 0.} + poolByteArrayInsert*: proc (self: var GodotPoolByteArray, + idx: cint, val: byte): Error + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + poolByteArrayInvert*: proc (self: var GodotPoolByteArray) + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + poolByteArrayPushBack*: proc (self: var GodotPoolByteArray, val: byte) + {.noconv, raises: [], gcsafe, tags: [], + locks: 0.} + poolByteArrayRemove*: proc (self: var GodotPoolByteArray, idx: cint) + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + poolByteArrayResize*: proc (self: var GodotPoolByteArray, size: cint) + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + poolByteArrayRead*: proc (self: GodotPoolByteArray): ptr GodotPoolByteArrayReadAccess + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + poolByteArrayWrite*: proc (self: var GodotPoolByteArray): ptr GodotPoolByteArrayWriteAccess + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + poolByteArraySet*: proc (self: var GodotPoolByteArray, idx: cint, data: byte) + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + poolByteArrayGet*: proc (self: GodotPoolByteArray, idx: cint): byte + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + poolByteArraySize*: proc (self: GodotPoolByteArray): cint + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + poolByteArrayDestroy*: proc (self: GodotPoolByteArray) + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + + # PoolIntArray API + poolIntArrayNew*: proc (dest: var GodotPoolIntArray) + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + poolIntArrayNewCopy*: proc (dest: var GodotPoolIntArray, + src: GodotPoolIntArray) + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + poolIntArrayNewWithArray*: proc (dest: var GodotPoolIntArray, src: GodotArray) + {.noconv, raises: [], gcsafe, tags: [], + locks: 0.} + poolIntArrayAppend*: proc (self: var GodotPoolIntArray, val: cint) + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + poolIntArrayAppendArray*: proc (self: var GodotPoolIntArray, + arr: GodotPoolIntArray) + {.noconv, raises: [], gcsafe, tags: [], + locks: 0.} + poolIntArrayInsert*: proc (self: var GodotPoolIntArray, idx: cint, + val: cint): Error + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + poolIntArrayInvert*: proc (self: var GodotPoolIntArray) + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + poolIntArrayPushBack*: proc (self: var GodotPoolIntArray, val: cint) + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + poolIntArrayRemove*: proc (self: var GodotPoolIntArray, idx: cint) + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + poolIntArrayResize*: proc (self: var GodotPoolIntArray, size: cint) + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + poolIntArrayRead*: proc (self: GodotPoolIntArray): ptr GodotPoolIntArrayReadAccess + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + poolIntArrayWrite*: proc (self: var GodotPoolIntArray): ptr GodotPoolIntArrayWriteAccess + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + poolIntArraySet*: proc (self: var GodotPoolIntArray, idx: cint, data: cint) + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + poolIntArrayGet*: proc (self: GodotPoolIntArray, idx: cint): cint + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + poolIntArraySize*: proc (self: GodotPoolIntArray): cint + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + poolIntArrayDestroy*: proc (self: GodotPoolIntArray) + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + + # PoolRealArray API + poolRealArrayNew*: proc (dest: var GodotPoolRealArray) + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + poolRealArrayNewCopy*: proc (dest: var GodotPoolRealArray, + src: GodotPoolRealArray) + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + poolRealArrayNewWithArray*: proc (dest: var GodotPoolRealArray, + src: GodotArray) + {.noconv, raises: [], gcsafe, tags: [], + locks: 0.} + poolRealArrayAppend*: proc (self: var GodotPoolRealArray, val: float32) + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + poolRealArrayAppendArray*: proc (self: var GodotPoolRealArray, + arr: GodotPoolRealArray) + {.noconv, raises: [], gcsafe, tags: [], + locks: 0.} + poolRealArrayInsert*: proc (self: var GodotPoolRealArray, + idx: cint, val: float32): Error + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + poolRealArrayInvert*: proc (self: var GodotPoolRealArray) + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + poolRealArrayPushBack*: proc (self: var GodotPoolRealArray, val: float32) + {.noconv, raises: [], gcsafe, tags: [], + locks: 0.} + poolRealArrayRemove*: proc (self: var GodotPoolRealArray, idx: cint) + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + poolRealArrayResize*: proc (self: var GodotPoolRealArray, size: cint) + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + poolRealArrayRead*: proc (self: GodotPoolRealArray): ptr GodotPoolRealArrayReadAccess + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + poolRealArrayWrite*: proc (self: var GodotPoolRealArray): ptr GodotPoolRealArrayWriteAccess + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + poolRealArraySet*: proc (self: var GodotPoolRealArray, idx: cint, + data: float32) + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + poolRealArrayGet*: proc (self: GodotPoolRealArray, idx: cint): float32 + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + poolRealArraySize*: proc (self: GodotPoolRealArray): cint + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + poolRealArrayDestroy*: proc (self: GodotPoolRealArray) + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + + # PoolStringArray API + poolStringArrayNew*: proc (dest: var GodotPoolStringArray) + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + poolStringArrayNewCopy*: proc (dest: var GodotPoolStringArray, + src: GodotPoolStringArray) + {.noconv, raises: [], gcsafe, tags: [], + locks: 0.} + poolStringArrayNewWithArray*: proc (dest: var GodotPoolStringArray, + src: GodotArray) + {.noconv, raises: [], gcsafe, tags: [], + locks: 0.} + poolStringArrayAppend*: proc (self: var GodotPoolStringArray, + val: GodotString) + {.noconv, raises: [], gcsafe, tags: [], + locks: 0.} + poolStringArrayAppendArray*: proc (self: var GodotPoolStringArray, + arr: GodotPoolStringArray) + {.noconv, raises: [], gcsafe, tags: [], + locks: 0.} + poolStringArrayInsert*: proc (self: var GodotPoolStringArray, + idx: cint, val: GodotString): Error + {.noconv, raises: [], gcsafe, tags: [], + locks: 0.} + poolStringArrayInvert*: proc (self: var GodotPoolStringArray) + {.noconv, raises: [], gcsafe, tags: [], + locks: 0.} + poolStringArrayPushBack*: proc (self: var GodotPoolStringArray, + val: GodotString) + {.noconv, raises: [], gcsafe, tags: [], + locks: 0.} + poolStringArrayRemove*: proc (self: var GodotPoolStringArray, idx: cint) + {.noconv, raises: [], gcsafe, tags: [], + locks: 0.} + poolStringArrayResize*: proc (self: var GodotPoolStringArray, size: cint) + {.noconv, raises: [], gcsafe, tags: [], + locks: 0.} + poolStringArrayRead*: proc (self: GodotPoolStringArray): ptr GodotPoolStringArrayReadAccess + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + poolStringArrayWrite*: proc (self: var GodotPoolStringArray): ptr GodotPoolStringArrayWriteAccess + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + poolStringArraySet*: proc (self: var GodotPoolStringArray, idx: cint, + data: GodotString) + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + poolStringArrayGet*: proc (self: GodotPoolStringArray, idx: cint): GodotString + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + poolStringArraySize*: proc (self: GodotPoolStringArray): cint + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + poolStringArrayDestroy*: proc (self: GodotPoolStringArray) + {.noconv, raises: [], gcsafe, tags: [], + locks: 0.} + + # PoolVector2 API + poolVector2ArrayNew*: proc (dest: var GodotPoolVector2Array) + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + poolVector2ArrayNewCopy*: proc (dest: var GodotPoolVector2Array, + src: GodotPoolVector2Array) + {.noconv, raises: [], gcsafe, tags: [], + locks: 0.} + poolVector2ArrayNewWithArray*: proc (dest: var GodotPoolVector2Array, + src: GodotArray) + {.noconv, raises: [], gcsafe, tags: [], + locks: 0.} + poolVector2ArrayAppend*: proc (self: var GodotPoolVector2Array, val: Vector2) + {.noconv, raises: [], gcsafe, tags: [], + locks: 0.} + poolVector2ArrayAppendArray*: proc (self: var GodotPoolVector2Array, + arr: GodotPoolVector2Array) + {.noconv, raises: [], gcsafe, tags: [], + locks: 0.} + poolVector2ArrayInsert*: proc (self: var GodotPoolVector2Array, idx: cint, + val: Vector2): Error + {.noconv, raises: [], gcsafe, tags: [], + locks: 0.} + poolVector2ArrayInvert*: proc (self: var GodotPoolVector2Array) + {.noconv, raises: [], gcsafe, tags: [], + locks: 0.} + poolVector2ArrayPushBack*: proc (self: var GodotPoolVector2Array, + val: Vector2) + {.noconv, raises: [], gcsafe, tags: [], + locks: 0.} + poolVector2ArrayRemove*: proc (self: var GodotPoolVector2Array, idx: cint) + {.noconv, raises: [], gcsafe, tags: [], + locks: 0.} + poolVector2ArrayResize*: proc (self: var GodotPoolVector2Array, size: cint) + {.noconv, raises: [], gcsafe, tags: [], + locks: 0.} + poolVector2ArrayRead*: proc (self: GodotPoolVector2Array): ptr GodotPoolVector2ArrayReadAccess + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + poolVector2ArrayWrite*: proc (self: var GodotPoolVector2Array): ptr GodotPoolVector2ArrayWriteAccess + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + poolVector2ArraySet*: proc (self: var GodotPoolVector2Array, idx: cint, + data: Vector2) + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + poolVector2ArrayGet*: proc (self: GodotPoolVector2Array, idx: cint): Vector2Data + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + poolVector2ArraySize*: proc (self: GodotPoolVector2Array): cint + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + poolVector2ArrayDestroy*: proc (self: GodotPoolVector2Array) + {.noconv, raises: [], gcsafe, tags: [], + locks: 0.} + + # PoolVector3 API + poolVector3ArrayNew*: proc (dest: var GodotPoolVector3Array) + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + poolVector3ArrayNewCopy*: proc (dest: var GodotPoolVector3Array, + src: GodotPoolVector3Array) + {.noconv, raises: [], gcsafe, tags: [], + locks: 0.} + poolVector3ArrayNewWithArray*: proc (dest: var GodotPoolVector3Array, + src: GodotArray) + {.noconv, raises: [], gcsafe, tags: [], + locks: 0.} + poolVector3ArrayAppend*: proc (self: var GodotPoolVector3Array, val: Vector3) + {.noconv, raises: [], gcsafe, tags: [], + locks: 0.} + poolVector3ArrayAppendArray*: proc (self: var GodotPoolVector3Array, + arr: GodotPoolVector3Array) + {.noconv, raises: [], gcsafe, tags: [], + locks: 0.} + poolVector3ArrayInsert*: proc (self: var GodotPoolVector3Array, idx: cint, + val: Vector3): Error + {.noconv, raises: [], gcsafe, tags: [], + locks: 0.} + poolVector3ArrayInvert*: proc (self: var GodotPoolVector3Array) + {.noconv, raises: [], gcsafe, tags: [], + locks: 0.} + poolVector3ArrayPushBack*: proc (self: var GodotPoolVector3Array, + val: Vector3) {.noconv, raises: [], gcsafe, + tags: [], locks: 0.} + poolVector3ArrayRemove*: proc (self: var GodotPoolVector3Array, + idx: cint) {.noconv, raises: [], gcsafe, + tags: [], locks: 0.} + poolVector3ArrayResize*: proc (self: var GodotPoolVector3Array, + size: cint) {.noconv, raises: [], gcsafe, + tags: [], locks: 0.} + poolVector3ArrayRead*: proc (self: GodotPoolVector3Array): ptr GodotPoolVector3ArrayReadAccess + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + poolVector3ArrayWrite*: proc (self: var GodotPoolVector3Array): ptr GodotPoolVector3ArrayWriteAccess + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + poolVector3ArraySet*: proc (self: var GodotPoolVector3Array, idx: cint, + data: Vector3) {.noconv, raises: [], gcsafe, + tags: [], locks: 0.} + poolVector3ArrayGet*: proc (self: GodotPoolVector3Array, idx: cint): Vector3Data + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + poolVector3ArraySize*: proc (self: GodotPoolVector3Array): cint + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + poolVector3ArrayDestroy*: proc (self: GodotPoolVector3Array) + {.noconv, raises: [], gcsafe, tags: [], + locks: 0.} + + # PoolColorArray API + poolColorArrayNew*: proc (dest: var GodotPoolColorArray) + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + poolColorArrayNewCopy*: proc (dest: var GodotPoolColorArray, + src: GodotPoolColorArray) + {.noconv, raises: [], gcsafe, tags: [], + locks: 0.} + poolColorArrayNewWithArray*: proc (dest: var GodotPoolColorArray, + src: GodotArray) + {.noconv, raises: [], gcsafe, tags: [], + locks: 0.} + poolColorArrayAppend*: proc (self: var GodotPoolColorArray, + val: Color) + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + poolColorArrayAppendArray*: proc (self: var GodotPoolColorArray, + arr: GodotPoolColorArray) + {.noconv, raises: [], gcsafe, tags: [], + locks: 0.} + poolColorArrayInsert*: proc (self: var GodotPoolColorArray, + idx: cint, val: Color): Error + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + poolColorArrayInvert*: proc (self: var GodotPoolColorArray) + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + poolColorArrayPushBack*: proc (self: var GodotPoolColorArray, val: Color) + {.noconv, raises: [], gcsafe, tags: [], + locks: 0.} + poolColorArrayRemove*: proc (self: var GodotPoolColorArray, idx: cint) + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + poolColorArrayResize*: proc (self: var GodotPoolColorArray, size: cint) + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + poolColorArrayRead*: proc (self: GodotPoolColorArray): ptr GodotPoolColorArrayReadAccess + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + poolColorArrayWrite*: proc (self: var GodotPoolColorArray): ptr GodotPoolColorArrayWriteAccess + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + poolColorArraySet*: proc (self: var GodotPoolColorArray, idx: cint, + data: Color) + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + poolColorArrayGet*: proc (self: GodotPoolColorArray, idx: cint): ColorData + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + poolColorArraySize*: proc (self: GodotPoolColorArray): cint + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + poolColorArrayDestroy*: proc (self: GodotPoolColorArray) + {.noconv, raises: [], gcsafe, tags: [], + locks: 0.} + + # Pool Array Read/Write Access API + + poolByteArrayReadAccessCopy*: proc (self: ptr GodotPoolByteArrayReadAccess): ptr GodotPoolByteArrayReadAccess + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + poolByteArrayReadAccessPtr*: proc (self: ptr GodotPoolByteArrayReadAccess): ptr byte + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + poolByteArrayReadAccessOperatorAssign*: proc (self, other: ptr GodotPoolByteArrayReadAccess) + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + poolByteArrayReadAccessDestroy*: proc (self: ptr GodotPoolByteArrayReadAccess) + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + + poolIntArrayReadAccessCopy*: proc (self: ptr GodotPoolIntArrayReadAccess): ptr GodotPoolIntArrayReadAccess + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + poolIntArrayReadAccessPtr*: proc (self: ptr GodotPoolIntArrayReadAccess): ptr cint + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + poolIntArrayReadAccessOperatorAssign*: proc (self, other: ptr GodotPoolIntArrayReadAccess) + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + poolIntArrayReadAccessDestroy*: proc (self: ptr GodotPoolIntArrayReadAccess) + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + + poolRealArrayReadAccessCopy*: proc (self: ptr GodotPoolRealArrayReadAccess): ptr GodotPoolRealArrayReadAccess + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + poolRealArrayReadAccessPtr*: proc (self: ptr GodotPoolRealArrayReadAccess): ptr float32 + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + poolRealArrayReadAccessOperatorAssign*: proc (self, other: ptr GodotPoolRealArrayReadAccess) + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + poolRealArrayReadAccessDestroy*: proc (self: ptr GodotPoolRealArrayReadAccess) + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + + poolStringArrayReadAccessCopy*: proc (self: ptr GodotPoolStringArrayReadAccess): ptr GodotPoolStringArrayReadAccess + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + poolStringArrayReadAccessPtr*: proc (self: ptr GodotPoolStringArrayReadAccess): ptr GodotString + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + poolStringArrayReadAccessOperatorAssign*: proc (self, other: ptr GodotPoolStringArrayReadAccess) + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + poolStringArrayReadAccessDestroy*: proc (self: ptr GodotPoolStringArrayReadAccess) + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + + poolVector2ArrayReadAccessCopy*: proc (self: ptr GodotPoolVector2ArrayReadAccess): ptr GodotPoolVector2ArrayReadAccess + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + poolVector2ArrayReadAccessPtr*: proc (self: ptr GodotPoolVector2ArrayReadAccess): ptr Vector2 + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + poolVector2ArrayReadAccessOperatorAssign*: proc (self, other: ptr GodotPoolVector2ArrayReadAccess) + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + poolVector2ArrayReadAccessDestroy*: proc (self: ptr GodotPoolVector2ArrayReadAccess) + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + + poolVector3ArrayReadAccessCopy*: proc (self: ptr GodotPoolVector3ArrayReadAccess): ptr GodotPoolVector3ArrayReadAccess + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + poolVector3ArrayReadAccessPtr*: proc (self: ptr GodotPoolVector3ArrayReadAccess): ptr Vector3 + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + poolVector3ArrayReadAccessOperatorAssign*: proc (self, other: ptr GodotPoolVector3ArrayReadAccess) + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + poolVector3ArrayReadAccessDestroy*: proc (self: ptr GodotPoolVector3ArrayReadAccess) + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + + poolColorArrayReadAccessCopy*: proc (self: ptr GodotPoolColorArrayReadAccess): ptr GodotPoolColorArrayReadAccess + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + poolColorArrayReadAccessPtr*: proc (self: ptr GodotPoolColorArrayReadAccess): ptr Color + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + poolColorArrayReadAccessOperatorAssign*: proc (self, other: ptr GodotPoolColorArrayReadAccess) + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + poolColorArrayReadAccessDestroy*: proc (self: ptr GodotPoolColorArrayReadAccess) + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + + poolByteArrayWriteAccessCopy*: proc (self: ptr GodotPoolByteArrayWriteAccess): ptr GodotPoolByteArrayWriteAccess + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + poolByteArrayWriteAccessPtr*: proc (self: ptr GodotPoolByteArrayWriteAccess): ptr byte + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + poolByteArrayWriteAccessOperatorAssign*: proc (self, other: ptr GodotPoolByteArrayWriteAccess) + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + poolByteArrayWriteAccessDestroy*: proc (self: ptr GodotPoolByteArrayWriteAccess) + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + + poolIntArrayWriteAccessCopy*: proc (self: ptr GodotPoolIntArrayWriteAccess): ptr GodotPoolIntArrayWriteAccess + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + poolIntArrayWriteAccessPtr*: proc (self: ptr GodotPoolIntArrayWriteAccess): ptr cint + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + poolIntArrayWriteAccessOperatorAssign*: proc (self, other: ptr GodotPoolIntArrayWriteAccess) + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + poolIntArrayWriteAccessDestroy*: proc (self: ptr GodotPoolIntArrayWriteAccess) + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + + poolRealArrayWriteAccessCopy*: proc (self: ptr GodotPoolRealArrayWriteAccess): ptr GodotPoolRealArrayWriteAccess + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + poolRealArrayWriteAccessPtr*: proc (self: ptr GodotPoolRealArrayWriteAccess): ptr float32 + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + poolRealArrayWriteAccessOperatorAssign*: proc (self, other: ptr GodotPoolRealArrayWriteAccess) + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + poolRealArrayWriteAccessDestroy*: proc (self: ptr GodotPoolRealArrayWriteAccess) + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + + poolStringArrayWriteAccessCopy*: proc (self: ptr GodotPoolStringArrayWriteAccess): ptr GodotPoolStringArrayWriteAccess + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + poolStringArrayWriteAccessPtr*: proc (self: ptr GodotPoolStringArrayWriteAccess): ptr GodotString + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + poolStringArrayWriteAccessOperatorAssign*: proc (self, other: ptr GodotPoolStringArrayWriteAccess) + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + poolStringArrayWriteAccessDestroy*: proc (self: ptr GodotPoolStringArrayWriteAccess) + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + + poolVector2ArrayWriteAccessCopy*: proc (self: ptr GodotPoolVector2ArrayWriteAccess): ptr GodotPoolVector2ArrayWriteAccess + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + poolVector2ArrayWriteAccessPtr*: proc (self: ptr GodotPoolVector2ArrayWriteAccess): ptr Vector2 + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + poolVector2ArrayWriteAccessOperatorAssign*: proc (self, other: ptr GodotPoolVector2ArrayWriteAccess) + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + poolVector2ArrayWriteAccessDestroy*: proc (self: ptr GodotPoolVector2ArrayWriteAccess) + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + + poolVector3ArrayWriteAccessCopy*: proc (self: ptr GodotPoolVector3ArrayWriteAccess): ptr GodotPoolVector3ArrayWriteAccess + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + poolVector3ArrayWriteAccessPtr*: proc (self: ptr GodotPoolVector3ArrayWriteAccess): ptr Vector3 + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + poolVector3ArrayWriteAccessOperatorAssign*: proc (self, other: ptr GodotPoolVector3ArrayWriteAccess) + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + poolVector3ArrayWriteAccessDestroy*: proc (self: ptr GodotPoolVector3ArrayWriteAccess) + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + + poolColorArrayWriteAccessCopy*: proc (self: ptr GodotPoolColorArrayWriteAccess): ptr GodotPoolColorArrayWriteAccess + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + poolColorArrayWriteAccessPtr*: proc (self: ptr GodotPoolColorArrayWriteAccess): ptr Color + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + poolColorArrayWriteAccessOperatorAssign*: proc (self, other: ptr GodotPoolColorArrayWriteAccess) + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + poolColorArrayWriteAccessDestroy*: proc (self: ptr GodotPoolColorArrayWriteAccess) + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + + # Array API + arrayNew*: proc (dest: var GodotArray) + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + arrayNewCopy*: proc (dest: var GodotArray, src: GodotArray) + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + arrayNewPoolColorArray*: proc (dest: var GodotArray, src: GodotPoolColorArray) + {.noconv, raises: [], gcsafe, tags: [], + locks: 0.} + arrayNewPoolVector3Array*: proc (dest: var GodotArray, + src: GodotPoolVector3Array) + {.noconv, raises: [], gcsafe, tags: [], + locks: 0.} + arrayNewPoolVector2Array*: proc (dest: var GodotArray, + src: GodotPoolVector2Array) + {.noconv, raises: [], gcsafe, tags: [], + locks: 0.} + arrayNewPoolStringArray*: proc (dest: var GodotArray, + src: GodotPoolStringArray) + {.noconv, raises: [], gcsafe, tags: [], + locks: 0.} + arrayNewPoolRealArray*: proc (dest: var GodotArray, src: GodotPoolRealArray) + {.noconv, raises: [], gcsafe, tags: [], + locks: 0.} + arrayNewPoolIntArray*: proc (dest: var GodotArray, src: GodotPoolIntArray) + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + arrayNewPoolByteArray*: proc (dest: var GodotArray, src: GodotPoolByteArray) + {.noconv, raises: [], gcsafe, tags: [], + locks: 0.} + arraySet*: proc (self: var GodotArray, idx: cint, val: GodotVariant) + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + arrayGet*: proc (self: GodotArray, idx: cint): GodotVariant + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + arrayOperatorIndex*: proc (self: var GodotArray, idx: cint): ptr GodotVariant + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + arrayAppend*: proc (self: var GodotArray, val: GodotVariant) + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + arrayClear*: proc (self: var GodotArray) + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + arrayCount*: proc (self: GodotArray, val: GodotVariant): cint + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + arrayEmpty*: proc (self: GodotArray): bool + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + arrayErase*: proc (self: var GodotArray, val: GodotVariant) + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + arrayFront*: proc (self: GodotArray): GodotVariant + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + arrayBack*: proc (self: GodotArray): GodotVariant + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + arrayFind*: proc (self: GodotArray, what: GodotVariant, fromIdx: cint): cint + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + arrayFindLast*: proc (self: GodotArray, what: GodotVariant): cint + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + arrayHas*: proc (self: GodotArray, val: GodotVariant): bool + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + arrayHash*: proc (self: GodotArray): cint + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + arrayInsert*: proc (self: var GodotArray, pos: cint, val: GodotVariant): Error + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + arrayInvert*: proc (self: var GodotArray) + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + arrayPopFront*: proc (self: GodotArray): GodotVariant + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + arrayPopBack*: proc (self: GodotArray): GodotVariant + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + arrayPushBack*: proc (self: var GodotArray, val: GodotVariant) + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + arrayPushFront*: proc (self: var GodotArray, val: GodotVariant) + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + arrayRemove*: proc (self: var GodotArray, idx: cint) + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + arrayResize*: proc (self: var GodotArray, size: cint) + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + arrayRFind*: proc (self: GodotArray, what: GodotVariant, fromIdx: cint): cint + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + arraySize*: proc (self: GodotArray): cint + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + arraySort*: proc (self: var GodotArray) + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + arraySortCustom*: proc (self: var GodotArray, obj: ptr GodotObject, + f: GodotString) + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + arrayBSearch*: proc (self: var GodotArray, val: ptr GodotVariant, + before: bool) + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + arrayBSearchCustom*: proc (self: var GodotArray, val: ptr GodotVariant, + obj: ptr GodotObject, f: GodotString, + before: bool) + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + arrayDestroy*: proc (self: var GodotArray) + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + + # Dictionary API + dictionaryNew*: proc (dest: var GodotDictionary) + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + dictionaryNewCopy*: proc (dest: var GodotDictionary, src: GodotDictionary) + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + dictionaryDestroy*: proc (self: var GodotDictionary) + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + dictionarySize*: proc (self: GodotDictionary): cint + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + dictionaryEmpty*: proc (self: GodotDictionary): bool + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + dictionaryClear*: proc (self: var GodotDictionary) + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + dictionaryHas*: proc (self: GodotDictionary, key: GodotVariant): bool + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + dictionaryHasAll*: proc (self: GodotDictionary, keys: GodotArray): bool + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + dictionaryErase*: proc (self: var GodotDictionary, key: GodotVariant) + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + dictionaryHash*: proc (self: GodotDictionary): cint + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + dictionaryKeys*: proc (self: GodotDictionary): GodotArray + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + dictionaryValues*: proc (self: GodotDictionary): GodotArray + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + dictionaryGet*: proc (self: GodotDictionary, key: GodotVariant): GodotVariant + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + dictionarySet*: proc (self: var GodotDictionary, key, value: GodotVariant) + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + dictionaryOperatorIndex*: proc (self: var GodotDictionary, + key: GodotVariant): ptr GodotVariant + {.noconv, raises: [], gcsafe, tags: [], + locks: 0.} + dictionaryNext*: proc (self: GodotDictionary, + key: GodotVariant): ptr GodotVariant + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + dictionaryOperatorEqual*: proc (self, other: GodotDictionary): bool + {.noconv, raises: [], gcsafe, tags: [], + locks: 0.} + dictionaryToJson*: proc (self: GodotDictionary): GodotString + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + + # NodePath API + nodePathNew*: proc (dest: var GodotNodePath, src: GodotString) + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + nodePathNewCopy*: proc (dest: var GodotNodePath, src: GodotNodePath) + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + nodePathDestroy*: proc (self: var GodotNodePath) + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + nodePathAsString*: proc (self: GodotNodePath): GodotString + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + nodePathIsAbsolute*: proc (self: GodotNodePath): bool + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + nodePathGetNameCount*: proc (self: GodotNodePath): cint + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + nodePathGetName*: proc (self: GodotNodePath, idx: cint): GodotString + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + nodePathGetSubnameCount*: proc (self: GodotNodePath): cint + {.noconv, raises: [], gcsafe, tags: [], + locks: 0.} + nodePathGetSubname*: proc (self: GodotNodePath, idx: cint): GodotString + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + nodePathGetConcatenatedSubnames*: proc (self: GodotNodePath): GodotString + {.noconv, raises: [], gcsafe, + tags: [], locks: 0.} + nodePathIsEmpty*: proc (self: GodotNodePath): bool + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + nodePathOperatorEqual*: proc (self, other: GodotNodePath): bool + {.noconv, raises: [], gcsafe, tags: [], + locks: 0.} + + # Plane API + planeNewWithReals*: proc (dest: var Plane, a, b, c, d: float32) + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + planeNewWithVectors*: proc (dest: var Plane, v1, v2, v3: Vector3) + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + planeNewWithNormal*: proc (dest: var Plane, normal: Vector3, d: float32) + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + planeAsString*: proc (self: Plane): GodotString + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + planeNormalized*: proc (self: Plane): PlaneData + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + planeCenter*: proc (self: Plane): Vector3Data + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + planeGetAnyPoint*: proc (self: Plane): Vector3Data + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + planeIsPointOver*: proc (self: Plane, point: Vector3): bool + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + planeDistanceTo*: proc (self: Plane, point: Vector3): float32 + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + planeHasPoint*: proc (self: Plane, point: Vector3, epsilon: float32): bool + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + planeProject*: proc (self: Plane, point: Vector3): Vector3Data + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + planeIntersect3*: proc (self: Plane, dest: var Vector3, b, c: Plane): bool + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + planeIntersectsRay*: proc (self: Plane, dest: var Vector3, + point, dir: Vector3): bool + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + planeIntersectsSegment*: proc (self: Plane, dest: var Vector3, + segmentBegin, segmentEnd: Vector3): bool + {.noconv, raises: [], gcsafe, tags: [], + locks: 0.} + planeOperatorNeg*: proc (self: Plane): PlaneData + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + planeOperatorEqual*: proc (self, other: Plane): bool + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + planeSetNormal*: proc (self: var Plane, normal: Vector3) + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + planeGetNormal*: proc (self: Plane): Vector3Data + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + planeGetD*: proc (self: Plane): float32 + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + planeSetD*: proc (self: var Plane, d: float32) + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + + # Rect2 API + rect2NewWithPositionAndSize*: proc (dest: var Rect2, pos, size: Vector2) + {.noconv, raises: [], gcsafe, tags: [], + locks: 0.} + rect2New*: proc (dest: var Rect2, x, y, width, height: float32) + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + rect2AsString*: proc (self: Rect2): GodotString + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + rect2GetArea*: proc (self: Rect2): float32 + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + rect2Intersects*: proc (self, other: Rect2): bool + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + rect2Encloses*: proc (self, other: Rect2): bool + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + rect2HasNoArea*: proc (self: Rect2): bool + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + rect2Clip*: proc (self, other: Rect2): Rect2Data + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + rect2Merge*: proc (self, other: Rect2): Rect2Data + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + rect2HasPoint*: proc (self: Rect2, point: Vector2): bool + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + rect2Grow*: proc (self: Rect2, by: float32): Rect2Data + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + rect2Expand*: proc (self: Rect2, to: Vector2): Rect2Data + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + rect2OperatorEqual*: proc (self, other: Rect2): bool + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + rect2GetPosition*: proc (self: Rect2): Vector2Data + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + rect2GetSize*: proc (self: Rect2): Vector2Data + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + rect2SetPosition*: proc (self: var Rect2, pos: Vector2) + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + rect2SetSize*: proc (self: var Rect2, size: Vector2) + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + + # AABB API + aabbNew*: proc (dest: var AABB, pos, size: Vector3) + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + aabbGetPosition*: proc (self: AABB): Vector3Data + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + aabbSetPosition*: proc (self: var AABB, pos: Vector3) + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + aabbGetSize*: proc (self: AABB): Vector3Data + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + aabbSetSize*: proc (self: var AABB, pos: Vector3) + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + aabbAsString*: proc (self: AABB): GodotString + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + aabbGetArea*: proc (self: AABB): float32 + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + aabbHasNoArea*: proc (self: AABB): bool + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + aabbHasNoSurface*: proc (self: AABB): bool + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + aabbIntersects*: proc (self, other: AABB): bool + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + aabbEncloses*: proc (self, other: AABB): bool + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + aabbMerge*: proc (self, other: AABB): AABBData + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + aabbIntersection*: proc (self, other: AABB): AABBData + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + aabbIntersectsPlane*: proc (self: AABB, plane: Plane): bool + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + aabbIntersectsSegment*: proc (self: AABB, vFrom, vTo: Vector3): bool + {.noconv, raises: [], gcsafe, tags: [], + locks: 0.} + aabbHasPoint*: proc (self: AABB, point: Vector3): bool + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + aabbGetSupport*: proc (self: AABB, dir: Vector3): Vector3Data + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + aabbGetLongestAxis*: proc (self: AABB): Vector3Data + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + aabbGetLongestAxisIndex*: proc (self: AABB): cint + {.noconv, raises: [], gcsafe, tags: [], + locks: 0.} + aabbGetLongestAxisSize*: proc (self: AABB): float32 + {.noconv, raises: [], gcsafe, tags: [], + locks: 0.} + aabbGetShortestAxis*: proc (self: AABB): Vector3Data + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + aabbGetShortestAxisIndex*: proc (self: AABB): cint + {.noconv, raises: [], gcsafe, tags: [], + locks: 0.} + aabbGetShortestAxisSize*: proc (self: AABB): float32 + {.noconv, raises: [], gcsafe, tags: [], + locks: 0.} + aabbExpand*: proc (self: AABB, toPoint: Vector3): AABBData + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + aabbGrow*: proc (self: AABB, by: float32): AABBData + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + aabbGetEndpoint*: proc (self: AABB, idx: cint): Vector3Data + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + aabbOperatorEqual*: proc (self, other: AABB): bool + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + + # RID API + ridNew*: proc (dest: var RID) + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + ridGetID*: proc (self: RID): cint + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + ridNewWithResource*: proc (dest: var RID, obj: ptr GodotObject) + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + ridOperatorEqual*: proc (self, other: RID): bool + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + ridOperatorLess*: proc (self, other: RID): bool + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + + # Transform API + transformNewWithAxisOrigin*: proc (dest: var Transform, + xAxis, yAxis, zAxis, origin: Vector3) + {.noconv, raises: [], gcsafe, tags: [], + locks: 0.} + transformNew*: proc (dest: var Transform, basis: Basis, origin: Vector3) + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + transformGetBasis*: proc (self: Transform): BasisData + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + transformSetBasis*: proc (self: var Transform, basis: Basis) + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + transformGetOrigin*: proc (self: Transform): Vector3Data + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + transformSetOrigin*: proc (self: var Transform, v: Vector3) + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + transformAsString*: proc (self: Transform): GodotString + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + transformInverse*: proc (self: Transform): TransformData + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + transformAffineInverse*: proc (self: Transform): TransformData + {.noconv, raises: [], gcsafe, tags: [], + locks: 0.} + transformOrthonormalized*: proc (self: Transform): TransformData + {.noconv, raises: [], gcsafe, tags: [], + locks: 0.} + transformRotated*: proc (self: Transform, axis: Vector3, + phi: float32): TransformData + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + transformScaled*: proc (self: Transform, scale: Vector3): TransformData + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + transformTranslated*: proc (self: Transform, offset: Vector3): TransformData + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + transformLookingAt*: proc (self: Transform, target, up: Vector3): TransformData + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + transformXformPlane*: proc (self: Transform, plane: Plane): PlaneData + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + transformXformInvPlane*: proc (self: Transform, plane: Plane): PlaneData + {.noconv, raises: [], gcsafe, tags: [], + locks: 0.} + transformNewIdentity*: proc (dest: var Transform) + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + transformOperatorEqual*: proc (self, other: Transform): bool + {.noconv, raises: [], gcsafe, tags: [], + locks: 0.} + transformOperatorMultiply*: proc (self, other: Transform): TransformData + {.noconv, raises: [], gcsafe, tags: [], + locks: 0.} + transformXformVector3*: proc (self: Transform, v: Vector3): Vector3Data + {.noconv, raises: [], gcsafe, tags: [], + locks: 0.} + transformXformInvVector3*: proc (self: Transform, v: Vector3): Vector3Data + {.noconv, raises: [], gcsafe, tags: [], + locks: 0.} + transformXformAABB*: proc (self: Transform, v: AABB): AABBData + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + transformXformInvAABB*: proc (self: Transform, v: AABB): AABBData + {.noconv, raises: [], gcsafe, tags: [], + locks: 0.} + + # Transform2D API + transform2DNew*: proc (dest: var Transform2D, rot: float32, pos: Vector2) + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + transform2DNewAxisOrigin*: proc (dest: var Transform2D, + xAxis, yAxis, origin: Vector2) + {.noconv, raises: [], gcsafe, tags: [], + locks: 0.} + transform2DAsString*: proc (self: Transform2D): GodotString + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + transform2DInverse*: proc (self: Transform2D): Transform2DData + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + transform2DAffineInverse*: proc (self: Transform2D): Transform2DData + {.noconv, raises: [], gcsafe, tags: [], + locks: 0.} + transform2DGetRotation*: proc (self: Transform2D): float32 + {.noconv, raises: [], gcsafe, tags: [], + locks: 0.} + transform2DGetOrigin*: proc (self: Transform2D): Vector2Data + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + transform2DGetScale*: proc (self: Transform2D): Vector2Data + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + transform2DOrthonormalized*: proc (self: Transform2D): Transform2DData + {.noconv, raises: [], gcsafe, tags: [], + locks: 0.} + transform2DRotated*: proc (self: Transform2D, phi: float32): Transform2DData + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + transform2DScaled*: proc (self: Transform2D, scale: Vector2): Transform2DData + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + transform2DTranslated*: proc (self: Transform2D, offset: Vector2): Transform2DData + {.noconv, raises: [], gcsafe, tags: [], + locks: 0.} + transform2DXformVector2*: proc (self: Transform2D, v: Vector2): Vector2Data + {.noconv, raises: [], gcsafe, tags: [], + locks: 0.} + transform2DXformInvVector2*: proc (self: Transform2D, v: Vector2): Vector2Data + {.noconv, raises: [], gcsafe, tags: [], + locks: 0.} + transform2DBasisXformVector2*: proc (self: Transform2D, v: Vector2): Vector2Data + {.noconv, raises: [], gcsafe, tags: [], + locks: 0.} + transform2DBasisXformInvVector2*: proc (self: Transform2D, + v: Vector2): Vector2Data + {.noconv, raises: [], gcsafe, tags: [], + locks: 0.} + transform2DInterpolateWith*: proc (self, other: Transform2D, + t: float32): Transform2DData + {.noconv, raises: [], gcsafe, tags: [], + locks: 0.} + transform2DOperatorEqual*: proc (self, other: Transform2D): bool + {.noconv, raises: [], gcsafe, tags: [], + locks: 0.} + transform2DOperatorMultiply*: proc (self, other: Transform2D): Transform2DData + {.noconv, raises: [], gcsafe, tags: [], + locks: 0.} + transform2DNewIdentity*: proc (dest: var Transform2D) + {.noconv, raises: [], gcsafe, tags: [], + locks: 0.} + transform2DXformRect2*: proc (self: Transform2D, v: Rect2): Rect2Data + {.noconv, raises: [], gcsafe, tags: [], + locks: 0.} + transform2DXformInvRect2*: proc (self: Transform2D, v: Rect2): Rect2Data + {.noconv, raises: [], gcsafe, tags: [], + locks: 0.} + + # Variant API + variantGetType*: proc (v: GodotVariant): VariantType + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + variantNewCopy*: proc (dest: var GodotVariant, src: GodotVariant) + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + variantNewNil*: proc (dest: var GodotVariant) + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + variantNewBool*: proc (dest: var GodotVariant, val: bool) + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + variantNewUInt*: proc (dest: var GodotVariant, val: uint64) + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + variantNewInt*: proc (dest: var GodotVariant, val: int64) + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + variantNewReal*: proc (dest: var GodotVariant, val: float64) + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + variantNewString*: proc (dest: var GodotVariant, val: GodotString) + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + variantNewVector2*: proc (dest: var GodotVariant, val: Vector2) + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + variantNewRect2*: proc (dest: var GodotVariant, val: Rect2) + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + variantNewVector3*: proc (dest: var GodotVariant, val: Vector3) + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + variantNewTransform2D*: proc (dest: var GodotVariant, val: Transform2D) + {.noconv, raises: [], gcsafe, tags: [], + locks: 0.} + variantNewPlane*: proc (dest: var GodotVariant, val: Plane) + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + variantNewQuat*: proc (dest: var GodotVariant, val: Quat) + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + variantNewAABB*: proc (dest: var GodotVariant, val: AABB) + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + variantNewBasis*: proc (dest: var GodotVariant, val: Basis) + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + variantNewTransform*: proc (dest: var GodotVariant, val: Transform) + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + variantNewColor*: proc (dest: var GodotVariant, val: Color) + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + variantNewNodePath*: proc (dest: var GodotVariant, val: GodotNodePath) + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + variantNewRID*: proc (dest: var GodotVariant, val: RID) + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + variantNewObject*: proc (dest: var GodotVariant, val: ptr GodotObject) + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + variantNewDictionary*: proc (dest: var GodotVariant, val: GodotDictionary) + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + variantNewArray*: proc (dest: var GodotVariant, val: GodotArray) + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + variantNewPoolByteArray*: proc (dest: var GodotVariant, + val: GodotPoolByteArray) + {.noconv, raises: [], gcsafe, tags: [], + locks: 0.} + variantNewPoolIntArray*: proc (dest: var GodotVariant, val: GodotPoolIntArray) + {.noconv, raises: [], gcsafe, tags: [], + locks: 0.} + variantNewPoolRealArray*: proc (dest: var GodotVariant, + val: GodotPoolRealArray) + {.noconv, raises: [], gcsafe, tags: [], + locks: 0.} + variantNewPoolStringArray*: proc (dest: var GodotVariant, + val: GodotPoolStringArray) + {.noconv, raises: [], gcsafe, tags: [], + locks: 0.} + variantNewPoolVector2Array*: proc (dest: var GodotVariant, + val: GodotPoolVector2Array) + {.noconv, raises: [], gcsafe, tags: [], + locks: 0.} + variantNewPoolVector3Array*: proc (dest: var GodotVariant, + val: GodotPoolVector3Array) + {.noconv, raises: [], gcsafe, tags: [], + locks: 0.} + variantNewPoolColorArray*: proc (dest: var GodotVariant, + val: GodotPoolColorArray) + {.noconv, raises: [], gcsafe, tags: [], + locks: 0.} + variantAsBool*: proc (self: GodotVariant): bool + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + variantAsUInt*: proc (self: GodotVariant): uint64 + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + variantAsInt*: proc (self: GodotVariant): int64 + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + variantAsReal*: proc (self: GodotVariant): float64 + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + variantAsString*: proc (self: GodotVariant): GodotString + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + variantAsVector2*: proc (self: GodotVariant): Vector2Data + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + variantAsRect2*: proc (self: GodotVariant): Rect2Data + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + variantAsVector3*: proc (self: GodotVariant): Vector3Data + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + variantAsTransform2D*: proc (self: GodotVariant): Transform2DData + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + variantAsPlane*: proc (self: GodotVariant): PlaneData + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + variantAsQuat*: proc (self: GodotVariant): QuatData + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + variantAsAABB*: proc (self: GodotVariant): AABBData + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + variantAsBasis*: proc (self: GodotVariant): BasisData + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + variantAsTransform*: proc (self: GodotVariant): TransformData + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + variantAsColor*: proc (self: GodotVariant): ColorData + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + variantAsNodePath*: proc (self: GodotVariant): GodotNodePath + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + variantAsRID*: proc (self: GodotVariant): RID + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + variantAsObject*: proc (self: GodotVariant): ptr GodotObject + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + variantAsDictionary*: proc (self: GodotVariant): GodotDictionary + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + variantAsArray*: proc (self: GodotVariant): GodotArray + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + variantAsPoolByteArray*: proc (self: GodotVariant): GodotPoolByteArray + {.noconv, raises: [], gcsafe, tags: [], + locks: 0.} + variantAsPoolIntArray*: proc (self: GodotVariant): GodotPoolIntArray + {.noconv, raises: [], gcsafe, tags: [], + locks: 0.} + variantAsPoolRealArray*: proc (self: GodotVariant): GodotPoolRealArray + {.noconv, raises: [], gcsafe, tags: [], + locks: 0.} + variantAsPoolStringArray*: proc (self: GodotVariant): GodotPoolStringArray + {.noconv, raises: [], gcsafe, tags: [], + locks: 0.} + variantAsPoolVector2Array*: proc (self: GodotVariant): GodotPoolVector2Array + {.noconv, raises: [], gcsafe, tags: [], + locks: 0.} + variantAsPoolVector3Array*: proc (self: GodotVariant): GodotPoolVector3Array + {.noconv, raises: [], gcsafe, tags: [], + locks: 0.} + variantAsPoolColorArray*: proc (self: GodotVariant): GodotPoolColorArray + {.noconv, raises: [], gcsafe, tags: [], + locks: 0.} + variantCall*: proc (self: var GodotVariant, meth: GodotString, + args: ptr array[MAX_ARG_COUNT, ptr GodotVariant], + argcount: cint, + callError: var VariantCallError): GodotVariant + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + variantHasMethod*: proc (self: GodotVariant, meth: GodotString): bool + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + variantOperatorEqual*: proc (self, other: GodotVariant): bool + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + variantOperatorLess*: proc (self, other: GodotVariant): bool + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + variantHashCompare*: proc (self, other: GodotVariant): bool + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + variantBooleanize*: proc (self: GodotVariant): bool + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + variantDestroy*: proc (self: var GodotVariant) + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + + # String API + charStringLength*: proc (self: GodotCharString): cint + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + charStringGetData*: proc (self: GodotCharString): cstring + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + charStringDestroy*: proc (self: var GodotCharString) + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + stringNew*: proc (dest: var GodotString) + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + stringNewCopy*: proc (dest: var GodotString, src: GodotString) + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + stringWideStr*: proc (self: GodotString): ptr cwchar_t + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + stringOperatorEqual*: proc (self, other: GodotString): bool + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + stringOperatorLess*: proc (self, other: GodotString): bool + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + stringOperatorPlus*: proc (self, other: GodotString): GodotString + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + stringLength*: proc (self: GodotString): cint + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + stringDestroy*: proc (self: var GodotString) + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + stringUtf8*: proc (self: GodotString): GodotCharString + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + stringCharsToUtf8*: proc (str: cstring): GodotString + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + stringCharsToUtf8WithLen*: proc (str: cstring, len: cint): GodotString + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + + # Misc API + objectDestroy*: proc (self: ptr GodotObject) + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + globalGetSingleton*: proc (name: cstring): ptr GodotObject + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + methodBindGetMethod*: proc (className, + methodName: cstring): ptr GodotMethodBind + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + methodBindPtrCall*: proc (methodBind: ptr GodotMethodBind, + obj: ptr GodotObject, + args: ptr array[MAX_ARG_COUNT, pointer], + ret: pointer) + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + methodBindCall*: proc (methodBind: ptr GodotMethodBind, obj: ptr GodotObject, + args: ptr array[MAX_ARG_COUNT, ptr GodotVariant], + argCount: cint, + callError: var VariantCallError): GodotVariant + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + getClassConstructor*: proc (className: cstring): GodotClassConstructor + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + + alloc*: proc (bytes: cint): pointer + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + realloc*: proc (p: pointer, bytes: cint): pointer + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + free*: proc (p: pointer) {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + + printError*: proc (description, function, file: cstring, line: cint) + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + printWarning*: proc (description, function, file: cstring, line: cint) + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + print*: proc (message: GodotString) + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + + nativeScriptRegisterClass*: proc (gdnativeHandle: pointer, + name, base: cstring, + createFunc: GodotInstanceCreateFunc, + destroyFunc: GodotInstanceDestroyFunc) + {.noconv, raises: [], gcsafe, tags: [], + locks: 0.} + nativeScriptRegisterToolClass*: proc (gdnativeHandle: pointer, + name, base: cstring, + createFunc: GodotInstanceCreateFunc, + destroyFunc: GodotInstanceDestroyFunc) + {.noconv, raises: [], gcsafe, tags: [], + locks: 0.} + nativeScriptRegisterMethod*: proc (gdnativeHandle: pointer, + name, functionName: cstring, + attr: GodotMethodAttributes, + meth: GodotInstanceMethod) + {.noconv, raises: [], gcsafe, tags: [], + locks: 0.} + nativeScriptRegisterProperty*: proc (gdnativeHandle: pointer, + name, path: cstring, + attr: ptr GodotPropertyAttributes, + setFunc: GodotPropertySetFunc, + getFunc: GodotPropertyGetFunc) + {.noconv, raises: [], gcsafe, tags: [], + locks: 0.} + nativeScriptRegisterSignal*: proc (gdnativeHandle: pointer, name: cstring, + signal: GodotSignal) + {.noconv, raises: [], gcsafe, tags: [], + locks: 0.} + nativeScriptGetUserdata*: proc (obj: ptr GodotObject): pointer + {.noconv, raises: [], gcsafe, tags: [], + locks: 0.} + +{.push stackTrace: off.} +proc toColor*(val: ColorData): Color {.inline, noinit.} = + cast[Color](val) + +proc toVector3*(val: Vector3Data): Vector3 {.inline, noinit.} = + cast[Vector3](val) + +proc toVector2*(val: Vector2Data): Vector2 {.inline, noinit.} = + cast[Vector2](val) + +proc toPlane*(val: PlaneData): Plane {.inline, noinit.} = + cast[Plane](val) + +proc toBasis*(val: BasisData): Basis {.inline, noinit.} = + cast[Basis](val) + +proc toQuat*(val: QuatData): Quat {.inline, noinit.} = + cast[Quat](val) + +proc toAABB*(val: AABBData): AABB {.inline, noinit.} = + cast[AABB](val) + +proc toRect2*(val: Rect2Data): Rect2 {.inline, noinit.} = + cast[Rect2](val) + +proc toTransform2D*(val: Transform2DData): Transform2D {.inline, noinit.} = + cast[Transform2D](val) + +proc toTransform*(val: TransformData): Transform {.inline, noinit.} = + cast[Transform](val) +{.pop.} + +macro assign(dest, src: typed, values: untyped): typed = + result = newStmtList() + for val in values: + result.add(newNimNode(nnkAsgn).add( + newNimNode(nnkDotExpr).add(dest, val), + newNimNode(nnkDotExpr).add(src, val))) + +var gdNativeAPI: GDNativeAPI + +proc getGDNativeAPI*(): ptr GDNativeAPI {.inline.} = + addr gdNativeAPI + +proc setGDNativeAPIInternal(apiStruct: pointer, initOptions: ptr GDNativeInitOptions, + foundCoreApi: var bool, foundNativeScriptApi: var bool) = + let header = cast[ptr GDNativeAPIHeader](apiStruct) + + if header.typ >= ord(low(GDNativeAPIType)).cuint and header.typ <= ord(high(GDNativeAPIType)).cuint: + let typ = GDNativeAPIType(header.typ) + case typ: + of GDNativeCore: + let coreApi = cast[ptr GDNativeCoreAPI1](apiStruct) + if coreApi[].version.major == 1 and coreApi[].version.minor == 0: + assign(gdNativeApi, coreApi[]): + # Color API + colorNewRGBA + colorNewRGB + colorGetR + colorSetR + colorGetG + colorSetG + colorGetB + colorSetB + colorGetA + colorSetA + colorGetH + colorGetS + colorGetV + colorAsString + colorToRGBA32 + colorAsARGB32 + colorGray + colorInverted + colorContrasted + colorLinearInterpolate + colorBlend + colorToHtml + colorOperatorEqual + colorOperatorLess + + # Vector 2 API + vector2New + vector2AsString + vector2Normalized + vector2Length + vector2Angle + vector2LengthSquared + vector2IsNormalized + vector2DistanceTo + vector2DistanceSquaredTo + vector2AngleTo + vector2AngleToPoint + vector2LinearInterpolate + vector2CubicInterpolate + vector2Rotated + vector2Tangent + vector2Floor + vector2Snapped + vector2Aspect + vector2Dot + vector2Slide + vector2Bounce + vector2Reflect + vector2Abs + vector2Clamped + vector2OperatorAdd + vector2OperatorSubtract + vector2OperatorMultiplyVector + vector2OperatorMultiplyScalar + vector2OperatorDivideVector + vector2OperatorDivideScalar + vector2OperatorEqual + vector2OperatorLess + vector2OperatorNeg + + # Quat API + quatNew + quatNewWithAxisAngle + quatGetX + quatSetX + quatGetY + quatSetY + quatGetZ + quatSetZ + quatGetW + quatSetW + quatAsString + quatLength + quatLengthSquared + quatNormalized + quatIsNormalized + quatInverse + quatDot + quatXform + quatSlerp + quatSlerpni + quatCubicSlerp + quatOperatorMultiply + quatOperatorAdd + quatOperatorSubtract + quatOperatorDivide + quatOperatorEqual + quatOperatorNeg + + # PoolByteArray API + poolByteArrayNew + poolByteArrayNewCopy + poolByteArrayNewWithArray + poolByteArrayAppend + poolByteArrayAppendArray + poolByteArrayInsert + poolByteArrayInvert + poolByteArrayPushBack + poolByteArrayRemove + poolByteArrayResize + poolByteArrayRead + poolByteArrayWrite + poolByteArraySet + poolByteArrayGet + poolByteArraySize + poolByteArrayDestroy + + # PoolIntArray API + poolIntArrayNew + poolIntArrayNewCopy + poolIntArrayNewWithArray + poolIntArrayAppend + poolIntArrayAppendArray + poolIntArrayInsert + poolIntArrayInvert + poolIntArrayPushBack + poolIntArrayRemove + poolIntArrayResize + poolIntArrayRead + poolIntArrayWrite + poolIntArraySet + poolIntArrayGet + poolIntArraySize + poolIntArrayDestroy + + # PoolRealArray API + poolRealArrayNew + poolRealArrayNewCopy + poolRealArrayNewWithArray + poolRealArrayAppend + poolRealArrayAppendArray + poolRealArrayInsert + poolRealArrayInvert + poolRealArrayPushBack + poolRealArrayRemove + poolRealArrayResize + poolRealArrayRead + poolRealArrayWrite + poolRealArraySet + poolRealArrayGet + poolRealArraySize + poolRealArrayDestroy + + # PoolStringArray API + poolStringArrayNew + poolStringArrayNewCopy + poolStringArrayNewWithArray + poolStringArrayAppend + poolStringArrayAppendArray + poolStringArrayInsert + poolStringArrayInvert + poolStringArrayPushBack + poolStringArrayRemove + poolStringArrayResize + poolStringArrayRead + poolStringArrayWrite + poolStringArraySet + poolStringArrayGet + poolStringArraySize + poolStringArrayDestroy + + + # PoolVector2 API + poolVector2ArrayNew + poolVector2ArrayNewCopy + poolVector2ArrayNewWithArray + poolVector2ArrayAppend + poolVector2ArrayAppendArray + poolVector2ArrayInsert + poolVector2ArrayInvert + poolVector2ArrayPushBack + poolVector2ArrayRemove + poolVector2ArrayResize + poolVector2ArrayRead + poolVector2ArrayWrite + poolVector2ArraySet + poolVector2ArrayGet + poolVector2ArraySize + poolVector2ArrayDestroy + + # PoolVector3 API + poolVector3ArrayNew + poolVector3ArrayNewCopy + poolVector3ArrayNewWithArray + poolVector3ArrayAppend + poolVector3ArrayAppendArray + poolVector3ArrayInsert + poolVector3ArrayInvert + poolVector3ArrayPushBack + poolVector3ArrayRemove + poolVector3ArrayResize + poolVector3ArrayRead + poolVector3ArrayWrite + poolVector3ArraySet + poolVector3ArrayGet + poolVector3ArraySize + poolVector3ArrayDestroy + + # PoolColorArray API + poolColorArrayNew + poolColorArrayNewCopy + poolColorArrayNewWithArray + poolColorArrayAppend + poolColorArrayAppendArray + poolColorArrayInsert + poolColorArrayInvert + poolColorArrayPushBack + poolColorArrayRemove + poolColorArrayResize + poolColorArrayRead + poolColorArrayWrite + poolColorArraySet + poolColorArrayGet + poolColorArraySize + poolColorArrayDestroy + + # Array API + arrayNew + arrayNewCopy + arrayNewPoolColorArray + arrayNewPoolVector3Array + arrayNewPoolVector2Array + arrayNewPoolStringArray + arrayNewPoolRealArray + arrayNewPoolIntArray + arrayNewPoolByteArray + arraySet + arrayGet + arrayOperatorIndex + arrayAppend + arrayClear + arrayCount + arrayEmpty + arrayErase + arrayFront + arrayBack + arrayFind + arrayFindLast + arrayHas + arrayHash + arrayInsert + arrayInvert + arrayPopFront + arrayPopBack + arrayPushBack + arrayPushFront + arrayRemove + arrayResize + arrayRFind + arraySize + arraySort + arraySortCustom + arrayBSearch + arrayBSearchCustom + arrayDestroy + + # Pool Array Read/Write Access API + + poolByteArrayReadAccessCopy + poolByteArrayReadAccessPtr + poolByteArrayReadAccessOperatorAssign + poolByteArrayReadAccessDestroy + + poolIntArrayReadAccessCopy + poolIntArrayReadAccessPtr + poolIntArrayReadAccessOperatorAssign + poolIntArrayReadAccessDestroy + + poolRealArrayReadAccessCopy + poolRealArrayReadAccessPtr + poolRealArrayReadAccessOperatorAssign + poolRealArrayReadAccessDestroy + + poolStringArrayReadAccessCopy + poolStringArrayReadAccessPtr + poolStringArrayReadAccessOperatorAssign + poolStringArrayReadAccessDestroy + + poolVector2ArrayReadAccessCopy + poolVector2ArrayReadAccessPtr + poolVector2ArrayReadAccessOperatorAssign + poolVector2ArrayReadAccessDestroy + + poolVector3ArrayReadAccessCopy + poolVector3ArrayReadAccessPtr + poolVector3ArrayReadAccessOperatorAssign + poolVector3ArrayReadAccessDestroy + + poolColorArrayReadAccessCopy + poolColorArrayReadAccessPtr + poolColorArrayReadAccessOperatorAssign + poolColorArrayReadAccessDestroy + + poolByteArrayWriteAccessCopy + poolByteArrayWriteAccessPtr + poolByteArrayWriteAccessOperatorAssign + poolByteArrayWriteAccessDestroy + + poolIntArrayWriteAccessCopy + poolIntArrayWriteAccessPtr + poolIntArrayWriteAccessOperatorAssign + poolIntArrayWriteAccessDestroy + + poolRealArrayWriteAccessCopy + poolRealArrayWriteAccessPtr + poolRealArrayWriteAccessOperatorAssign + poolRealArrayWriteAccessDestroy + + poolStringArrayWriteAccessCopy + poolStringArrayWriteAccessPtr + poolStringArrayWriteAccessOperatorAssign + poolStringArrayWriteAccessDestroy + + poolVector2ArrayWriteAccessCopy + poolVector2ArrayWriteAccessPtr + poolVector2ArrayWriteAccessOperatorAssign + poolVector2ArrayWriteAccessDestroy + + poolVector3ArrayWriteAccessCopy + poolVector3ArrayWriteAccessPtr + poolVector3ArrayWriteAccessOperatorAssign + poolVector3ArrayWriteAccessDestroy + + poolColorArrayWriteAccessCopy + poolColorArrayWriteAccessPtr + poolColorArrayWriteAccessOperatorAssign + poolColorArrayWriteAccessDestroy + + # Dictionary API + dictionaryNew + dictionaryNewCopy + dictionaryDestroy + dictionarySize + dictionaryEmpty + dictionaryClear + dictionaryHas + dictionaryHasAll + dictionaryErase + dictionaryHash + dictionaryKeys + dictionaryValues + dictionaryGet + dictionarySet + dictionaryOperatorIndex + dictionaryNext + dictionaryOperatorEqual + dictionaryToJson + + # NodePath API + nodePathNew + nodePathNewCopy + nodePathDestroy + nodePathAsString + nodePathIsAbsolute + nodePathGetNameCount + nodePathGetName + nodePathGetSubnameCount + nodePathGetSubname + nodePathGetConcatenatedSubnames + nodePathIsEmpty + nodePathOperatorEqual + + # Plane API + planeNewWithReals + planeNewWithVectors + planeNewWithNormal + planeAsString + planeNormalized + planeCenter + planeGetAnyPoint + planeIsPointOver + planeDistanceTo + planeHasPoint + planeProject + planeIntersect3 + planeIntersectsRay + planeIntersectsSegment + planeOperatorNeg + planeOperatorEqual + planeSetNormal + planeGetNormal + planeGetD + planeSetD + + # Rect2 API + rect2NewWithPositionAndSize + rect2New + rect2AsString + rect2GetArea + rect2Intersects + rect2Encloses + rect2HasNoArea + rect2Clip + rect2Merge + rect2HasPoint + rect2Grow + rect2Expand + rect2OperatorEqual + rect2GetPosition + rect2GetSize + rect2SetPosition + rect2SetSize + + # AABB API + aabbNew + aabbGetPosition + aabbSetPosition + aabbGetSize + aabbSetSize + aabbAsString + aabbGetArea + aabbHasNoArea + aabbHasNoSurface + aabbIntersects + aabbEncloses + aabbMerge + aabbIntersection + aabbIntersectsPlane + aabbIntersectsSegment + aabbHasPoint + aabbGetSupport + aabbGetLongestAxis + aabbGetLongestAxisIndex + aabbGetLongestAxisSize + aabbGetShortestAxis + aabbGetShortestAxisIndex + aabbGetShortestAxisSize + aabbExpand + aabbGrow + aabbGetEndpoint + aabbOperatorEqual + + # RID API + ridNew + ridGetID + ridNewWithResource + ridOperatorEqual + ridOperatorLess + + # Transform API + transformNewWithAxisOrigin + transformNew + transformGetBasis + transformSetBasis + transformGetOrigin + transformSetOrigin + transformAsString + transformInverse + transformAffineInverse + transformOrthonormalized + transformRotated + transformScaled + transformTranslated + transformLookingAt + transformXformPlane + transformXformInvPlane + transformNewIdentity + transformOperatorEqual + transformOperatorMultiply + transformXformVector3 + transformXformInvVector3 + transformXformAABB + transformXformInvAABB + + # Transform2D API + transform2DNew + transform2DNewAxisOrigin + transform2DAsString + transform2DInverse + transform2DAffineInverse + transform2DGetRotation + transform2DGetOrigin + transform2DGetScale + transform2DOrthonormalized + transform2DRotated + transform2DScaled + transform2DTranslated + transform2DXformVector2 + transform2DXformInvVector2 + transform2DBasisXformVector2 + transform2DBasisXformInvVector2 + transform2DInterpolateWith + transform2DOperatorEqual + transform2DOperatorMultiply + transform2DNewIdentity + transform2DXformRect2 + transform2DXformInvRect2 + + # Variant API + variantGetType + variantNewCopy + variantNewNil + variantNewBool + variantNewUInt + variantNewInt + variantNewReal + variantNewString + variantNewVector2 + variantNewRect2 + variantNewVector3 + variantNewTransform2D + + variantNewPlane + variantNewQuat + variantNewAABB + variantNewBasis + variantNewTransform + variantNewColor + variantNewNodePath + variantNewRID + variantNewObject + variantNewDictionary + variantNewArray + variantNewPoolByteArray + variantNewPoolIntArray + variantNewPoolRealArray + variantNewPoolStringArray + variantNewPoolVector2Array + variantNewPoolVector3Array + variantNewPoolColorArray + variantAsBool + variantAsUInt + variantAsInt + variantAsReal + variantAsString + variantAsVector2 + variantAsRect2 + variantAsVector3 + variantAsTransform2D + variantAsPlane + variantAsQuat + variantAsAABB + variantAsBasis + variantAsTransform + variantAsColor + variantAsNodePath + variantAsRID + variantAsObject + variantAsDictionary + variantAsArray + variantAsPoolByteArray + variantAsPoolIntArray + variantAsPoolRealArray + variantAsPoolStringArray + variantAsPoolVector2Array + variantAsPoolVector3Array + variantAsPoolColorArray + variantCall + variantHasMethod + variantOperatorEqual + variantOperatorLess + variantHashCompare + variantBooleanize + variantDestroy + + # String API + charStringLength + charStringGetData + charStringDestroy + + stringNew + stringNewCopy + stringWideStr + stringOperatorEqual + stringOperatorLess + stringOperatorPlus + stringLength + stringDestroy + stringUtf8 + stringCharsToUtf8 + stringCharsToUtf8WithLen + + # Misc API + objectDestroy + globalGetSingleton + methodBindGetMethod + methodBindPtrCall + methodBindCall + getClassConstructor + + alloc + realloc + free + + printError + printWarning + print + + foundCoreApi = true + for i in 0.cuint..= (0, 19, 0): + import compiler/lineinfos + +when (NimMajor, NimMinor, NimPatch) >= (0, 19, 0): + var gic = newIdentCache() + + proc getIdent(ident: string): PIdent = + getIdent(gic, ident) + +proc ident(ident: string): PNode = + result = PNode(kind: nkIdent, ident: getIdent(ident)) + +proc newPNode(kind: TNodeKind): PNode = + when (NimMajor, NimMinor, NimPatch) < (0, 19, 0): + result = newNode(kind) + else: + result = PNode(kind: kind) + result.info.fileIndex = InvalidFileIdx + result.info.col = int16(-1) + result.info.line = uint16(0) + +proc addChain(node: PNode, others: varargs[PNode]): PNode {.discardable.} = + for other in others: + node.add(other) + result = node + +proc newIdentDefs(name, typ: PNode, + defaultVal: PNode = nil): PNode = + result = newPNode(nkIdentDefs) + result.add(name) + result.add(typ) + if defaultVal.isNil: + result.add(newPNode(nkEmpty)) + else: + result.add(defaultVal) + +proc newProc(name: PNode, params: openArray[PNode], body = newPNode(nkEmpty), + procType = nkProcDef): PNode = + result = newPNode(procType) + result.add(name) + result.add(newPNode(nkEmpty)) + result.add(newPNode(nkEmpty)) + let formalParams = newPNode(nkFormalParams) + for param in params: + formalParams.add(param) + result.add(formalParams) + result.add(newPNode(nkEmpty)) + result.add(newPNode(nkEmpty)) + result.add(body) + +proc newIfStmt(condition, body: PNode): PNode = + result = newPNode(nkIfStmt) + let branch = newPNode(nkElifBranch) + result.add(branch) + branch.add(condition) + branch.add(body) + +proc newCall(theProc: PNode, args: varargs[PNode]): PNode = + result = newPNode(nkCall) + result.add(theProc) + for arg in args: + result.add(arg) + +proc newCall(theProc: string, args: varargs[PNode]): PNode = + newCall(ident(theProc), args) + +proc newStrLit(s: string): PNode = + result = newPNode(nkStrLit) + result.strVal = s + +proc newRStrLit(s: string): PNode = + result = newPNode(nkRStrLit) + result.strVal = s + +proc newCStringLit(s: string): PNode = + newPNode(nkCallStrLit).addChain(ident("cstring"), newRStrLit(s)) + +proc newIntLit(val: BiggestInt): PNode = + result = newPNode(nkIntLit) + result.intVal = val + +proc newInt64Lit(val: BiggestInt): PNode = + result = newPNode(nkInt64Lit) + result.intVal = val + +proc newFloatLit(val: BiggestFloat): PNode = + result = newPNode(nkFloatLit) + result.floatVal = val + +proc newFloat64Lit(val: BiggestFloat): PNode = + result = newPNode(nkFloat64Lit) + result.floatVal = val + +proc newNilLit(): PNode = + result = newPNode(nkNilLit) + +proc newDotExpr(left, right: PNode): PNode = + result = newPNode(nkDotExpr) + result.add(left) + result.add(right) + +proc newCommand(left, right: PNode): PNode = + result = newPNode(nkCommand) + result.add(left) + result.add(right) + +proc infix(left, op, right: PNode): PNode = + result = newPNode(nkInfix) + result.add(op) + result.add(left) + result.add(right) + +proc postfix(left: PNode, op: string): PNode = + result = newPNode(nkPostfix) + result.add(ident(op)) + result.add(left) + +proc prefix(op: string, right: PNode): PNode = + result = newPNode(nkPrefix) + result.add(ident(op)) + result.add(right) + +proc newBracketExpr(first, bracket: PNode): PNode = + newPNode(nkBracketExpr).addChain(first, bracket) + +proc newEmptyNode(): PNode = + newPNode(nkEmpty) + +type GodotType = ref object + name: string + godotName: string + baseName: string + doc: string + derivedCount: int + isSingleton: bool + jsonNode: JsonNode + +proc findCommonRoot(typeRegistry: Table[string, GodotType], + types: seq[string]): string = + if types.len == 0: return "Object" + var chains = newSeq[seq[string]](types.len) + for idx, typ in types: + chains[idx] = newSeq[string]() + chains[idx].add(typ) + var curTyp = typeRegistry[typ] + while curTyp.baseName != "NimGodotObject": + chains[idx].add(curTyp.baseName) + curTyp = typeRegistry[curTyp.baseName] + chains[idx].reverse() + + var idx = 0 + while true: + var curType = none(string) + var allEqual = true + for chain in chains: + if idx >= chain.len: + allEqual = false + break + if curType.isNone: + curType = some(chain[idx]) + elif curType.get != chain[idx]: + allEqual = false + break + if allEqual: + result = curType.get + else: + break + inc idx + +proc incDerivedCount(types: var Table[string, GodotType], + className: string) = + let typ = types.getOrDefault(className) + if not typ.isNil: + inc typ.derivedCount + types.incDerivedCount(typ.baseName) + +proc toNimType(godotType: string): string = + result = case godotType: + of "float": "float64" + of "int": "int64" + of "String": "string" + of "File": "godottypes.File" + else: godotType + + if result.startsWith("enum."): + result = if result == "enum.Error": "Error" else: "int64" + +proc toNimType(types: Table[string, GodotType], godotType: string): string = + let origType = + if godotType.contains(','): + findCommonRoot(types, godotType.split(',')) + else: + godotType + result = toNimType(origType) + +proc toNimStyle(name: string): string = + result = newStringOfCap(name.len + 1) + var i = 0 + var makeUpperCase: bool + while i < name.len: + if name[i] == '_': + if result.len != 0: + makeUpperCase = true + elif name[i] != '/': # remove slashes + if makeUpperCase: + result.add(name[i].toUpperAscii()) + makeUpperCase = false + else: + result.add(name[i]) + inc i + + while isKeyword(getIdent(result)): + result.add(result[result.len - 1]) + + if result == "result": + result = "resultVal" + +proc newRefTypeNode(typeSection: PNode, typ, base, doc: string, + isExported = true) = + let typeDef = newPNode(nkTypeDef) + typeSection.add(typeDef) + if isExported: + typeDef.add(postfix(ident(typ), "*")) + else: + typeDef.add(ident(typ)) + + typeDef.add(newPNode(nkEmpty)) # generic + let objTy = newPNode(nkObjectTy) + let refTy = newPNode(nkRefTy) + refTy.add(objTy) + typeDef.add(refTy) + + objTy.add(newPNode(nkEmpty)) + let inherit = newPNode(nkOfInherit) + inherit.add(ident(base)) + objTy.add(inherit) + + if doc.len > 0: + let recList = newPNode(nkRecList) + let docNode = newPNode(nkCommentStmt) + docNode.comment = doc + recList.add(docNode) + objTy.add(recList) + else: + objTy.add(newPNode(nkEmpty)) + +proc makeConstSection(constObj: JsonNode): PNode = + if constObj.len == 0: + return newPNode(nkEmpty) + + result = newPNode(nkConstSection) + for field, val in constObj: + let def = newPNode(nkConstDef) + def.add(postfix(ident(field), "*")) + def.add(newPNode(nkEmpty)) # infer type + var valNode: PNode + if val.kind == JInt: + valNode = newInt64Lit(val.num) + # valNode.intVal = val.num + elif val.kind == JFloat: + valNode = newFloat64Lit(val.fnum) + elif val.kind == JBool: + valNode = ident($val.bval) + elif val.kind == JString: + valNode = newPNode(nkStrLit) + valNode.strVal = val.str + else: + raise newException(ValueError, "Unexpected constant kind: " & $val.kind) + def.add(valNode) + result.add(def) + +type + ArgKind = enum + Normal, + VarArgs + Bound + + MethodArg = object + name: string + typ: string + defaultVal: JsonNode + kind: ArgKind + + MethodInfo = ref object + name: PNode + godotName: string + typ: GodotType + args: seq[MethodArg] + returnType: Option[string] + isVirtual: bool + isBase: bool + isDiscardable: bool + +const standardTypes = toHashSet( + ["bool", "cint", "int", "uint8", "int8", "uint16", "int16", "uint32", "int32", + "uint64", "Error", + "int64", "float32", "cfloat", "float64", "GodotString", "Vector2", "Rect2", + "Vector3", "Transform2D", "Plane", "Quat", "AABB", "Basis", "Transform", + "Color", "RID", "NodePath", "Dictionary", "Variant", "Array", + "PoolByteArray", "PoolIntArray", "PoolRealArray", "PoolStringArray", + "PoolVector2Array", "PoolVector3Array", "PoolColorArray"]) + +const variantPrimitives = [ + "bool", "cint", "int", "uint8", "int8", "uint16", "int16", "uint32", "int32", + "uint64", "Error", + "int64", "float32", "cfloat", "float64", "GodotString", "Vector2", "Rect2", + "Vector3", "Transform2D", "Plane", "Quat", "AABB", "Basis", "Transform", + "Color", "RID"] + +const smallIntTypes = toHashSet(["uint8", "int8", "uint16", "int16", "uint32", + "int32", "cint", "int", "Error"]) +const int64Types = toHashSet(["uint64", "int64"]) +const intTypes = union(smallIntTypes, int64Types) +const float64Types = toHashSet(["float64", "cdouble"]) +const float32Types = toHashSet(["float32", "cfloat"]) +const floatTypes = union(float64Types, float32Types) +const arrayTypes = toHashSet(["Array", "PoolByteArray", + "PoolIntArray", "PoolRealArray", "PoolStringArray", "PoolVector2Array", + "PoolVector3Array", "PoolColorArray"]) +const wrapperTypes = union(arrayTypes, + toHashSet(["NodePath", "Dictionary", "Variant"])) + +proc getInternalPtr(varName: PNode, typ: string): PNode = + assert(typ in wrapperTypes or typ == "Object") + result = newDotExpr(varName, ident("godot" & typ)) + +proc newNilCheck(ident, toAssign: PNode): PNode = + newIfStmt(newCall("isNil", ident), + newPNode(nkAsgn).addChain(ident).addChain( + toAssign + ) + ) + +proc singletonName(typ: string): PNode = + ident("singleton" & typ) + +proc makeDefaultValue(arg: MethodArg): PNode = + result = newEmptyNode() + if not arg.defaultVal.isNil: + var failed = false + if arg.typ == "bool": + result = ident(arg.defaultVal.str.toLowerAscii()) + elif arg.typ in intTypes: + result = newInt64Lit(parseBiggestInt(arg.defaultVal.str)) + elif arg.typ == "string" or arg.typ == "NodePath": + result = newStrLit(arg.defaultVal.str) + elif arg.typ in floatTypes: + result = newFloatLit(parseFloat(arg.defaultVal.str)) + elif arg.defaultVal.str == "Null": + if arg.typ == "Variant": + result = newCall("newVariant") + else: + result = newNilLit() + elif arg.typ == "Color": + result = newCall("initColor", + arg.defaultVal.str.split(',').mapIt(newFloatLit(parseFloat(it)))) + elif arg.typ == "RID" and arg.defaultVal.str == "[RID]": + result = newCall("initRID") + elif arg.typ in arrayTypes and (arg.defaultVal.str == "[]" or + arg.defaultVal.str == "[" & arg.typ & "]"): + result = newCall("new" & arg.typ) + elif arg.typ == "Vector2" or arg.typ == "Vector3" or arg.typ == "Rect2": + let parts = arg.defaultVal.str.replace("(", "").replace(")", ""). + replace(" ", ""). + split(',').mapIt(newFloatLit(parseFloat(it))) + if arg.typ.endsWith("r2"): + result = newCall("vec2", parts) + elif arg.typ.endsWith('3'): + result = newCall("vec3", parts) + else: + result = newCall("initRect2", parts) + elif arg.defaultVal.str == "[Object:null]": + result = newNilLit() + elif arg.typ == "Transform": + let transformParts = arg.defaultVal.str.replace(" ", "").split('-') + doAssert(transformParts.len == 2) + let basisParts = transformParts[0].split(',').mapIt( + newFloatLit(parseFloat(it))) + let originParts = transformParts[1].split(',').mapIt( + newFloatLit(parseFloat(it))) + let basis = newCall("initBasis", basisParts) + let origin = newCall("vec3", originParts) + result = newCall("initTransform", basis, origin) + elif arg.typ == "Transform2D": + let parts = arg.defaultVal.str. + replace(" ", ""). + replace(")", ""). + replace("(", ""). + split(',').mapIt(newFloatLit(parseFloat(it))) + doAssert(parts.len == 6) + let xAxis = newCall("vec2", parts[0..1]) + let yAxis = newCall("vec2", parts[2..3]) + let origin = newCall("vec2", parts[4..5]) + result = newCall("initTransform2D", xAxis, yAxis, origin) + elif arg.typ == "Variant": + if arg.defaultVal.str == "0": + result = newCall("newVariant", newIntLit(0)) + elif arg.defaultVal.str == "Null": + result = newCall("newVariant") + else: + failed = true + elif arg.typ == "Dictionary": + result = newCall("newDictionary") + else: + failed = true + + if failed: + raise newException( + ValueError, + "Cannot build default value from \"$#\" ($#) - please report this at https://github.com/pragmagic/godot-nim/issues" % + [$arg.defaultVal, arg.typ]) + +proc boundArgName(idx: int): string = + "godotBoundArg" & $idx + +proc doGenerateMethod(tree: PNode, methodBindRegistry: var HashSet[string], + meth: MethodInfo, withImplementation: bool) = + var body: PNode + if not withImplementation: + body = newPNode(nkEmpty) + elif meth.godotName == "_init" and meth.typ.godotName == "Object": + # It's not real (calling it crashes) and will be removed later, + # but we use init() convention in Nim, so it needs to work. + body = newPNode(nkStmtList).addChain( + newPNode(nkDiscardStmt).addChain(newPNode(nkEmpty))) + else: + let methGodotName = if meth.godotName.startsWith('_'): + "underscore" & meth.godotName[1..^1] + else: + meth.godotName + var methodBindName = toNimStyle( + meth.typ.name & "_" & methGodotName & "_method_bind") + if methodBindName[0].isUpperAscii(): + methodBindName[0] = methodBindName[0].toLowerAscii() + if methodBindName notin methodBindRegistry: + let methodBindDecl = newPNode(nkVarSection).addChain( + newIdentDefs( + newPNode(nkPragmaExpr).addChain( + ident(methodBindName)).addChain( + newPNode(nkPragma).addChain(ident("threadvar"))), + newPNode(nkPtrTy).addChain(ident("GodotMethodBind")) + )) + tree.add(methodBindDecl) + methodBindRegistry.incl(methodBindName) + + let nilCheck = newNilCheck(ident(methodBindName), + newCall("getMethod", newCStringLit(meth.typ.godotName), + newCStringLit(meth.godotName)) + ) + let vars = newPNode(nkVarSection) + var varargsName = none(string) + var isVarargs: bool + var staticArgsLen: int + var argLenNode = newIntLit(0) + let argsName = ident("argsToPassToGodot") + if meth.args.len > 0: + for idx, arg in meth.args: + if arg.kind == ArgKind.VarArgs: + varargsName = some(arg.name) + isVarargs = true + vars.add(newIdentDefs(ident("callError"), ident("VariantCallError"))) + elif arg.kind == ArgKind.Bound: + let argName = boundArgName(idx) + vars.add(newIdentDefs( + ident(argName), newPNode(nkEmpty), arg.makeDefaultValue())) + + let argsAlloc = newPNode(nkCast).addChain( + newPNode(nkPtrTy).addChain( + newPNode(nkBracketExpr).addChain( + ident("array"), ident("MAX_ARG_COUNT"), + if isVarargs: newPNode(nkPtrTy).addChain(ident("GodotVariant")) + else: ident("pointer")))) + staticArgsLen = if varargsName.isNone: meth.args.len + else: meth.args.len - 1 + if varargsName.isSome: + argLenNode = newCall("cint", + infix(newIntLit(staticArgsLen), + ident("+"), + newDotExpr(ident(varargsName.get), ident("len")))) + argsAlloc.add(newCall("godotAlloc", newCall("cint", infix( + newCall("sizeof", newPNode(nkPtrTy).addChain(ident("GodotVariant"))), ident("*"), + newPNode(nkPar).addChain(argLenNode)))) + ) + else: + argLenNode = newCall("cint", newIntLit(staticArgsLen)) + vars.add(newIdentDefs( + ident("argsStatic"), + newPNode(nkBracketExpr).addChain( + ident("array"), newIntLit(staticArgsLen), ident("pointer")), + newPNode(nkEmpty))) + argsAlloc.add(newCommand(ident("addr"), ident("argsStatic"))) + vars.add(newIdentDefs(argsName, newPNode(nkEmpty), argsAlloc)) + + let argConversions = newPNode(nkStmtList) + let destructors = newPNode(nkStmtList) + for idx, arg in meth.args: + var argName = if arg.kind == ArgKind.Bound: ident(boundArgName(idx)) + else: ident(arg.name) + if arg.kind == ArgKind.VarArgs: + argName = newPNode(nkBracketExpr).addChain( + ident(varargsName.get), + infix(ident("idx"), ident("-"), newIntLit(staticArgsLen))) + let argIdx = if arg.kind == ArgKind.VarArgs: ident("idx") else: newIntLit(idx) + let isStandardType = arg.typ in standardTypes + let isWrappedType = arg.typ in wrapperTypes + let convArg = + if varargsName.isSome: + let isAlreadyVariant = arg.typ == "Variant" + let variantIdent = if isAlreadyVariant: getInternalPtr(argName, "Variant") + else: ident("variant" & $idx) + if not isAlreadyVariant: + argConversions.add(newPNode(nkVarSection).addChain( + newIdentDefs(variantIdent, ident("GodotVariant"), newEmptyNode()) + )) + destructors.add( + newCall("deinit", variantIdent) + ) + if arg.typ in variantPrimitives: + argConversions.add( + newCall("initGodotVariant", variantIdent, argName) + ) + elif arg.typ in wrapperTypes or arg.typ == "Object": + argConversions.add( + newCall("initGodotVariant", variantIdent, getInternalPtr(argName, arg.typ)) + ) + elif arg.typ == "string": + let stringIdent = ident("variantString" & $idx) + argConversions.addChain( + newPNode(nkVarSection).addChain( + newIdentDefs(stringIdent, ident("GodotString"), newCall("toGodotString", argName)) + ) + ).addChain( + newCall("initGodotVariant", variantIdent, stringIdent) + ) + destructors.add(newCall("deinit", stringIdent)) + else: + raise newException(ValueError, + "Non-standard type $# for varargs params of method $# of type $#" % + [arg.typ, meth.godotName, meth.typ.godotName]) + + if isAlreadyVariant: variantIdent + else: newCall("addr", variantIdent) + elif isWrappedType: getInternalPtr(argName, arg.typ) + elif isStandardType: newCall("unsafeAddr", argName) + elif arg.typ == "string": newCall("unsafeAddr", + ident("argToPassToGodot" & $idx)) + else: ident("argToPassToGodot" & $idx) # object + if not isStandardType and arg.kind == ArgKind.VarArgs: + raise newException(ValueError, + "Non-standard type $# for varargs params of method $# of type $#" % + [arg.typ, meth.godotName, meth.typ.godotName]) + if not isStandardType and varargsName.isNone: + if arg.typ == "string": + argConversions.add(newPNode(nkVarSection).addChain( + newIdentDefs(ident("argToPassToGodot" & $idx), newEmptyNode(), + newCall("toGodotString", argName)))) + else: + let objVal = newIfStmt( + prefix("not", newDotExpr(argName, ident"isNil")), + newDotExpr(argName, ident("godotObject")) + ).addChain(newPNode(nkElse).addChain(newNilLit())) + argConversions.add(newPNode(nkLetSection).addChain( + newIdentDefs(ident("argToPassToGodot" & $idx), newEmptyNode(), objVal))) + let argAsgn = newPNode(nkAsgn).addChain( + newPNode(nkBracketExpr).addChain( + newPNode(nkBracketExpr).addChain(argsName), argIdx), + convArg + ) + if arg.kind != ArgKind.VarArgs: + argConversions.add( + argAsgn + ) + else: + argConversions.add(newPNode(nkVarSection).addChain( + newIdentDefs(ident("idx"), newPNode(nkEmpty), + newIntLit(staticArgsLen)))) + let argLoop = newPNode(nkWhileStmt) + argConversions.add(argLoop) + argLoop.add(infix(ident("idx"), ident("<"), argLenNode) + ) + argLoop.add(newPNode(nkStmtList).addChain( + argAsgn, + newCommand(ident("inc"), ident("idx")))) + + let retName = if isVarargs: "callRet" else: "ptrCallRet" + let theCall = newCall( + newDotExpr(ident(methodBindName), + ident(if isVarargs: "call" else: "ptrCall")), + newDotExpr(ident("self"), ident("godotObject")), + if meth.args.len > 0: argsName else: newPNode(nkNilLit), + argLenNode, + if not isVarargs: ident(retName) else: ident("callError") + ) + if not isVarargs: + theCall.sons.delete(3) + let freeCall = newCall("godotFree", argsName) + body = newPNode(nkStmtList) + if meth.typ.isSingleton: + let varName = singletonName(meth.typ.name) + body.add(newNilCheck(varName, newCall( + newBracketExpr(ident("getSingleton"), ident(meth.typ.name))))) + body.add(newPNode(nkLetSection).addChain(newIdentDefs( + ident("self"), newPNode(nkEmpty), varName + ))) + body.add(nilCheck) + body.add(vars) + body.add(argConversions) + if not isVarargs: + let retPtrDecl = newPNode(nkVarSection).addChain( + newIdentDefs(ident(retName), ident("pointer"), newEmptyNode()) + ) + body.add(retPtrDecl) + var isVariantRet: bool + var isConversionRet: bool + var isObjRet: bool + var isStringRet: bool + var isWrapperRet: bool + let retValIdent = if not isVarargs: ident("ptrCallVal") else: ident(retName) + if meth.returnType.isSome and not isVarargs: + let returnType = meth.returnType.get + var addrToAssign = newCall("addr", retValIdent) + if returnType in smallIntTypes: + isConversionRet = true + body.add(newPNode(nkVarSection).addChain(newIdentDefs( + retValIdent, ident("int64"), + ))) + elif returnType in float32Types: + isConversionRet = true + body.add(newPNode(nkVarSection).addChain(newIdentDefs( + retValIdent, ident("float64"), + ))) + elif returnType in wrapperTypes: + isWrapperRet = true + body.add(newPNode(nkVarSection).addChain(newIdentDefs( + retValIdent, ident("Godot" & returnType), + ))) + if returnType != "NodePath": + body.add(newCall("initGodot" & returnType, retValIdent)) + elif returnType in standardTypes: + addrToAssign = newCall("addr", ident("result")) + elif returnType == "string": + isStringRet = true + body.add(newPNode(nkVarSection).addChain(newIdentDefs( + retValIdent, ident("GodotString"), + ))) + elif returnType != "void": + isObjRet = true + body.add(newPNode(nkVarSection).addChain(newIdentDefs( + retValIdent, newPNode(nkPtrTy).addChain(ident("GodotObject")), + ))) + body.add(newPNode(nkAsgn).addChain(ident(retName), addrToAssign)) + + if not isVarargs: + body.add(theCall) + else: + if meth.returnType.isSome: + isVariantRet = true + let callStmt = newPNode(nkLetSection).addChain( + newIdentDefs( + newPNode(nkPragmaExpr).addChain( + ident(retName), newPNode(nkPragma).addChain(ident("used"))), + newPNode(nkEmpty), theCall)) + body.add(callStmt) + + if varargsName.isNone: + for idx, arg in meth.args: + if arg.typ == "string": + body.add(newCall("deinit", ident("argToPassToGodot" & $idx))) + + if varargsName.isSome: + if meth.args.len > 0: + body.add(freeCall) + body.add(destructors) + let errCheck = newIfStmt( + infix(newDotExpr(ident("callError"), ident("error")), ident("!="), + newDotExpr(ident("VariantCallErrorType"), ident("OK"))), + newPNode(nkRaiseStmt).addChain( + newCall("newCallError", ident("callError"))) + ) + body.add(errCheck) + if isVariantRet: + let convErrDef = newPNode(nkLetSection).addChain( + newIdentDefs(ident("convErr"), newPNode(nkEmpty), + newCall("fromVariant", ident("result"), + newCall("newVariant", retValIdent)))) + let convCheck = newIfStmt( + infix(ident("convErr"), ident("!="), + newDotExpr(ident("ConversionResult"), ident("OK"))), + newPNode(nkRaiseStmt).addChain( + newCall("newConversionError", ident("convErr"))) + ) + body.add(convErrDef) + body.add(convCheck) + if isStringRet: + body.add(newPNode(nkAsgn).addChain( + ident("result"), prefix("$", retValIdent))) + body.add(newCall("deinit", retValIdent)) + elif isConversionRet: + body.add(newPNode(nkAsgn).addChain( + ident("result"), + newCall(meth.returnType.get, retValIdent))) + elif isWrapperRet: + body.add(newPNode(nkAsgn).addChain( + ident("result"), + newCall("new" & meth.returnType.get, retValIdent))) + elif isObjRet: + body.add(newPNode(nkAsgn).addChain(ident("result"), + newCall(newBracketExpr(ident("asNimGodotObject"), + newCall("type", ident("result"))), + retValIdent, ident("false"), ident("true")))) + elif isStringRet: + body.add(newPNode(nkAsgn).addChain(ident("result"), + newCall("$", retValIdent))) + + let procType = if meth.isVirtual: nkMethodDef + else: nkProcDef + var params = newSeqOfCap[PNode](meth.args.len + 2) + if meth.returnType.isSome: + params.add(ident(meth.returnType.get)) + else: + params.add(newPNode(nkEmpty)) + if not meth.typ.isSingleton: + params.add(newIdentDefs(ident("self"), ident(toNimType(meth.typ.name)))) + + for arg in meth.args: + case arg.kind: + of ArgKind.Normal: + let defaultValue = arg.makeDefaultValue() + params.add(newIdentDefs(ident(arg.name), ident(arg.typ), defaultValue)) + of ArgKind.VarArgs: + params.add(newIdentDefs(ident(arg.name), + newPNode(nkBracketExpr).addChain(ident("varargs"), ident(arg.typ)))) + of ArgKind.Bound: + discard + + let procDecl = newProc(if not withImplementation: postfix(meth.name, "*") + else: meth.name, + params, body, procType) + if not withImplementation: + let pragma = newPNode(nkPragma) + pragma.add(ident("gcsafe")) + pragma.add(newPNode(nkExprColonExpr).addChain(ident("locks"), + newIntLit(0))) + if meth.isVirtual and meth.isBase and meth.typ.name != "PhysicsBody": + # Nim doesn't like `base` on PhysicsBody methods - wtf + pragma.add(ident("base")) + if meth.isDiscardable and meth.returnType.isSome: + pragma.add(ident("discardable")) + procDecl.sons[4] = pragma + tree.add(procDecl) + +proc generateMethod(tree: PNode, methodBindRegistry: var HashSet[string], + meth: MethodInfo, withImplementation: bool) = + doGenerateMethod(tree, methodBindRegistry, meth, withImplementation) + +proc getMethodInfo(methodObj: JsonNode, types: Table[string, GodotType], + typ: GodotType): MethodInfo = + var origArgs = methodObj["arguments"] + var isBase = methodObj["is_virtual"].bval + if methodObj["is_virtual"].bval: + proc getMethod(typNode: JsonNode, methName: string): JsonNode = + for meth in typNode["methods"]: + if meth["is_virtual"].bval and + meth["name"].str == methName: return meth + var curTyp = types.getOrDefault(typ.baseName) + while not curTyp.isNil: + let meth = curTyp.jsonNode.getMethod(methodObj["name"].str) + if not meth.isNil: + origArgs = meth["arguments"] + isBase = false + curTyp = types.getOrDefault(curTyp.baseName) + + var args = newSeqOfCap[MethodArg](methodObj["arguments"].len + 1) + for arg in origArgs: + let typ = toNimType(types, arg["type"].str) + let defaultVal = if arg["has_default_value"].bval: arg["default_value"] + else: nil + args.add(MethodArg( + name: toNimStyle(arg["name"].str), typ: typ, + defaultVal: defaultVal)) + if methodObj["has_varargs"].bval: + args.add(MethodArg(name: "variantArgs", typ: "Variant", kind: ArgKind.VarArgs)) + + let godotName = methodObj["name"].str + var nimName = toNimStyle(godotName) + if not godotName.startsWith('_'): + for meth in typ.jsonNode["methods"]: + if meth["name"].str == '_' & godotName: + nimName = nimName & "Impl" + + let returnType = if methodObj["return_type"].str != "void": + some(toNimType(types, methodObj["return_type"].str)) + else: none(string) + const discardableMethods = toHashSet(["emit_signal"]) + result = MethodInfo( + name: ident(nimName), + typ: typ, + godotName: methodObj["name"].str, + args: args, + returnType: returnType, + isVirtual: methodObj["is_virtual"].bval, + isBase: isBase, + isDiscardable: typ.godotName == "Object" and + methodObj["name"].str in discardableMethods + ) + +proc findMethod(obj: JsonNode, methName: string): JsonNode = + for meth in obj["methods"]: + if meth["name"].str == methName: + return meth + +proc makeProperty(types: Table[string, GodotType], tree: PNode, + methodBindRegistry: var HashSet[string], + typ: GodotType, propertyObj: JsonNode, obj: JsonNode, + withImplementation: bool) = + for meth in obj["methods"]: + if meth["name"].str == '_' & propertyObj["name"].str: + # Don't generate properties if there is a name clash - otherwise + # using the property would not compile due to ambiguity. + return + let getterNameStr = toNimStyle(propertyObj["name"].str) + let getterName = ident(getterNameStr) + let setterName = newPNode(nkAccQuoted).addChain(ident(getterNameStr & "=")) + + let getter = findMethod(obj, propertyObj["getter"].str) + let nimType = if getter.isNil: toNimType(types, propertyObj["type"].str) + else: getMethodInfo(getter, types, typ).returnType.get("void") + let getterInfo = MethodInfo( + name: getterName, + typ: typ, + godotName: propertyObj["getter"].str, + args: newSeq[MethodArg](), + returnType: some(nimType) + ) + let setterInfo = MethodInfo( + name: setterName, + typ: typ, + godotName: propertyObj["setter"].str, + args: @[MethodArg(name: "val", typ: nimType)] + ) + if "index" in propertyObj and propertyObj["index"] != newJInt(-1): + getterInfo.args = + @[MethodArg(defaultVal: newJString($propertyObj["index"]), + typ: "int", kind: ArgKind.Bound)] & getterInfo.args + setterInfo.args = + @[MethodArg(defaultVal: newJString($propertyObj["index"]), + typ: "int", kind: ArgKind.Bound)] & setterInfo.args + generateMethod(tree, methodBindRegistry, getterInfo, withImplementation) + generateMethod(tree, methodBindRegistry, setterInfo, withImplementation) + +proc makeMethod(types: Table[string, GodotType], tree: PNode, + methodBindRegistry: var HashSet[string], + typ: GodotType, methodObj: JsonNode, + withImplementation: bool) = + if not typ.isSingleton: + # for singletons we don't generate Nim setters/getters, + # but use plain procedures instead. That's because setter syntax is + # supposed to be used on an object (have at least 2 params). + for prop in typ.jsonNode["properties"]: + if prop["getter"].str == methodObj["name"].str or + prop["setter"].str == methodObj["name"].str: + var hasDuplicateMethod = false + for meth in typ.jsonNode["methods"]: + if meth["name"].str == '_' & prop["name"].str: + hasDuplicateMethod = true + break + if not hasDuplicateMethod: + return + + let methodInfo = getMethodInfo(methodObj, types, typ) + + generateMethod(tree, methodBindRegistry, methodInfo, withImplementation) + +proc addAttributeToDoc(doc: var string, propName, propValue: string) = + if doc.len > 0: + doc.add("\n") + doc.add(propName & ": " & propValue) + +const classAttributes = ["singleton", "instanciable", "is_reference"] + +proc typeNameToModuleName(name: string): string = + var wasUpperOrDigit = true + result = newStringOfCap(name.len + 10) + for idx, c in name: + if c.isUpperAscii() or c.isDigit(): + if not wasUpperOrDigit or idx > 0 and idx < name.len - 1 and + name[idx + 1].isLowerAscii(): + result.add('_') + result.add(c.toLowerAscii()) + wasUpperOrDigit = true + else: + result.add(c) + wasUpperOrDigit = false + if result == "object": + # keyword + result = "objects" + if result == "os": + # to avoid clash with stdlib + result = "gd_os" + +proc newRegisterClassNode(typ: GodotType): PNode = + newCall("registerClass", + ident(typ.name), + newStrLit(typ.godotName), + ident("true") # isNative + ) + +proc genSingletonDecl(typ: string): PNode = + result = newPNode(nkVarSection) + let name = singletonName(typ) + let threadvar = newPNode(nkPragma).addChain(ident("threadvar")) + result.add(newIdentDefs(newPNode(nkPragmaExpr).addChain(name, threadvar), + ident(typ))) + +proc shouldExport(typ: GodotType, types: Table[string, GodotType]): bool = + var curTyp = typ + while not curTyp.isNil and not curTyp.isSingleton: + curTyp = types.getOrDefault(curTyp.baseName) + result = curTyp.isNil + +proc sortByDerivedCount(types: Table[string, GodotType]): seq[GodotType] = + result = toSeq(types.values()) + result.sort do (x, y: GodotType) -> int: + cmp(y.derivedCount, x.derivedCount) + +proc genTypeFile(types: Table[string, GodotType], targetDir: string) = + let sortedTypes = sortByDerivedCount(types) + + let godotApiTypesTree = newPNode(nkStmtList) + godotApiTypesTree.add(newPNode(nkImportStmt).addChain(ident("godot"))) + let typeSection = newPNode(nkTypeSection) + godotApiTypesTree.add(typeSection) + + for typ in sortedTypes: + if not typ.shouldExport(types): continue + newRefTypeNode(typeSection, typ.name, typ.baseName, typ.doc) + + for typ in sortedTypes: + if not typ.shouldExport(types): continue + let regNode = newCall("registerClass", + ident(typ.name), + newStrLit(typ.godotName), + ident("true") # isNative + ) + godotApiTypesTree.add(regNode) + + writeFile(targetDir / "godottypes.nim", renderTree(godotApiTypesTree)) + +proc genSingletonWithDerived(tree: PNode, typ: GodotType, + types: Table[string, GodotType]) = + let sortedTypes = sortByDerivedCount(types) + + var parents = initHashSet[string]() + parents.incl(typ.name) + + let typeDecl = newPNode(nkTypeSection) + tree.add(typeDecl) + proc genDecl(typ: GodotType) = + newRefTypeNode(typeDecl, typ.name, typ.baseName, typ.doc, + isExported = false) + tree.add(newRegisterClassNode(typ)) + + genDecl(typ) + for otherType in sortedTypes: + if otherType.baseName in parents: + parents.incl(otherType.name) + genDecl(otherType) + + tree.add(genSingletonDecl(typ.name)) + +proc genApi*(targetDir: string, apiJsonFile: string) = + ## Generates .nim files in the ``targetDir`` based on the ``apiJsonFile``. + ## The JSON file can be generated by executing Godot with + ## ``--gdnative-generate-json-api `` parameters. + let apiJson = parseJson(newFileStream(apiJsonFile), + apiJsonFile.extractFilename()) + var megaImport = newStringOfCap(64 * 1024) + + var types = initTable[string, GodotType]() + for obj in apiJson: + let godotClassName = obj["name"].str + let className = godotClassName.replace("_", "") + var baseClassName = obj["base_class"].str + baseClassName = toNimType(baseClassName.replace("_", "")) + if baseClassName.len == 0: + baseClassName = "NimGodotObject" + var doc = "" + for attr in classAttributes: + if attr in obj: + addAttributeToDoc(doc, attr, $obj[attr]) + types[className] = GodotType( + name: className, + godotName: godotClassName, + baseName: baseClassName, + doc: doc, + jsonNode: obj, + isSingleton: obj["singleton"].bval + ) + + for typ in types.values(): + types.incDerivedCount(typ.baseName) + + for typ in types.values(): + let moduleName = typeNameToModuleName(typ.name) + echo "Generating ", moduleName, ".nim..." + let tree = newPNode(nkStmtList) + let importStmt = newPNode(nkImportStmt) + importStmt.add(ident("godot")) + importStmt.add(ident("godottypes")) + importStmt.add(ident("godotinternal")) + tree.add(importStmt) + let exportStmt = newPNode(nkExportStmt) + exportStmt.add(ident("godottypes")) + tree.add(exportStmt) + + var methodBindRegsitry = initHashSet[string]() + let obj = typ.jsonNode + if typ.baseName != "NimGodotObject": + let baseModule = typeNameToModuleName(typ.baseName) + let baseModuleNode = if getIdent(baseModule).isKeyword: + newStrLit(baseModule & ".nim") + else: + ident(baseModule) + importStmt.add(baseModuleNode) + exportStmt.add(baseModuleNode) + let constSection = makeConstSection(obj["constants"]) + if constSection.kind != nkEmpty: + # renderer doesn't properly render empty stmt after type section + tree.add(makeConstSection(obj["constants"])) + + if typ.isSingleton: + genSingletonWithDerived(tree, typ, types) + + if "enums" in obj: + # Quite often Godot enums are flags that need to be bitwise ORed + # Nim's enums don't serve well for that purpose, so we just generate + # integer constants. The only enum used in API is Error. + for enumDef in obj["enums"]: + let uniqueConstants = newJObject() + for k, v in enumDef["values"]: + if k notin obj["constants"]: + uniqueConstants[k] = v + if uniqueConstants.len > 0: + tree.add(makeConstSection(uniqueConstants)) + + # first, generate declarations only for ease of + # human readability of the file + if not typ.isSingleton: + for property in obj["properties"]: + makeProperty(types, tree, methodBindRegsitry, typ, property, + obj, withImplementation = false) + for meth in obj["methods"]: + makeMethod(types, tree, methodBindRegsitry, typ, + meth, withImplementation = false) + + if not typ.isSingleton: + for property in obj["properties"]: + makeProperty(types, tree, methodBindRegsitry, typ, + property, obj, withImplementation = true) + for meth in obj["methods"]: + makeMethod(types, tree, methodBindRegsitry, typ, meth, + withImplementation = true) + + writeFile(targetDir / moduleName & ".nim", renderTree(tree)) + + megaImport.add("import \"" & moduleName & "\"\n") + + genTypeFile(types, targetDir) + + writeFile(targetDir / "godotall.nim", megaImport) + writeFile(targetDir / splitPath(targetDir)[1] & ".nimble", "") + +when isMainModule: + import os + + const usage = """Tool for wrapping Godot API into Nim + godotapigen [godot binary path] [target directory]""" + + proc main() = + if paramCount() < 2: + echo usage + quit(-1) + let godotBin = paramStr(1) + let targetDir = paramStr(2) + + if not dirExists(targetDir): + echo "The specified directory does not exist" + quit(-1) + if not fileExists(godotBin): + echo "Invalid godot binary path" + quit(-1) + + let jsonFile = targetDir / "api.json" + if fileExists(jsonFile) and + godotBin.getLastModificationTime() <= jsonFile.getLastModificationTime(): + echo "api.json is up to date - doing nothing." + return + + discard execShellCmd( + "\"" & godotBin & "\" --gdnative-generate-json-api \"" & jsonFile & "\"") + if not fileExists(jsonFile): + echo "Failed to generate api.json" + quit(-1) + + genApi(targetDir, jsonFile) + + main() \ No newline at end of file diff --git a/godot/godotinternal.nim b/godot/godotinternal.nim new file mode 100644 index 0000000..207d76f --- /dev/null +++ b/godot/godotinternal.nim @@ -0,0 +1,122 @@ +# Copyright 2018 Xored Software, Inc. + +import internal/godotinternaltypes, internal/godotarrays, + internal/godotnodepaths, internal/godotpoolarrays, internal/godotstrings, + internal/godotvariants, internal/godotdictionaries + +import gdnativeapi +export godotinternaltypes, godotarrays, godotnodepaths, godotpoolarrays, + godotstrings, godotvariants, godotdictionaries + +proc getMethod*(className: cstring; + methodName: cstring): ptr GodotMethodBind {.inline.} = + getGDNativeAPI().methodBindGetMethod(className, methodName) + +proc ptrCall*(methodBind: ptr GodotMethodBind; + instance: ptr GodotObject; + args: ptr array[MAX_ARG_COUNT, pointer]; + ret: pointer) {.inline.} = + getGDNativeAPI().methodBindPtrCall(methodBind, instance, args, ret) + +proc call*(methodBind: ptr GodotMethodBind; + instance: ptr GodotObject; + args: ptr array[MAX_ARG_COUNT, ptr GodotVariant]; argCount: cint; + callError: var VariantCallError): GodotVariant {.inline.} = + getGDNativeAPI().methodBindCall( + methodBind, instance, args, argCount, callError) + +proc nativeScriptRegisterClass*(libHandle: pointer; name, base: cstring; + createFunc: GodotInstanceCreateFunc; + destroyFunc: GodotInstanceDestroyFunc) + {.inline.} = + getGDNativeAPI().nativeScriptRegisterClass( + libHandle, name, base, createFunc, destroyFunc) + +proc nativeScriptRegisterToolClass*(libHandle: pointer; name, base: cstring; + createFunc: GodotInstanceCreateFunc; + destroyFunc: GodotInstanceDestroyFunc) + {.inline.} = + getGDNativeAPI().nativeScriptRegisterToolClass( + libHandle, name, base, createFunc, destroyFunc) + +proc nativeScriptRegisterMethod*(libHandle: pointer; + name: cstring; function_name: cstring; + attr: GodotMethodAttributes; + meth: GodotInstanceMethod) {.inline.} = + getGDNativeAPI().nativeScriptRegisterMethod( + libHandle, name, functionName, attr, meth) + +proc nativeScriptRegisterProperty*(libHandle: pointer; + name, path: cstring; + attr: ptr GodotPropertyAttributes; + setFunc: GodotPropertySetFunc; + getFunc: GodotPropertyGetFunc) {.inline.} = + getGDNativeAPI().nativeScriptRegisterProperty( + libHandle, name, path, attr, setFunc, getFunc) + +proc nativeScriptRegisterSignal*(libHandle: pointer; name: cstring; + signal: GodotSignal) {.inline.} = + getGDNativeAPI().nativeScriptRegisterSignal(libHandle, name, signal) + +proc getUserdata*(instance: ptr GodotObject): pointer {.inline.} = + getGDNativeAPI().nativeScriptGetUserdata(instance) + +proc getClassConstructor*(className: cstring): GodotClassConstructor + {.inline.} = + getGDNativeAPI().getClassConstructor(className) + +proc deinit*(o: ptr GodotObject) {.inline.} = + getGDNativeAPI().objectDestroy(o) + +# print using Godot's error handler list + +proc godotPrintError*(description, function, file: cstring; + line: cint) {.inline.} = + getGDNativeAPI().printError(description, function, file, line) + +proc godotPrintWarning*(description, function, file: cstring; + line: cint) {.inline.} = + getGDNativeAPI().printWarning(description, function, file, line) + +proc godotPrint*(message: GodotString) {.inline.} = + getGDNativeAPI().print(message) + +var getClassMethodBind: ptr GodotMethodBind +proc getClassName*(o: ptr GodotObject): string = + if getClassMethodBind.isNil: + getClassMethodBind = getMethod(cstring"Object", cstring"get_class") + var ret: GodotString + getClassMethodBind.ptrCall(o, nil, addr ret) + result = $ret + deinit(ret) + if result.len > 2 and result[^2] == 'S' and result[^1] == 'W': + # There are physics type not known by ClassDB + result = result[0..result.len-3] + +proc getClassNameRaw*(o: ptr GodotObject): GodotString = + if getClassMethodBind.isNil: + getClassMethodBind = getMethod(cstring"Object", cstring"get_class") + getClassMethodBind.ptrCall(o, nil, addr result) + +proc getGodotSingleton*(name: cstring): ptr GodotObject {.inline.} = + getGDNativeAPI().globalGetSingleton(name) + +# System Functions + +proc godotAlloc*(bytes: cint): pointer {.inline.} = + ## Allocates the specified number of bytes. + ## Using this instead of stdlib proc will help Godot track how much memory + ## is in use in debug mode. + getGDNativeAPI().alloc(bytes) + +proc godotRealloc*(p: pointer; bytes: cint): pointer {.inline.} = + ## Reallocates the pointer for the specified number of bytes. + ## Using this instead of stdlib proc will help Godot track how much memory + ## is in use in debug mode. + getGDNativeAPI().realloc(p, bytes) + +proc godotFree*(p: pointer) {.inline.} = + ## Frees the memory pointed to by the pointer. + ## Using this instead of stdlib proc will help Godot track how much memory + ## is in use in debug mode. + getGDNativeAPI().free(p) diff --git a/godot/internal/backwardcompat.inc.nim b/godot/internal/backwardcompat.inc.nim new file mode 100644 index 0000000..9d31844 --- /dev/null +++ b/godot/internal/backwardcompat.inc.nim @@ -0,0 +1,19 @@ +# Copyright 2019 Xored Software, Inc. + +when (NimMajor, NimMinor, NimPatch) < (0, 19, 0): + import macros, sets + + proc strVal(n: NimNode): string {.used.} = + case n.kind + of nnkIdent: + $n.ident + of nnkSym: + $n.symbol + else: + macros.strVal(n) + + proc toHashSet[A](keys: openArray[A]): HashSet[A] {.inline, used.} = + toSet(keys) + + proc initHashSet[A](): HashSet[A] {.inline, used.} = + initSet[A]() diff --git a/godot/internal/godotarrays.nim b/godot/internal/godotarrays.nim new file mode 100644 index 0000000..c7e451d --- /dev/null +++ b/godot/internal/godotarrays.nim @@ -0,0 +1,162 @@ +# Copyright (c) 2018 Xored Software, Inc. + +import godotinternaltypes, gdnativeapi, core/godotcoretypes + +proc len*(self: GodotArray): cint {.inline.} = + getGDNativeAPI().arraySize(self) + +import hashes + +proc initGodotArray*(dest: var GodotArray) {.inline.} = + getGDNativeAPI().arrayNew(dest) + +proc initGodotArray*(dest: var GodotArray; + pca: GodotPoolColorArray) {.inline.} = + getGDNativeAPI().arrayNewPoolColorArray(dest, pca) + +proc initGodotArray*(dest: var GodotArray; + pv3a: GodotPoolVector3Array) {.inline.} = + getGDNativeAPI().arrayNewPoolVector3Array(dest, pv3a) + +proc initGodotArray*(dest: var GodotArray; + pv2a: GodotPoolVector2Array) {.inline.} = + getGDNativeAPI().arrayNewPoolVector2Array(dest, pv2a) + +proc initGodotArray*(dest: var GodotArray; + psa: GodotPoolStringArray) {.inline.} = + getGDNativeAPI().arrayNewPoolStringArray(dest, psa) + +proc initGodotArray*(dest: var GodotArray; + pra: GodotPoolRealArray) {.inline.} = + getGDNativeAPI().arrayNewPoolRealArray(dest, pra) + +proc initGodotArray*(dest: var GodotArray; + pia: GodotPoolIntArray) {.inline.} = + getGDNativeAPI().arrayNewPoolIntArray(dest, pia) + +proc initGodotArray*(dest: var GodotArray; + pba: GodotPoolByteArray) {.inline.} = + getGDNativeAPI().arrayNewPoolByteArray(dest, pba) + +proc initGodotArray*(dest: var GodotArray; src: GodotArray) {.inline.} = + getGDNativeAPI().arrayNewCopy(dest, src) + +proc deinit*(self: var GodotArray) {.inline.} = + getGDNativeAPI().arrayDestroy(self) + +proc `[]=`*(self: var GodotArray; idx: cint; value: GodotVariant) {.inline.} = + getGDNativeAPI().arraySet(self, idx, value) + +proc `[]`*(self: GodotArray; idx: cint): GodotVariant {.inline.} = + getGDNativeAPI().arrayGet(self, idx) + +proc mget*(self: var GodotArray; idx: cint): ptr GodotVariant {.inline.} = + getGDNativeAPI().arrayOperatorIndex(self, idx) + +proc add*(self: var GodotArray; value: GodotVariant) {.inline.} = + getGDNativeAPI().arrayPushBack(self, value) + +proc clear*(self: var GodotArray) {.inline.} = + getGDNativeAPI().arrayClear(self) + +proc count*(self: GodotArray; value: GodotVariant): cint {.inline.} = + getGDNativeAPI().arrayCount(self, value) + +proc isEmpty*(self: GodotArray): bool {.inline.} = + getGDNativeAPI().arrayEmpty(self) + +proc erase*(self: var GodotArray; value: GodotVariant) {.inline.} = + getGDNativeAPI().arrayErase(self, value) + +proc first*(self: GodotArray): GodotVariant {.inline.} = + getGDNativeAPI().arrayFront(self) + +proc last*(self: GodotArray): GodotVariant {.inline.} = + getGDNativeAPI().arrayBack(self) + +proc find*(self: GodotArray; what: GodotVariant; + fromIdx: cint): cint {.inline.} = + getGDNativeAPI().arrayFind(self, what, fromIdx) + +proc findLast*(self: GodotArray; what: GodotVariant): cint {.inline.} = + getGDNativeAPI().arrayFindLast(self, what) + +proc contains*(self: GodotArray; value: GodotVariant): bool {.inline.} = + getGDNativeAPI().arrayHas(self, value) + +proc godotHash*(self: GodotArray): cint {.inline.} = + getGDNativeAPI().arrayHash(self) + +proc hash*(self: GodotArray): Hash {.inline.} = + hash(godotHash(self)) + +proc insert*(self: var GodotArray; pos: cint; + value: GodotVariant): Error {.discardable, inline.} = + getGDNativeAPI().arrayInsert(self, pos, value) + +proc reverse*(self: var GodotArray) {.inline.} = + getGDNativeAPI().arrayInvert(self) + +proc popLast*(self: var GodotArray): GodotVariant {.inline.} = + getGDNativeAPI().arrayPopBack(self) + +proc popFirst*(self: var GodotArray): GodotVariant {.inline.} = + getGDNativeAPI().arrayPopFront(self) + +proc addLast*(self: var GodotArray; value: GodotVariant) {.inline.} = + getGDNativeAPI().arrayPushBack(self, value) + +proc addFirst*(self: var GodotArray; value: GodotVariant) {.inline.} = + getGDNativeAPI().arrayPushFront(self, value) + +proc delete*(self: var GodotArray; idx: cint) {.inline.} = + getGDNativeAPI().arrayRemove(self, idx) + +proc setLen*(self: var GodotArray; size: cint) {.inline.} = + getGDNativeAPI().arrayResize(self, size) + +proc rfind*(self: GodotArray; what: GodotVariant; + fromIdx: cint): cint {.inline.} = + getGDNativeAPI().arrayRFind(self, what, fromIdx) + +proc sort*(self: var GodotArray) {.inline.} = + getGDNativeAPI().arraySort(self) + +proc sortCustom*(self: var GodotArray; obj: ptr GodotObject; + funcName: GodotString) {.inline.} = + getGDNativeAPI().arraySortCustom(self, obj, funcName) + +proc binarySearch*(self: var GodotArray, val: ptr GodotVariant, + before: bool) {.inline.} = + getGDNativeAPI().arrayBSearch(self, val, before) + +proc binarySearchCustom*(self: var GodotArray, val: ptr GodotVariant, + obj: ptr GodotObject, funcName: GodotString, + before: bool) {.inline.} = + getGDNativeAPI().arrayBSearchCustom(self, val, obj, funcName, before) + +iterator items*(self: GodotArray): GodotVariant = + for i in 0.cint.. 1: + result.add(", ") + result.add($item) + result.add(']') diff --git a/godot/internal/godotdictionaries.nim b/godot/internal/godotdictionaries.nim new file mode 100644 index 0000000..447647a --- /dev/null +++ b/godot/internal/godotdictionaries.nim @@ -0,0 +1,56 @@ +# Copyright (c) 2018 Xored Software, Inc. + +import godotinternaltypes, gdnativeapi + +proc initGodotDictionary*(dest: var GodotDictionary) {.inline.} = + getGDNativeAPI().dictionaryNew(dest) + +proc initGodotDictionary*(dest: var GodotDictionary; + src: GodotDictionary) {.inline.} = + getGDNativeAPI().dictionaryNewCopy(dest, src) + +proc deinit*(self: var GodotDictionary) {.inline.} = + getGDNativeAPI().dictionaryDestroy(self) + +proc len*(self: GodotDictionary): cint {.inline.} = + getGDNativeAPI().dictionarySize(self) + +proc isEmpty*(self: GodotDictionary): bool {.inline.} = + getGDNativeAPI().dictionaryEmpty(self) + +proc clear*(self: var GodotDictionary) {.inline.} = + getGDNativeAPI().dictionaryClear(self) + +proc contains*(self: GodotDictionary; key: GodotVariant): bool {.inline.} = + getGDNativeAPI().dictionaryHas(self, key) + +proc contains*(self: GodotDictionary; keys: GodotArray): bool {.inline.} = + getGDNativeAPI().dictionaryHasAll(self, keys) + +proc del*(self: var GodotDictionary; key: GodotVariant) {.inline.} = + getGDNativeAPI().dictionaryErase(self, key) + +proc godotHash*(self: GodotDictionary): cint {.inline.} = + getGDNativeAPI().dictionaryHash(self, ) + +proc keys*(self: GodotDictionary): GodotArray {.inline.} = + getGDNativeAPI().dictionaryKeys(self) + +proc values*(self: GodotDictionary): GodotArray {.inline.} = + getGDNativeAPI().dictionaryValues(self) + +proc `[]`*(self: GodotDictionary; key: GodotVariant): GodotVariant {.inline.} = + getGDNativeAPI().dictionaryGet(self, key) + +proc `[]=`*(self: var GodotDictionary; key, value: GodotVariant) {.inline.} = + getGDNativeAPI().dictionarySet(self, key, value) + +proc mget*(self: var GodotDictionary; + key: GodotVariant): ptr GodotVariant {.inline.} = + getGDNativeAPI().dictionaryOperatorIndex(self, key) + +proc `==`*(self, other: GodotDictionary): bool {.inline.} = + getGDNativeAPI().dictionaryOperatorEqual(self, other) + +proc toJson*(self: GodotDictionary): GodotString {.inline.} = + getGDNativeAPI().dictionaryToJson(self) diff --git a/godot/internal/godotinternaltypes.nim b/godot/internal/godotinternaltypes.nim new file mode 100644 index 0000000..a2910c9 --- /dev/null +++ b/godot/internal/godotinternaltypes.nim @@ -0,0 +1,313 @@ +# Copyright 2018 Xored Software, Inc. + +const MAX_ARG_COUNT* = 256 + +type + GodotArray* {.byref.} = object + data: array[sizeof(int), byte] + + GodotDictionary* {.byref.} = object + data: array[sizeof(int), byte] + + GodotNodePath* {.byref.} = object + data: array[sizeof(int), byte] + + GodotObject* = object + + GodotPoolByteArray* {.byref.} = object + data: array[sizeof(int), byte] + GodotPoolByteArrayReadAccess* {.byref.} = object + data: array[1, byte] + GodotPoolByteArrayWriteAccess* {.byref.} = object + data: array[1, byte] + + GodotPoolIntArray* {.byref.} = object + data: array[sizeof(int), byte] + GodotPoolIntArrayReadAccess* {.byref.} = object + data: array[1, byte] + GodotPoolIntArrayWriteAccess* {.byref.} = object + data: array[1, byte] + + GodotPoolRealArray* {.byref.} = object + data: array[sizeof(int), byte] + GodotPoolRealArrayReadAccess* {.byref.} = object + data: array[1, byte] + GodotPoolRealArrayWriteAccess* {.byref.} = object + data: array[1, byte] + + GodotPoolStringArray* {.byref.} = object + data: array[sizeof(int), byte] + GodotPoolStringArrayReadAccess* {.byref.} = object + data: array[1, byte] + GodotPoolStringArrayWriteAccess* {.byref.} = object + data: array[1, byte] + + GodotPoolVector2Array* {.byref.} = object + data: array[sizeof(int), byte] + GodotPoolVector2ArrayReadAccess* {.byref.} = object + data: array[1, byte] + GodotPoolVector2ArrayWriteAccess* {.byref.} = object + data: array[1, byte] + + GodotPoolVector3Array* {.byref.} = object + data: array[sizeof(int), byte] + GodotPoolVector3ArrayReadAccess* {.byref.} = object + data: array[1, byte] + GodotPoolVector3ArrayWriteAccess* {.byref.} = object + data: array[1, byte] + + GodotPoolColorArray* {.byref.} = object + data: array[sizeof(int), byte] + GodotPoolColorArrayReadAccess* {.byref.} = object + data: array[1, byte] + GodotPoolColorArrayWriteAccess* {.byref.} = object + data: array[1, byte] + + GodotString* {.byref.} = object + data: array[sizeof(int), byte] + + cwchar_t* {.importc: "wchar_t", nodecl.} = object + + GodotCharString* {.byref.} = object + data: array[sizeof(int), byte] + + VariantType* {.size: sizeof(cint), pure.} = enum + Nil, ## atomic types + Bool, + Int, + Real, + String, + # math types + Vector2, ## 5 + Rect2, + Vector3, + Transform2D, + Plane, + Quat, ## 10 + AABB, + Basis, + Transform, ## misc types + Color, + NodePath, ## 15 + RID, + Object, + Dictionary, + Array, ## 20 + # arrays + PoolByteArray, + PoolIntArray, + PoolRealArray, + PoolStringArray, + PoolVector2Array, ## 25 + PoolVector3Array, + PoolColorArray + + VariantCallErrorType* {.size: sizeof(cint), pure.} = enum + OK, + InvalidMethod, + InvalidArgument, + TooManyArguments, + TooFewArguments, + InstanceIsNull + + VariantCallError* = object + error*: VariantCallErrorType + argument*: cint + expected*: VariantType + + GodotVariant* {.byref.} = object + data: array[2, int64] + data2: int + +type GodotMethodBind* = object + +type + GDNativeAPIVersion* = object + major*: cuint + minor*: cuint + + GDNativeInitOptions* = object + inEditor*: bool + coreApiHash*: uint64 + editorApiHash*: uint64 + noApiHash*: uint64 + reportVersionMismatch*: proc (library: ptr GodotObject, extension: cstring, + want: GDNativeAPIVersion, have: GDNativeAPIVersion) {.noconv.} + reportLoadingError*: proc (library: ptr GodotObject, what: cstring) {.noconv.} + gdNativeLibrary*: ptr GodotObject + gdNativeAPIStruct*: pointer + activeLibraryPath*: ptr GodotString + + GDNativeTerminateOptions* = object + inEditor*: bool + + GodotMethodRPCMode* {.size: sizeof(cint), pure.} = enum + Disabled, + Remote, + Sync, + Master, + Slave + + GodotMethodAttributes* = object + rpcMode*: GodotMethodRPCMode + + GodotPropertyHint* {.size: sizeof(cint), pure.} = enum + None, ## no hint provided. + Range, ## hint_text = "min,max,step,slider; // slider is optional" + ExpRange, ## hint_text = "min,max,step", exponential edit + Enum, ## hint_text= "val1,val2,val3,etc" + ExpEasing, ## exponential easing funciton (Math::ease) + Length, ## hint_text= "length" (as integer) + SpriteFrame, + KeyAccel, ## hint_text= "length" (as integer) + Flags, ## hint_text= "flag1,flag2,etc" (as bit flags) + Layers2DRender, + Layers2DPhysics, + Layers3DRender, + Layers3DPhysics, + File, ## a file path must be passed, hint_text (optionally) + ## is a filter "*.png,*.wav,*.doc," + Dir, ## a directort path must be passed + GlobalFile, ## a file path must be passed, hint_text (optionally) is a + ## filter "*.png,*.wav,*.doc," + GlobalDir, ## a directort path must be passed + ResourceType, ## a resource object type + MultilineText, ## used for string properties that can contain multiple lines + ColorNoAlpha, ## used for ignoring alpha component when editing a color + ImageCompressLossy, + ImageCompressLossless, + ObjectId, + TypeString, ## a type string, the hint is the base type to choose + NodePathToEditedNode, ## so something else can provide this + ## (used in scripts) + MethodOfVariantType, ## a method of a type + MethodOfBaseType, ## a method of a base type + MethodOfInstance, ## a method of an instance + MethodOfScript, ## a method of a script & base + PropertyOfVariantType, ## a property of a type + PropertyOfBaseType, ## a property of a base type + PropertyOfInstance, ## a property of an instance + PropertyOfScript, ## a property of a script & base + PropertyHintMax + +const + GODOT_PROPERTY_USAGE_STORAGE_VALUE = 1.cint + GODOT_PROPERTY_USAGE_EDITOR_VALUE = 2.cint + GODOT_PROPERTY_USAGE_NETWORK_VALUE = 4.cint + GODOT_PROPERTY_USAGE_EDITOR_HELPER_VALUE = 8.cint + GODOT_PROPERTY_USAGE_CHECKABLE_VALUE = 16.cint + GODOT_PROPERTY_USAGE_CHECKED_VALUE = 32.cint + GODOT_PROPERTY_USAGE_INTERNATIONALIZED_VALUE = 64.cint + GODOT_PROPERTY_USAGE_GROUP_VALUE = 128.cint + GODOT_PROPERTY_USAGE_CATEGORY_VALUE = 256.cint + GODOT_PROPERTY_USAGE_STORE_IF_NONZERO_VALUE = 512.cint + GODOT_PROPERTY_USAGE_STORE_IF_NONONE_VALUE = 1024.cint + GODOT_PROPERTY_USAGE_NO_INSTANCE_STATE_VALUE = 2048.cint + GODOT_PROPERTY_USAGE_RESTART_IF_CHANGED_VALUE = 4096.cint + GODOT_PROPERTY_USAGE_SCRIPT_VARIABLE_VALUE = 8192.cint + GODOT_PROPERTY_USAGE_STORE_IF_NULL_VALUE = 16384.cint + GODOT_PROPERTY_USAGE_ANIMATE_AS_TRIGGER_VALUE = 32768.cint + GODOT_PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED_VALUE = 65536.cint + + GODOT_PROPERTY_USAGE_DEFAULT_VALUE: cint = + GODOT_PROPERTY_USAGE_STORAGE_VALUE or GODOT_PROPERTY_USAGE_EDITOR_VALUE or + GODOT_PROPERTY_USAGE_NETWORK_VALUE + GODOT_PROPERTY_USAGE_DEFAULT_INTL_VALUE: cint = + GODOT_PROPERTY_USAGE_STORAGE_VALUE or + GODOT_PROPERTY_USAGE_EDITOR_VALUE or GODOT_PROPERTY_USAGE_NETWORK_VALUE or + GODOT_PROPERTY_USAGE_INTERNATIONALIZED_VALUE + GODOT_PROPERTY_USAGE_NOEDITOR_VALUE: cint = + GODOT_PROPERTY_USAGE_STORAGE_VALUE or GODOT_PROPERTY_USAGE_NETWORK_VALUE + +type + GodotPropertyUsage* {.size: sizeof(cint), pure.} = enum + Storage = GODOT_PROPERTY_USAGE_STORAGE_VALUE + Editor = GODOT_PROPERTY_USAGE_EDITOR_VALUE + Network = GODOT_PROPERTY_USAGE_NETWORK_VALUE + NoEditor = GODOT_PROPERTY_USAGE_NOEDITOR_VALUE + Default = GODOT_PROPERTY_USAGE_DEFAULT_VALUE + EditorHelper = GODOT_PROPERTY_USAGE_EDITOR_HELPER_VALUE + Checkable = GODOT_PROPERTY_USAGE_CHECKABLE_VALUE + ## used for editing global variables + Checked = GODOT_PROPERTY_USAGE_CHECKED_VALUE + ## used for editing global variables + Internationalized = GODOT_PROPERTY_USAGE_INTERNATIONALIZED_VALUE + ## hint for internationalized strings + DefaultIntl = GODOT_PROPERTY_USAGE_DEFAULT_INTL_VALUE + Group = GODOT_PROPERTY_USAGE_GROUP_VALUE + ## used for grouping props in the editor + Category = GODOT_PROPERTY_USAGE_CATEGORY_VALUE + NonZero = GODOT_PROPERTY_USAGE_STORE_IF_NONZERO_VALUE + ## only store if nonzero + NonOne = GODOT_PROPERTY_USAGE_STORE_IF_NONONE_VALUE + ## only store if false + NoInstanceState = GODOT_PROPERTY_USAGE_NO_INSTANCE_STATE_VALUE + RestartIfChanged = GODOT_PROPERTY_USAGE_RESTART_IF_CHANGED_VALUE + ScriptVariable = GODOT_PROPERTY_USAGE_SCRIPT_VARIABLE_VALUE + StoreIfNull = GODOT_PROPERTY_USAGE_STORE_IF_NULL_VALUE + AnimateAsTrigger = GODOT_PROPERTY_USAGE_ANIMATE_AS_TRIGGER_VALUE + UpdateAllIfModified = GODOT_PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED_VALUE + + GodotPropertyAttributes* {.bycopy.} = object + rsetType*: GodotMethodRPCMode + typ*: cint + hint*: GodotPropertyHint + hintString*: GodotString + usage*: cint + defaultValue*: GodotVariant + + GodotInstanceCreateFunc* {.bycopy.} = object + createFunc*: + proc (obj: ptr GodotObject; methodData: pointer): pointer {.noconv.} + ## returns user data + methodData*: pointer + freeFunc*: proc (a2: pointer) {.noconv.} + + GodotInstanceDestroyFunc* {.bycopy.} = object + destroyFunc*: + proc (obj: ptr GodotObject; methodData: pointer; + userData: pointer) {.noconv.} + methodData*: pointer + freeFunc*: proc (a2: pointer) {.noconv.} + + GodotInstanceMethod* {.bycopy.} = object + meth*: + proc (obj: ptr GodotObject; methodData: pointer; + userData: pointer; numArgs: cint; + args: var array[MAX_ARG_COUNT, ptr GodotVariant]): + GodotVariant {.noconv.} + methodData*: pointer + freeFunc*: proc (a2: pointer) {.noconv.} + + GodotPropertySetFunc* {.bycopy.} = object + setFunc*: proc (obj: ptr GodotObject; methodData: pointer; + userData: pointer; value: GodotVariant) {.noconv.} + methodData*: pointer + freeFunc*: proc (a2: pointer) {.noconv.} + + GodotPropertyGetFunc* {.bycopy.} = object + getFunc*: proc (obj: ptr GodotObject; methodData: pointer; + userData: pointer): GodotVariant {.noconv.} + methodData*: pointer + freeFunc*: proc (a2: pointer) {.noconv.} + + GodotSignalArgument* {.bycopy.} = object + name*: GodotString + typ*: cint + hint*: GodotPropertyHint + hintString*: GodotString + usage*: cint + defaultValue*: GodotVariant + + GodotSignal* = object + name*: GodotString + numArgs*: cint + args*: ptr GodotSignalArgument + numDefaultArgs*: cint + defaultArgs*: ptr GodotVariant + + GodotClassConstructor* = proc (): ptr GodotObject {. + noconv, gcsafe, locks: 0, raises: [], tags: [].} + +template offset*[T](p: ptr T, offset: int): ptr T = + cast[ptr T](cast[ByteAddress](p) +% (offset * sizeof(T))) \ No newline at end of file diff --git a/godot/internal/godotnodepaths.nim b/godot/internal/godotnodepaths.nim new file mode 100644 index 0000000..b4578c0 --- /dev/null +++ b/godot/internal/godotnodepaths.nim @@ -0,0 +1,40 @@ +# Copyright 2018 Xored Software, Inc. + +import godotinternaltypes, gdnativeapi + +proc initGodotNodePath*(dest: var GodotNodePath; s: GodotString) {.inline.} = + getGDNativeAPI().nodePathNew(dest, s) + +proc initGodotNodePath*(dest: var GodotNodePath; + src: GodotNodePath) {.inline.} = + getGDNativeAPI().nodePathNewCopy(dest, src) + +proc deinit*(self: var GodotNodePath) {.inline.} = + getGDNativeAPI().nodePathDestroy(self) + +proc toGodotString*(self: GodotNodePath): GodotString {.inline.} = + getGDNativeAPI().nodePathAsString(self) + +proc isAbsolute*(self: GodotNodePath): bool {.inline.} = + getGDNativeAPI().nodePathIsAbsolute(self) + +proc nameCount*(self: GodotNodePath): cint {.inline.} = + getGDNativeAPI().nodePathGetNameCount(self) + +proc getName*(self: GodotNodePath; idx: cint): GodotString {.inline.} = + getGDNativeAPI().nodePathGetName(self, idx) + +proc subnameCount*(self: GodotNodePath): cint {.inline.} = + getGDNativeAPI().nodePathGetSubnameCount(self) + +proc getSubname*(self: GodotNodePath; idx: cint): GodotString {.inline.} = + getGDNativeAPI().nodePathGetSubname(self, idx) + +proc getConcatenatedSubnames*(self: GodotNodePath): GodotString {.inline.} = + getGDNativeAPI().nodePathGetConcatenatedSubnames(self) + +proc isEmpty*(self: GodotNodePath): bool {.inline.} = + getGDNativeAPI().nodePathIsEmpty(self) + +proc `==`*(a, b: GodotNodePath): bool {.inline.} = + getGDNativeAPI().nodePathOperatorEqual(a, b) diff --git a/godot/internal/godotpoolarrays.nim b/godot/internal/godotpoolarrays.nim new file mode 100644 index 0000000..119848f --- /dev/null +++ b/godot/internal/godotpoolarrays.nim @@ -0,0 +1,269 @@ +# Copyright (c) 2018 Xored Software, Inc. + +import godotinternaltypes, gdnativeapi +import core/godotcoretypes + +template genPoolArrayAPI(ArrayT, initIdent, DataT, + newProc, newCopyProc, newWithArrayProc, appendProc, + appendArrayProc, insertProc, invertProc, pushBackProc, + removeProc, resizeProc, setProc, getProc, sizeProc, + destroyProc, readProc, writeProc, + readAccessPtrProc, writeAccessPtrProc, + readAccessDestroyProc, writeAccessDestroyProc) = + proc initIdent*(dest: var ArrayT) {.inline.} = + getGDNativeAPI().newProc(dest) + + proc initIdent*(dest: var ArrayT; src: ArrayT) {.inline.} = + getGDNativeAPI().newCopyProc(dest, src) + + proc initIdent*(dest: var ArrayT; arr: GodotArray) {.inline.} = + getGDNativeAPI().newWithArrayProc(dest, arr) + + proc deinit*(self: var ArrayT) {.inline.} = + getGDNativeAPI().destroyProc(self) + + proc add*(self: var ArrayT; data: DataT) {.inline.} = + getGDNativeAPI().pushBackProc(self, data) + + proc add*(self: var ArrayT; arr: ArrayT) {.inline.} = + getGDNativeAPI().appendArrayProc(self, arr) + + proc insert*(self: var ArrayT; idx: cint; + data: DataT): Error {.inline.} = + getGDNativeAPI().insertProc(self, idx, data) + + proc delete*(self: var ArrayT; idx: cint) {.inline.} = + getGDNativeAPI().removeProc(self, idx) + + proc reverse*(self: var ArrayT) {.inline.} = + getGDNativeAPI().invertProc(self) + + proc setLen*(self: var ArrayT; size: cint) {.inline.} = + getGDNativeAPI().resizeProc(self, size) + + proc `[]=`*(self: var ArrayT; idx: cint; data: DataT) {.inline.} = + getGDNativeAPI().setProc(self, idx, data) + + proc `[]`*(self: ArrayT; idx: cint): DataT {.inline.} = + let data = getGDNativeAPI().getProc(self, idx) + when DataT is Color: + data.toColor() + elif DataT is Vector2: + data.toVector2() + elif DataT is Vector3: + data.toVector3() + else: + data + + proc len*(self: ArrayT): cint {.inline.} = + getGDNativeAPI().sizeProc(self) + + iterator items*(self: ArrayT): DataT = + let readAccess = getGDNativeAPI().readProc(self) + let readPtr = getGDNativeAPI().readAccessPtrProc(readAccess) + for i in 0.cint..= ownLen: + let instInfo = instantiationInfo() + getGDNativeAPI().printError( + cstring"Invalid subarray begin index", cstring"subarray", instInfo.filename, instInfo.line.cint) + return + if actualIdxTo < 0 or actualIdxTo >= ownLen: + let instInfo = instantiationInfo() + getGDNativeAPI().printError( + cstring"Invalid subarray end index", cstring"subarray", instInfo.filename, instInfo.line.cint) + return + let span = actualIdxTo - actualIdxFrom + 1 + result.setLen(span) + let readAccess = getGDNativeAPI().readProc(self) + let writeAccess = getGDNativeAPI().writeProc(result) + let readPtr = getGDNativeAPI().readAccessPtrProc(readAccess).offset(actualIdxFrom) + copyMem(getGDNativeAPI().writeAccessPtrProc(writeAccess), readPtr, span) + getGDNativeAPI().readAccessDestroyProc(readAccess) + getGDNativeAPI().writeAccessDestroyProc(writeAccess) + +genPoolArrayAPI(GodotPoolByteArray, initGodotPoolByteArray, byte, + poolByteArrayNew, + poolByteArrayNewCopy, + poolByteArrayNewWithArray, + poolByteArrayAppend, + poolByteArrayAppendArray, + poolByteArrayInsert, + poolByteArrayInvert, + poolByteArrayPushBack, + poolByteArrayRemove, + poolByteArrayResize, + poolByteArraySet, + poolByteArrayGet, + poolByteArraySize, + poolByteArrayDestroy, + poolByteArrayRead, + poolByteArrayWrite, + poolByteArrayReadAccessPtr, + poolByteArrayWriteAccessPtr, + poolByteArrayReadAccessDestroy, + poolByteArrayWriteAccessDestroy) + +genPoolArrayAPI(GodotPoolIntArray, initGodotPoolIntArray, cint, + poolIntArrayNew, + poolIntArrayNewCopy, + poolIntArrayNewWithArray, + poolIntArrayAppend, + poolIntArrayAppendArray, + poolIntArrayInsert, + poolIntArrayInvert, + poolIntArrayPushBack, + poolIntArrayRemove, + poolIntArrayResize, + poolIntArraySet, + poolIntArrayGet, + poolIntArraySize, + poolIntArrayDestroy, + poolIntArrayRead, + poolIntArrayWrite, + poolIntArrayReadAccessPtr, + poolIntArrayWriteAccessPtr, + poolIntArrayReadAccessDestroy, + poolIntArrayWriteAccessDestroy) + +genPoolArrayAPI(GodotPoolRealArray, initGodotPoolRealArray, float32, + poolRealArrayNew, + poolRealArrayNewCopy, + poolRealArrayNewWithArray, + poolRealArrayAppend, + poolRealArrayAppendArray, + poolRealArrayInsert, + poolRealArrayInvert, + poolRealArrayPushBack, + poolRealArrayRemove, + poolRealArrayResize, + poolRealArraySet, + poolRealArrayGet, + poolRealArraySize, + poolRealArrayDestroy, + poolRealArrayRead, + poolRealArrayWrite, + poolRealArrayReadAccessPtr, + poolRealArrayWriteAccessPtr, + poolRealArrayReadAccessDestroy, + poolRealArrayWriteAccessDestroy) + +genPoolArrayAPI(GodotPoolStringArray, initGodotPoolStringArray, GodotString, + poolStringArrayNew, + poolStringArrayNewCopy, + poolStringArrayNewWithArray, + poolStringArrayAppend, + poolStringArrayAppendArray, + poolStringArrayInsert, + poolStringArrayInvert, + poolStringArrayPushBack, + poolStringArrayRemove, + poolStringArrayResize, + poolStringArraySet, + poolStringArrayGet, + poolStringArraySize, + poolStringArrayDestroy, + poolStringArrayRead, + poolStringArrayWrite, + poolStringArrayReadAccessPtr, + poolStringArrayWriteAccessPtr, + poolStringArrayReadAccessDestroy, + poolStringArrayWriteAccessDestroy) + +genPoolArrayAPI(GodotPoolVector2Array, initGodotPoolVector2Array, Vector2, + poolVector2ArrayNew, + poolVector2ArrayNewCopy, + poolVector2ArrayNewWithArray, + poolVector2ArrayAppend, + poolVector2ArrayAppendArray, + poolVector2ArrayInsert, + poolVector2ArrayInvert, + poolVector2ArrayPushBack, + poolVector2ArrayRemove, + poolVector2ArrayResize, + poolVector2ArraySet, + poolVector2ArrayGet, + poolVector2ArraySize, + poolVector2ArrayDestroy, + poolVector2ArrayRead, + poolVector2ArrayWrite, + poolVector2ArrayReadAccessPtr, + poolVector2ArrayWriteAccessPtr, + poolVector2ArrayReadAccessDestroy, + poolVector2ArrayWriteAccessDestroy) + +genPoolArrayAPI(GodotPoolVector3Array, initGodotPoolVector3Array, Vector3, + poolVector3ArrayNew, + poolVector3ArrayNewCopy, + poolVector3ArrayNewWithArray, + poolVector3ArrayAppend, + poolVector3ArrayAppendArray, + poolVector3ArrayInsert, + poolVector3ArrayInvert, + poolVector3ArrayPushBack, + poolVector3ArrayRemove, + poolVector3ArrayResize, + poolVector3ArraySet, + poolVector3ArrayGet, + poolVector3ArraySize, + poolVector3ArrayDestroy, + poolVector3ArrayRead, + poolVector3ArrayWrite, + poolVector3ArrayReadAccessPtr, + poolVector3ArrayWriteAccessPtr, + poolVector3ArrayReadAccessDestroy, + poolVector3ArrayWriteAccessDestroy) + +genPoolArrayAPI(GodotPoolColorArray, initGodotPoolColorArray, Color, + poolColorArrayNew, + poolColorArrayNewCopy, + poolColorArrayNewWithArray, + poolColorArrayAppend, + poolColorArrayAppendArray, + poolColorArrayInsert, + poolColorArrayInvert, + poolColorArrayPushBack, + poolColorArrayRemove, + poolColorArrayResize, + poolColorArraySet, + poolColorArrayGet, + poolColorArraySize, + poolColorArrayDestroy, + poolColorArrayRead, + poolColorArrayWrite, + poolColorArrayReadAccessPtr, + poolColorArrayWriteAccessPtr, + poolColorArrayReadAccessDestroy, + poolColorArrayWriteAccessDestroy) diff --git a/godot/internal/godotstrings.nim b/godot/internal/godotstrings.nim new file mode 100644 index 0000000..e67acfd --- /dev/null +++ b/godot/internal/godotstrings.nim @@ -0,0 +1,54 @@ +# Copyright (c) 2018 Xored Software, Inc. + +import godotinternaltypes, gdnativeapi + +proc initGodotString(dest: var GodotString) {.inline, raises: [].} = + getGDNativeAPI().stringNew(dest) + +proc initGodotString(dest: var GodotString; contents: cstring; + size: cint) {.inline.} = + ## Initializes ``dest`` from UTF-8 ``contents`` + dest = getGDNativeAPI().stringCharsToUtf8WithLen(contents, size) + +proc `==`*(self, b: GodotString): bool {.inline.} = + getGDNativeAPI().stringOperatorEqual(self, b) + +proc `<`*(self, b: GodotString): bool {.inline.} = + getGDNativeAPI().stringOperatorLess(self, b) + +proc `&`*(self, b: GodotString): GodotString {.inline.} = + getGDNativeAPI().stringOperatorPlus(self, b) + +proc deinit*(self: var GodotString) {.inline.} = + getGDNativeAPI().stringDestroy(self) + +proc len*(self: GodotString): cint {.inline.} = + getGDNativeAPI().stringLength(self) + +proc dataPtr*(self: GodotString): ptr cwchar_t {.inline.} = + getGDNativeAPI().stringWideStr(self) + +proc `$`*(self: GodotString): string = + ## Converts the ``GodotString`` into Nim string + var charStr = getGDNativeAPI().stringUtf8(self) + let length = getGDNativeAPI().charStringLength(charStr) + result = newString(length) + copyMem(addr result[0], getGDNativeAPI().charStringGetData(charStr), length) + getGDNativeAPI().charStringDestroy(charStr) + +proc toGodotString*(s: string): GodotString {.inline.} = + ## Converts the Nim string into ``GodotString`` + when (NimMajor, NimMinor, NimPatch) < (0, 19, 0): + if s.isNil: + initGodotString(result) + else: + initGodotString(result, cstring(s), cint(s.len + 1)) + else: + initGodotString(result, cstring(s), cint(s.len + 1)) + +proc toGodotString*(s: cstring): GodotString {.inline.} = + ## Converts the cstring into ``GodotString`` + if s.isNil: + initGodotString(result) + else: + initGodotString(result, s, cint(s.len + 1)) diff --git a/godot/internal/godotvariants.nim b/godot/internal/godotvariants.nim new file mode 100644 index 0000000..0a0980f --- /dev/null +++ b/godot/internal/godotvariants.nim @@ -0,0 +1,217 @@ +# Copyright 2018 Xored Software, Inc. + +import core/godotcoretypes, godotinternaltypes, gdnativeapi + +proc getType*(p: GodotVariant): VariantType {.inline.} = + getGDNativeAPI().variantGetType(p) + +proc initGodotVariant*(dest: var GodotVariant) {.inline.} = + getGDNativeAPI().variantNewNil(dest) + +proc initGodotVariant*(dest: var GodotVariant, src: GodotVariant) {.inline.} = + getGDNativeAPI().variantNewCopy(dest, src) + +proc initGodotVariant*(dest: var GodotVariant; b: bool) {.inline.} = + getGDNativeAPI().variantNewBool(dest, b) + +proc initGodotVariant*(dest: var GodotVariant; i: uint64) {.inline.} = + getGDNativeAPI().variantNewUInt(dest, i) + +proc initGodotVariant*(dest: var GodotVariant; i: int64) {.inline.} = + getGDNativeAPI().variantNewInt(dest, i) + +proc initGodotVariant*(dest: var GodotVariant; r: cdouble) {.inline.} = + getGDNativeAPI().variantNewReal(dest, r) + +proc initGodotVariant*(dest: var GodotVariant; s: GodotString) {.inline.} = + getGDNativeAPI().variantNewString(dest, s) + +proc initGodotVariant*(dest: var GodotVariant; v2: Vector2) {.inline.} = + getGDNativeAPI().variantNewVector2(dest, v2) + +proc initGodotVariant*(dest: var GodotVariant; rect2: Rect2) {.inline.} = + getGDNativeAPI().variantNewRect2(dest, rect2) + +proc initGodotVariant*(dest: var GodotVariant; v3: Vector3) {.inline.} = + getGDNativeAPI().variantNewVector3(dest, v3) + +proc initGodotVariant*(dest: var GodotVariant; t2d: Transform2D) {.inline.} = + getGDNativeAPI().variantNewTransform2D(dest, t2d) + +proc initGodotVariant*(dest: var GodotVariant; plane: Plane) {.inline.} = + getGDNativeAPI().variantNewPlane(dest, plane) + +proc initGodotVariant*(dest: var GodotVariant; quat: Quat) {.inline.} = + getGDNativeAPI().variantNewQuat(dest, quat) + +proc initGodotVariant*(dest: var GodotVariant; aabb: AABB) {.inline.} = + getGDNativeAPI().variantNewAABB(dest, aabb) + +proc initGodotVariant*(dest: var GodotVariant; basis: Basis) {.inline.} = + getGDNativeAPI().variantNewBasis(dest, basis) + +proc initGodotVariant*(dest: var GodotVariant; trans: Transform) {.inline.} = + getGDNativeAPI().variantNewTransform(dest, trans) + +proc initGodotVariant*(dest: var GodotVariant; color: Color) {.inline.} = + getGDNativeAPI().variantNewColor(dest, color) + +proc initGodotVariant*(dest: var GodotVariant; + nodePath: GodotNodePath) {.inline.} = + getGDNativeAPI().variantNewNodePath(dest, nodePath) + +proc initGodotVariant*(dest: var GodotVariant; rid: RID) {.inline.} = + getGDNativeAPI().variantNewRID(dest, rid) + +proc initGodotVariant*(dest: var GodotVariant; + obj: ptr GodotObject) {.inline.} = + getGDNativeAPI().variantNewObject(dest, obj) + +proc initGodotVariant*(dest: var GodotVariant; arr: GodotArray) {.inline.} = + getGDNativeAPI().variantNewArray(dest, arr) + +proc initGodotVariant*(dest: var GodotVariant; + pba: GodotPoolByteArray) {.inline.} = + getGDNativeAPI().variantNewPoolByteArray(dest, pba) + +proc initGodotVariant*(dest: var GodotVariant; + pia: GodotPoolIntArray) {.inline.} = + getGDNativeAPI().variantNewPoolIntArray(dest, pia) + +proc initGodotVariant*(dest: var GodotVariant; + pra: GodotPoolRealArray) {.inline.} = + getGDNativeAPI().variantNewPoolRealArray(dest, pra) + +proc initGodotVariant*(dest: var GodotVariant; + psa: GodotPoolStringArray) {.inline.} = + getGDNativeAPI().variantNewPoolStringArray(dest, psa) + +proc initGodotVariant*(dest: var GodotVariant; + pv2a: GodotPoolVector2Array) {.inline.} = + getGDNativeAPI().variantNewPoolVector2Array(dest, pv2a) + +proc initGodotVariant*(dest: var GodotVariant; + pv3a: GodotPoolVector3Array) {.inline.} = + getGDNativeAPI().variantNewPoolVector3Array(dest, pv3a) + +proc initGodotVariant*(dest: var GodotVariant; + pca: GodotPoolColorArray) {.inline.} = + getGDNativeAPI().variantNewPoolColorArray(dest, pca) + +proc initGodotVariant*(dest: var GodotVariant; + dict: GodotDictionary) {.inline.} = + getGDNativeAPI().variantNewDictionary(dest, dict) + +proc deinit*(v: var GodotVariant) {.inline.} = + getGDNativeAPI().variantDestroy(v) + +proc asBool*(self: GodotVariant): bool {.inline.} = + getGDNativeAPI().variantAsBool(self) + +proc asUInt*(self: GodotVariant): uint64 {.inline.} = + getGDNativeAPI().variantAsUInt(self) + +proc asInt*(self: GodotVariant): int64 {.inline.} = + getGDNativeAPI().variantAsInt(self) + +proc asReal*(self: GodotVariant): cdouble {.inline.} = + getGDNativeAPI().variantAsReal(self) + +proc asGodotString*(self: GodotVariant): GodotString {.inline.} = + getGDNativeAPI().variantAsString(self) + +proc asVector2*(self: GodotVariant): Vector2 {.inline.} = + getGDNativeAPI().variantAsVector2(self).toVector2() + +proc asRect2*(self: GodotVariant): Rect2 {.inline.} = + getGDNativeAPI().variantAsRect2(self).toRect2() + +proc asVector3*(self: GodotVariant): Vector3 {.inline.} = + getGDNativeAPI().variantAsVector3(self).toVector3() + +proc asTransform2D*(self: GodotVariant): Transform2D {.inline.} = + getGDNativeAPI().variantAsTransform2D(self).toTransform2D() + +proc asPlane*(self: GodotVariant): Plane {.inline.} = + getGDNativeAPI().variantAsPlane(self).toPlane() + +proc asQuat*(self: GodotVariant): Quat {.inline.} = + getGDNativeAPI().variantAsQuat(self).toQuat() + +proc asAABB*(self: GodotVariant): AABB {.inline.} = + getGDNativeAPI().variantAsAABB(self).toAABB() + +proc asBasis*(self: GodotVariant): Basis {.inline.} = + getGDNativeAPI().variantAsBasis(self).toBasis() + +proc asTransform*(self: GodotVariant): Transform {.inline.} = + getGDNativeAPI().variantAsTransform(self).toTransform() + +proc asColor*(self: GodotVariant): Color {.inline.} = + getGDNativeAPI().variantAsColor(self).toColor() + +proc asNodePath*(self: GodotVariant): GodotNodePath {.inline.} = + getGDNativeAPI().variantAsNodePath(self) + +proc asRID*(self: GodotVariant): RID {.inline.} = + getGDNativeAPI().variantAsRID(self) + +proc asGodotObject*(self: GodotVariant): ptr GodotObject {.inline.} = + getGDNativeAPI().variantAsObject(self) + +proc asGodotArray*(self: GodotVariant): GodotArray {.inline.} = + getGDNativeAPI().variantAsArray(self) + +proc asGodotPoolByteArray*(self: GodotVariant): GodotPoolByteArray {.inline.} = + getGDNativeAPI().variantAsPoolByteArray(self) + +proc asGodotPoolIntArray*(self: GodotVariant): GodotPoolIntArray {.inline.} = + getGDNativeAPI().variantAsPoolIntArray(self) + +proc asGodotPoolRealArray*(self: GodotVariant): GodotPoolRealArray {.inline.} = + getGDNativeAPI().variantAsPoolRealArray(self) + +proc asGodotPoolStringArray*(self: GodotVariant): GodotPoolStringArray + {.inline.} = + getGDNativeAPI().variantAsPoolStringArray(self) + +proc asGodotPoolVector2Array*(self: GodotVariant): GodotPoolVector2Array + {.inline.} = + getGDNativeAPI().variantAsPoolVector2Array(self) + +proc asGodotPoolVector3Array*(self: GodotVariant): GodotPoolVector3Array + {.inline.} = + getGDNativeAPI().variantAsPoolVector3Array(self) + +proc asGodotPoolColorArray*(self: GodotVariant): GodotPoolColorArray + {.inline.} = + getGDNativeAPI().variantAsPoolColorArray(self) + +proc asGodotDictionary*(self: GodotVariant): GodotDictionary {.inline.} = + getGDNativeAPI().variantAsDictionary(self) + +proc call*(self: var GodotVariant; meth: GodotString; + args: ptr array[256, ptr GodotVariant]; argCount: cint; + error: var VariantCallError): GodotVariant {.inline.} = + getGDNativeAPI().variantCall(self, meth, args, argCount, error) + +proc hasMethod*(self: GodotVariant; meth: GodotString): bool {.inline.} = + getGDNativeAPI().variantHasMethod(self, meth) + +proc `==`*(self, other: GodotVariant): bool {.inline.} = + getGDNativeAPI().variantOperatorEqual(self, other) + +proc `<`*(self, other: GodotVariant): bool {.inline.} = + getGDNativeAPI().variantOperatorLess(self, other) + +proc hashCompare*(self, other: GodotVariant): bool {.inline.} = + getGDNativeAPI().variantHashCompare(self, other) + +proc booleanize*(self: GodotVariant): bool {.inline.} = + getGDNativeAPI().variantBooleanize(self) + +import godotstrings +proc `$`*(self: GodotVariant): string = + var s = self.asGodotString() + result = $s + s.deinit() diff --git a/godot/internal/nim.cfg b/godot/internal/nim.cfg new file mode 100644 index 0000000..f1fb6a7 --- /dev/null +++ b/godot/internal/nim.cfg @@ -0,0 +1 @@ +--path:"$projectdir/../" \ No newline at end of file diff --git a/godot/nim/godotmacros.nim b/godot/nim/godotmacros.nim index d8ae49c..6b81f7e 100644 --- a/godot/nim/godotmacros.nim +++ b/godot/nim/godotmacros.nim @@ -1,8 +1,8 @@ -# Copyright 2017 Xored Software, Inc. +# Copyright 2018 Xored Software, Inc. -import macros, tables, typetraits -import "../core/godotcore.nim" -import godotnim +import macros, tables, typetraits, strutils, sets, sequtils, options, algorithm +import godotinternal, internal/godotvariants +import godotnim, core/variants type VarDecl = ref object @@ -10,9 +10,10 @@ type typ: NimNode defaultValue: NimNode isNoGodot: bool - hint: string - hintTip: string - usage: string + hint: Option[string] + hintStr: Option[string] + usage: NimNode + isExported: bool MethodDecl = ref object name: string @@ -27,70 +28,62 @@ type parentName: string fields: seq[VarDecl] methods: seq[MethodDecl] + isTool: bool ParseError = object of Exception +include "internal/backwardcompat.inc.nim" + +proc godotToNim[T](val: Variant): (T, ConversionResult) = + mixin fromVariant + result[1] = fromVariant(result[0], val) + +proc nimToGodot[T](val: T): Variant = + mixin toVariant + when compiles(toVariant(val)): + result = toVariant(val) + else: + const err = "Cannot convert Nim value of type " & T.name & + " into Variant" + {.error: err.} + template parseError(node: NimNode, msg: string) = raise newException(ParseError, lineinfo(node) & ": " & msg) proc extractNames(definition: NimNode): tuple[name, parentName: string] = if definition.kind == nnkIdent: - result.name = $(definition.ident) + result.name = definition.strVal else: - if not (definition.kind == nnkInfix and definition[0].ident == !"of"): + if not (definition.kind == nnkInfix and + definition[0].strVal == "of"): parseError(definition, "invalid type definition") - result.name = $(definition[1].ident) + result.name = definition[1].strVal case definition[2].kind: of nnkIdent: - result.parentName = $definition[2].ident + result.parentName = definition[2].strVal else: parseError(definition[2], "parent type expected") -proc newRStrLit(s: string): NimNode {.compileTime.} = - result = newNimNode(nnkRStrLit) - result.strVal = s +when not declared(newRStrLit): + proc newRStrLit(s: string): NimNode {.compileTime.} = + result = newNimNode(nnkRStrLit) + result.strVal = s proc newCStringLit(s: string): NimNode {.compileTime.} = newNimNode(nnkCallStrLit).add(ident("cstring"), newRStrLit(s)) iterator pragmas(node: NimNode): - tuple[key: NimIdent, value: string, index: int] = + tuple[key: string, value: NimNode, index: int] = assert node.kind in {nnkPragma, nnkEmpty} for index in countdown(node.len - 1, 0): if node[index].kind == nnkExprColonExpr: - let val = $(node[index][1]) - yield (node[index][0].ident, val, index) + yield (node[index][0].strVal, node[index][1], index) elif node[index].kind == nnkIdent: - yield (node[index].ident, nil, index) + yield (node[index].strVal, nil, index) -proc hasPragma(statement: NimNode, pname: string): bool = - ## Checks if the pragma is present in the `statement` - if not (RoutineNodes.contains(statement.kind) or - statement.kind == nnkPragmaExpr): - return false - var pragmas = if RoutineNodes.contains(statement.kind): statement.pragma() - else: statement[1] - let pnameIdent = !pname - for ident, val, i in pragmas(pragmas): - if ident == pnameIdent: - return true - -proc removePragma(statement: NimNode, pname: string): bool = - ## Removes the pragma from the node and returns whether pragma was removed - if not (RoutineNodes.contains(statement.kind) or - statement.kind == nnkPragmaExpr): - return false - var pragmas = if RoutineNodes.contains(statement.kind): statement.pragma() - else: statement[1] - let pnameIdent = !pname - for ident, val, i in pragmas(pragmas): - if ident == pnameIdent: - pragmas.del(i) - return true - -proc removeStrPragma(statement: NimNode, - pname: string): string {.compileTime.} = +proc removePragmaNode(statement: NimNode, + pname: string): NimNode {.compileTime.} = ## Removes the pragma from the node and returns value of the pragma ## Works for routine nodes or nnkPragmaExpr if not (RoutineNodes.contains(statement.kind) or @@ -100,11 +93,30 @@ proc removeStrPragma(statement: NimNode, result = nil var pragmas = if RoutineNodes.contains(statement.kind): statement.pragma() else: statement[1] - let pnameIdent = !pname for ident, val, i in pragmas(pragmas): - if ident == pnameIdent: + if ident.eqIdent(pname): pragmas.del(i) - return (if val.isNil: "" else: val) + return val + +proc removePragma(statement: NimNode, pname: string): bool = + ## Removes the pragma from the node and returns whether pragma was removed + if not (RoutineNodes.contains(statement.kind) or + statement.kind == nnkPragmaExpr): + return false + var pragmas = if RoutineNodes.contains(statement.kind): statement.pragma() + else: statement[1] + for ident, val, i in pragmas(pragmas): + if ident.eqIdent(pname): + pragmas.del(i) + return true + +proc removeStrPragma(statement: NimNode, + pname: string): Option[string] {.compileTime.} = + ## Removes the pragma from the node and returns value of the pragma + ## Works for routine nodes or nnkPragmaExpr + let node = removePragmaNode(statement, pname) + result = if node.isNil: none(string) + else: some($node) proc isExported(node: NimNode): bool {.compileTime.} = if node.kind == nnkPragmaExpr: @@ -116,38 +128,36 @@ proc identDefsToVarDecls(identDefs: NimNode): seq[VarDecl] = assert(identDefs.kind == nnkIdentDefs) result = newSeqOfCap[VarDecl](identDefs.len - 2) + var typ = identDefs[identDefs.len - 2] + if typ.kind == nnkEmpty: + let defaultValue = identDefs[identDefs.len - 1] + if defaultValue.kind != nnkEmpty: + typ = newCall("type", defaultValue) + for i in 0..<(identDefs.len - 2): let nameNode = identDefs[i].copyNimTree() let hint = removeStrPragma(nameNode, "hint") - let hintTip = removeStrPragma(nameNode, "tip") - let usage = removeStrPragma(nameNode, "usage") + let hintStr = removeStrPragma(nameNode, "hintStr") + let usage = removePragmaNode(nameNode, "usage") let isGdExport = removePragma(nameNode, "gdExport") - if not nameNode.isExported() and isGdExport: - parseError(nameNode, "gdExport is not applicable for private fields") - - let isNoGodot = not nameNode.isExported() or not isGdExport result.add(VarDecl( name: if nameNode.kind == nnkPragmaExpr: nameNode[0].basename() else: nameNode.basename(), - typ: identDefs[identDefs.len - 2], + typ: typ, defaultValue: identDefs[identDefs.len - 1], hint: hint, - hintTip: hintTip, - isNoGodot: isNoGodot, - usage: usage + hintStr: hintStr, + isNoGodot: not isGdExport, + usage: usage, + isExported: nameNode.isExported() )) proc parseMethod(meth: NimNode): MethodDecl = assert(meth.kind in {nnkProcDef, nnkMethodDef}) - let methName = meth[0] let isGdExport = removePragma(meth, "gdExport") - if not methName.isExported() and isGdExport: - parseError(meth, "gdExport is not applicable for private procs/methods") - let isNoGodot = meth.kind != nnkMethodDef and ( - not methName.isExported() or - not isGdExport - ) or removePragma(meth, "noExport") + let isNoGodot = (meth.kind != nnkMethodDef and not isGdExport) or + removePragma(meth, "noGdExport") result = MethodDecl( name: $meth[0].basename, args: newSeq[VarDecl](), @@ -162,16 +172,33 @@ proc parseMethod(meth: NimNode): MethodDecl = proc parseVarSection(decl: NimNode): seq[VarDecl] = assert(decl.kind == nnkVarSection) - result = identDefsToVarDecls(decl[0]) + for i in 0..`_: + ## + ## .. code-block:: nim + ## import godot, editor_plugin + ## + ## gdobj(MyTool of EditorPlugin, tool): + ## method enterTree*() = + ## print("MyTool initialized!") + ## + ## Objects can be instantiated by invoking + ## `gdnew `_ or by using + ## `load `_ or any other way + ## that you can find in `Godot API `_. + let typeDef = parseType(ast) result = genType(typeDef) diff --git a/godot/nim/godotnim.nim b/godot/nim/godotnim.nim index 227004e..7f3ed96 100644 --- a/godot/nim/godotnim.nim +++ b/godot/nim/godotnim.nim @@ -1,21 +1,52 @@ -# Copyright 2017 Xored Software, Inc. +# Copyright 2018 Xored Software, Inc. -import tables, typetraits, macros -import "../core/godotbase.nim", "../core/godotcore.nim" -import "../core/strings.nim", "../core/vector2.nim", "../core/rect2.nim", - "../core/vector3.nim", "../core/transform2d.nim", - "../core/plane.nim", "../core/quat.nim", "../core/rect3.nim", - "../core/basis.nim", "../core/transform.nim", "../core/color.nim", - "../core/nodepath.nim", "../core/rid.nim", "../core/dictionary.nim", - "../core/arrays.nim", "../core/poolarray.nim", "../core/variant.nim" +import tables, typetraits, macros, unicode, strutils, sets, options +import gdnativeapi +import core/godotcoretypes, core/godotbase +import core/vector2, core/rect2, + core/vector3, core/transform2d, + core/planes, core/quats, core/aabb, + core/basis, core/transforms, core/colors, + core/nodepaths, core/rids, core/dictionaries, + core/arrays, core/poolarrays, core/variants +import godotinternal -## Definition of NimGodotObject and converters for built-in types. +## This module defines ``NimGodotObject`` and ``toVariant``/``fromVariant`` +## converters for Nim types. The converters are used by +## `gdobj `_ macro to import/export +## values from/to Godot (editor, GDScript). +## +## You can also allow conversion of any custom type ``MyType`` by implementing: +## +## .. code-block:: nim +## proc godotTypeInfo*(T: typedesc[MyType]): GodotTypeInfo +## proc toVariant*(self: MyType): Variant +## proc fromVariant*(self: var MyType, val: Variant): ConversionResult +## +## Implementing ``godotTypeInfo`` is optional and is necessary only if you want +## the type to be editable from the editor. type NimGodotObject* = ref object of RootObj + ## The base type all Godot types inherit from. + ## Manages lifecycle of the wrapped ``GodotObject``. godotObject: ptr GodotObject + linkedObjectPtr: pointer + ## Wrapper around native object that is the container of the Nim "script" + ## This is needed for `of` checks and `as` conversions to work as + ## expected. For example, Nim type may inherit from ``Spatial``, but the + ## script is attached to ``Particles``. In this case conversion to + ## ``Particles`` is valid, but Nim type system is not aware of that. + ## This works in both directions - for linked native object this + ## reference points to Nim object. + ## This is stored as a raw pointer to avoid reference cycles and therefore + ## improve GC performance. + isRef*: bool + isFinalized: bool + isNative: bool ConversionResult* {.pure.} = enum + ## Conversion result to return from ``fromVariant`` procedure. OK, TypeError, ## Type mismatch @@ -28,7 +59,7 @@ type SomeFloat = float32 or float64 or cfloat SomeGodot = bool or Vector2 or Rect2 or Vector3 or - Transform2D or Plane or Quat or Rect3 or + Transform2D or Plane or Quat or AABB or Basis or Transform or Color or NodePath or RID or GodotObject or Dictionary or Array or PoolByteArray or PoolIntArray or PoolRealArray or @@ -38,35 +69,134 @@ type SomeGodotOrNum = SomeGodot or SomeSignedInt or SomeUnsignedInt or SomeFloat CallError* = object of Exception + ## Raised by wrappers in case of an incorrect dynamic invocation. + ## For example, if incorrect number of arguments were passed or they had + ## unexpected types. err*: VariantCallError + ## The error as returned by Godot ObjectInfo = object constructor: proc(): NimGodotObject {.gcsafe, nimcall.} baseNativeClass: cstring isNative: bool + isRef: bool -var classRegistry {.threadvar.}: TableRef[cstring, ObjectInfo] + GodotTypeInfo* = object + ## Type information provided to Godot editor + variantType*: VariantType + hint*: GodotPropertyHint + hintStr*: string + ## Format depends on the type and the hint. + ## For example, for Enum ``hint`` this is a comma separated list of + ## values. + ## See documentation of ``GodotPropertyHint`` for description of formats. + FNV1Hash = uint32 + +include "internal/backwardcompat.inc.nim" + +proc isFinalized*(obj: NimGodotObject): bool {.inline.} = + obj.isFinalized + +var classRegistry {.threadvar.}: TableRef[FNV1Hash, ObjectInfo] +var classRegistryStatic* {.compileTime.}: TableRef[FNV1Hash, ObjectInfo] + ## Compile-time variable used for implementation of several procedures + ## and macros static: - import sets, strutils -var nativeClasses {.compileTime.} = initSet[string]() + classRegistryStatic = newTable[FNV1Hash, ObjectInfo]() -var getClassMethodBind {.threadvar.}: ptr GodotMethodBind -proc getClassName*(o: ptr GodotObject): string = - if getClassMethodBind.isNil: - getClassMethodBind = getMethod(cstring"Object", cstring"get_class") - var ret: GodotString - getClassMethodBind.ptrCall(o, nil, addr ret) - result = $ret - if result.endsWith("SW"): - # There are physics type not known by ClassDB - result = result[0..result.len-3] +var nativeClasses {.compileTime.} = newSeq[string]() +var refClasses* {.compileTime.} = newSeq[string]() -proc godotFinalizer[T: NimGodotObject](obj: T) = - # hmm, not sure yet how to deal with references correctly - # when T is Reference: - # obj.godotObject.deinit() - discard +template initFNV1Hash(hash: var FNV1Hash) = + hash = 0x811c9dc5'u32 + +template appendFNV1Hash(hash: var FNV1Hash, val: uint8) = + block: + let u64hash = hash.uint64 + hash = (( + u64hash + + (u64hash shl 1'u64) + + (u64hash shl 4'u64) + + (u64hash shl 7'u64) + + (u64hash shl 8'u64) + + (u64hash shl 24'u64)) and 0xFFFFFFFF'u32).uint32 xor val + +{.push stackTrace:off.} +proc lsb(c: ptr cwchar_t): char {.noinit, inline.} = + {.emit: [result, " = (char)(", c[]," & 0xFF);"]} +{.pop.} + +proc fnv1Hash(godotClassName: GodotString): FNV1Hash = + var charsCount = godotClassName.len + let charsPtr = godotClassName.dataPtr + if charsCount > 2 and + charsPtr.offset(charsCount - 2).lsb == 'S' and + charsPtr.offset(charsCount - 1).lsb == 'W': + charsCount -= 2 + + initFNV1Hash(result) + for i in 0..= charsCount: + break + let firstByte = uint8(rune.uint64 and 0xFF'u64) + appendFNV1Hash(result, firstByte) + # We don't really need to calculate hash of other bytes, + # since we only use hashes of ASCII strings + inc i + +proc getClassName*(o: NimGodotObject): string = + o.godotObject.getClassName() + +var unreferenceMethodBind {.threadvar.}: ptr GodotMethodBind +proc unreference(o: ptr GodotObject): bool = + if isNil(unreferenceMethodBind): + unreferenceMethodBind = getMethod(cstring"Reference", + cstring"unreference") + unreferenceMethodBind.ptrCall(o, nil, addr(result)) + +var referenceMethodBind {.threadvar.}: ptr GodotMethodBind +proc reference(o: ptr GodotObject): bool {.discardable.} = + if isNil(referenceMethodBind): + referenceMethodBind = getMethod(cstring"Reference", + cstring"reference") + referenceMethodBind.ptrCall(o, nil, addr result) + +var initRefMethodBind {.threadvar.}: ptr GodotMethodBind +proc initRef(o: ptr GodotObject): bool {.discardable.} = + if isNil(initRefMethodBind): + initRefMethodBind = getMethod(cstring"Reference", + cstring"init_ref") + initRefMethodBind.ptrCall(o, nil, addr result) + +proc deinit*(obj: NimGodotObject) = + ## Destroy the object. You only need to call this for objects not inherited + ## from Reference, where manual lifecycle control is necessary. + assert(not obj.godotObject.isNil) + obj.godotObject.deinit() + obj.godotObject = nil + +proc linkedObject(obj: NimGodotObject): NimGodotObject {.inline.} = + cast[NimGodotObject](obj.linkedObjectPtr) + +proc nimGodotObjectFinalizer*[T: NimGodotObject](obj: T) = + if obj.godotObject.isNil or obj.isNative: return + # important to set it before so that ``unreference`` is aware + obj.isFinalized = true + if (obj.isRef or not obj.linkedObject.isNil and obj.linkedObject.isRef) and + obj.godotObject.unreference(): + obj.deinit() macro baseNativeType(T: typedesc): cstring = var t = getType(getType(T)[1][1]) @@ -79,123 +209,231 @@ macro baseNativeType(T: typedesc): cstring = if typeName == "NimGodotObject": break t = getType(t[1][1]) - if baseT.isNil: + if baseT.len == 0: result = newNilLit() else: let rStr = newNimNode(nnkRStrLit) rStr.strVal = baseT result = newNimNode(nnkCallStrLit).add(ident("cstring"), rStr) -template registerClass*(T: typedesc; godotClassName: cstring, - isNativeParam: bool) = +proc inherits(t: NimNode, parent: string): bool {.compileTime.} = + var curT = t + while true: + let typeName = ($curT[1][1]).split(':')[0] + if typeName == parent: + return true + if typeName == "NimGodotObject": + break + curT = getType(curT[1][1]) + +macro isReference(T: typedesc): bool = + result = if inherits(getType(T), "Reference"): ident("true") + else: ident("false") + +macro isResource(T: typedesc): bool = + result = if inherits(getType(T), "Resource"): ident("true") + else: ident("false") + +template registerClass*(T: typedesc; godotClassName: string or cstring, + native: bool) = + ## Registers the specified Godot type. + ## Used by ``gdobj`` macro and `godotapigen `_. if classRegistry.isNil: - classRegistry = newTable[cstring, ObjectInfo]() + classRegistry = newTable[FNV1Hash, ObjectInfo]() let constructor = proc(): NimGodotObject = var t: T - new(t, godotFinalizer[T]) + new(t, nimGodotObjectFinalizer[T]) result = t const base = baseNativeType(T) - classRegistry[godotClassName] = ObjectInfo( + const isRef: bool = isReference(T) + let objInfo = ObjectInfo( constructor: constructor, baseNativeClass: base, - isNative: isNativeParam + isNative: native, + isRef: isRef ) - when isNativeParam: + classRegistry[fnv1Hash($godotClassName)] = objInfo + static: + let objInfoStatic = ObjectInfo( + baseNativeClass: base, + isNative: native, + isRef: isRef, + ) + let nameHash = fnv1Hash($godotClassName) + if not classRegistryStatic.contains(nameHash): + classRegistryStatic[nameHash] = objInfoStatic + elif not endsWith($godotClassName, "SW"): + # For simplicity we assume that all class names must have + # different hashes + # If this exception is ever raised, I guess, we should + # implement a proper collision resolving + raise newException(Exception, "Hash collision " & $godotClassName) + when isRef: static: - nativeClasses.incl(T.name) + refClasses.add(T.name) + when native: + static: + nativeClasses.add(T.name) proc newNimGodotObject[T: NimGodotObject]( - godotObject: ptr GodotObject, godotClassName: cstring): T = + godotObject: ptr GodotObject, godotClassName: GodotString, noRef: bool): T = assert(not classRegistry.isNil) assert(not godotObject.isNil) - let objInfo = classRegistry.getOrDefault(godotClassName) + let objInfo = classRegistry.getOrDefault(fnv1Hash(godotClassName)) if objInfo.constructor.isNil: printError("Nim constructor not found for class " & $godotClassName) else: result = T(objInfo.constructor()) result.godotObject = godotObject + result.isRef = objInfo.isRef + if not noRef and objInfo.isRef: + result.godotObject.reference() -proc asNimGodotObject*[T: NimGodotObject](godotObject: ptr GodotObject): T = +proc asNimGodotObject*[T: NimGodotObject]( + godotObject: ptr GodotObject, forceNativeObject, noRef: bool = false): T = + ## Wraps ``godotObject`` into Nim type ``T``. + ## This is used by `godotapigen `_ and should rarely be + ## used by anything else. if godotObject.isNil: return nil let userDataPtr = godotObject.getUserData() - if not userDataPtr.isNil: + if not userDataPtr.isNil and not forceNativeObject: result = cast[T](userDataPtr) if result.godotObject != godotObject: # Could be data from other bindings result = nil if result.isNil: + var classNameStr = godotObject.getClassNameRaw() result = newNimGodotObject[T]( - godotObject, cstring(godotObject.getClassName())) + godotObject, classNameStr, + forceNativeObject or noRef) + deinit(classNameStr) + +proc newVariant*(obj: NimGodotObject): Variant {.inline.} = + newVariant(obj.godotObject) + +proc asObject*[T: NimGodotObject](v: Variant): T {.inline.} = + ## Converts ``v`` to object of type ``T``. + ## Returns ``nil`` if the conversion cannot be performed + ## (``v``'s type is not an Object or it's an object of an incompatible type) + asNimGodotObject[T](v.asGodotObject()) + +proc asObject*(v: Variant, T: typedesc[NimGodotObject]): T {.inline.} = + ## Converts ``v`` to object of type ``T``. + ## Returns ``nil`` if the conversion cannot be performed + ## (``v``'s type is not an Object or it's an object of an incompatible type) + asNimGodotObject[T](v.asGodotObject()) proc `as`*[T: NimGodotObject](obj: NimGodotObject, t: typedesc[T]): T = ## Converts the ``obj`` into the specified type. ## Returns ``nil`` if the conversion cannot be performed ## (the ``obj`` is not of the type ``T``) - if obj.isNil or not (obj of T): - when not defined(release): - if not obj.isNil: - printError("Failed to cast object to " & - t.name & "\n" & getStackTrace()) - result = nil - else: + ## + ## This can be used either in dot notation (``node.as(Button)``) or + ## infix notation (``node as Button``). + if obj.isNil: return nil + if system.`of`(obj, T): result = T(obj) + elif not obj.linkedObject.isNil and system.`of`(obj.linkedObject, T): + result = T(obj.linkedObject) + else: + result = nil -proc getSingletonGodot*(name: cstring): ptr GodotObject {. - importc: "godot_global_get_singleton", header: "../godot.h".} +proc `of`*[T1, T2: NimGodotObject](obj: T1, t: typedesc[T2]): bool {.inline.} = + ## Godot-specific inheritance check. + not obj.isNil and (system.`of`(obj, T2) or system.`of`(obj.linkedObject, T2)) proc newRStrLit(s: string): NimNode {.compileTime.} = result = newNimNode(nnkRStrLit) result.strVal = s -static: - import strutils -macro toGodotName(T: typedesc): cstring = - let nameStr: string = (($T.getType()[1][1].symbol).split(':')[0]) - let godotName = case nameStr: - of "File", "Directory", "Thread", "Mutex", "Semaphore": - "_" & nameStr +macro toGodotName(T: typedesc): untyped = + if T is GodotString or T is string: + newStrLitNode"String" + elif T is SomeFloat: + newStrLitNode"float" + elif T is SomeUnsignedInt or T is SomeSignedInt: + newStrLitNode"int" else: - nameStr + let nameStr = ((T.getType()[1][1].strVal).split(':')[0]) + case nameStr: + of "File", "Directory", "Thread", "Mutex", "Semaphore": + newStrLitNode("_" & nameStr) + else: + newStrLitNode(nameStr) +macro asCString(s: static[string]): cstring = result = newNimNode(nnkCallStrLit).add( - ident("cstring"), newRStrLit(godotName)) + ident("cstring"), newRStrLit(s)) proc getSingleton*[T: NimGodotObject](): T = - const godotName = toGodotName(T) - let singleton = getSingletonGodot(godotName) + ## Returns singleton of type ``T``. Normally, this should not be used, + ## because `godotapigen `_ wraps singleton methods so that + ## singleton objects don't have to be provided as parameters. + const godotName = asCString(toGodotName(T)) + let singleton = getGodotSingleton(godotName) if singleton.isNil: printError("Tried to get non-existing singleton of type " & $godotName) else: result = asNimGodotObject[T](singleton) +var gdNativeLibraryObj: ptr GodotObject + +var setClassNameMethod: ptr GodotMethodBind +var setLibraryMethod: ptr GodotMethodBind +var newMethod: ptr GodotMethodBind +type + PtrCallArgType = ptr array[MAX_ARG_COUNT, pointer] +proc newOwnObj[T: NimGodotObject](name: cstring): T = + let newNativeScript = getClassConstructor(cstring"NativeScript")() + if setClassNameMethod.isNil: + setClassNameMethod = + getMethod(cstring"NativeScript", cstring"set_class_name") + if setLibraryMethod.isNil: + setLibraryMethod = + getMethod(cstring"NativeScript", cstring"set_library") + if newMethod.isNil: + newMethod = getMethod(cstring"NativeScript", cstring"new") + var godotStrName = name.toGodotString() + var argPtr: pointer = addr godotStrName + setClassNameMethod.ptrCall( + newNativeScript, cast[PtrCallArgType](addr argPtr), nil) + deinit(godotStrName) + setLibraryMethod.ptrCall( + newNativeScript, cast[PtrCallArgType](addr gdNativeLibraryObj), nil) + + var err: VariantCallError + var ret = newMethod.call(newNativeScript, nil, 0, err) + if err.error != VariantCallErrorType.OK: + printError("Failed to invoke 'new' on NativeScript for " & $name) + elif ret.getType() != VariantType.Object: + printError("Expected that NativeScript::new returns Object, " & + "but it returned: " & $ret.getType()) + else: + result = asNimGodotObject[T](ret.asGodotObject()) + if result.isRef: + result.isFinalized = true + result.godotObject.reference() + result.isFinalized = false + ret.deinit() + proc gdnew*[T: NimGodotObject](): T = + ## Instantiates new object of type ``T``. const godotName = toGodotName(T) - let obj = godotNew(godotName) - if obj.isNil: - printError("godot_new returned nil for type " & $godotName) - result = asNimGodotObject[T](obj) - # const godotName = toGodotName(T) - # let objInfo = classRegistry.getOrDefault(godotName) - # if objInfo.constructor.isNil: - # printError("gdnew invoked on unregistered class: " & $godotName) - # return - # let godotConstructor = getClassConstructor( - # if objInfo.isNative: godotName else: objInfo.baseNativeClass) - # printError("Base native class for " & T.name & ": " & $objInfo.baseNativeClass) - # when not defined(release): - # if godotConstructor.isNil: - # printError("Failed to obtain Godot constrcutor for type: " & $godotName) - # return - # let godotObject = godotConstructor() - # when not defined(release): - # if godotObject.isNil: - # printError("Godot constructor returned nil - must never happen") - # return - # new(result, godotFinalizer[T]) - # result.setGodotObject(godotObject) + const cGodotName = asCString(godotName) + const objInfo = classRegistryStatic[fnv1Hash(godotName)] + when objInfo.isNative: + let godotObject = getClassConstructor(cGodotName)() + new(result, nimGodotObjectFinalizer[T]) + result.godotObject = godotObject + when objInfo.isRef: + godotObject.initRef() + result.isRef = true + else: + result = newOwnObj[T](cGodotName) proc newCallError*(err: VariantCallError): ref CallError = + ## Instantiates ``CallError`` from Godot ``err``. let msg = case err.error: of VariantCallErrorType.OK, VariantCallErrorType.InvalidMethod, @@ -211,6 +449,8 @@ proc newCallError*(err: VariantCallError): ref CallError = result.err = err proc newConversionError*(err: ConversionResult): ref ValueError = + ## Instantiates error raised by `godotapigen `_ + ## generated code in case of a conversion error. let msg = case err: of ConversionResult.TypeError: "Failed to convert the return value into Nim type" @@ -221,28 +461,56 @@ proc newConversionError*(err: ConversionResult): ref ValueError = result = newException(ValueError, msg) -proc removeGodotObject*(nimObj: NimGodotObject) = - ## Used from destructor - nimObj.godotObject = nil - proc setGodotObject*(nimObj: NimGodotObject, obj: ptr GodotObject) {.inline.} = + ## Used from Godot constructor produced by ``gdobj`` macro. Do not call. assert(not obj.isNil) assert(nimObj.godotObject.isNil) # reassignment is not allowed nimObj.godotObject = obj +proc setNativeObject*(nimObj: NimGodotObject, + nativeObj: NimGodotObject) {.inline.} = + ## Used from Godot constructor produced by ``gdobj`` macro. Do not call. + GC_ref(nativeObj) + nimObj.linkedObjectPtr = cast[pointer](nativeObj) + nativeObj.linkedObjectPtr = cast[pointer](nimObj) + nativeObj.isNative = true + +proc removeGodotObject*(nimObj: NimGodotObject) {.inline.} = + ## Used from Godot destructor produced by ``gdobj`` macro. Do not call. + GC_unref(nimObj.linkedObject) + nimObj.godotObject = nil + nimObj.linkedObject.godotObject = nil + nimObj.linkedObjectPtr = nil + +proc `==`*(self, other: NimGodotObject): bool {.inline.} = + ## Compares objects by referential equality. + if self.isNil and other.isNil: return true + if self.isNil != other.isNil: return false + result = (self.godotObject == other.godotObject) + proc godotObject*(nimObj: NimGodotObject): ptr GodotObject {.inline.} = + ## Returns raw poitner to ``GodotObject``. Use only if you know what + ## you are doing. nimObj.godotObject -proc godotVariantType*(T: typedesc[NimGodotObject]): VariantType {.inline.} = - VariantType.Object +proc godotTypeInfo*(T: typedesc[NimGodotObject]): GodotTypeInfo {.inline.} = + GodotTypeInfo( + variantType: VariantType.Object, + hint: when isResource(T): GodotPropertyHint.ResourceType + else: GodotPropertyHint.None, + hintStr: toGodotName(T) + ) -proc toGodot*(self: NimGodotObject): Variant {.inline.} = - variant(self.godotObject) +proc toVariant*(self: NimGodotObject): Variant {.inline.} = + if self.isNil: + newVariant() + else: + newVariant(self.godotObject) -proc fromGodot*[T: NimGodotObject](self: var T, - val: Variant): ConversionResult = +proc fromVariant*[T: NimGodotObject](self: var T, + val: Variant): ConversionResult = if val.getType() == VariantType.Object: - let objPtr = val.asObject() + let objPtr = val.asGodotObject() self = asNimGodotObject[T](objPtr) if self.isNil: result = ConversionResult.TypeError @@ -251,107 +519,144 @@ proc fromGodot*[T: NimGodotObject](self: var T, else: result = ConversionResult.TypeError -proc godotVariantType*(T: typedesc[enum]): VariantType {.inline.} = - VariantType.Int - -proc toGodot*[T: enum](self: T): Variant {.inline.} = - variant(ord(self)) - -proc fromGodot*[T: enum](self: var T, val: Variant): ConversionResult = - if val.getType() == VariantType.Int: - self = T(val.asInt()) +proc toVariant*(self: Variant): Variant {.inline.} = + if self.isNil: + newVariant() else: - result = ConversionResult.TypeError + newVariant(self) -proc toGodot*(self: Variant): Variant {.inline.} = - result = self +proc fromVariant*(self: var Variant, + val: Variant): ConversionResult {.inline.} = + self = newVariant(val) -proc fromGodot*(self: var Variant, val: Variant): ConversionResult {.inline.} = - self = val +proc godotTypeInfo*(T: typedesc[SomeGodotOrNum]): GodotTypeInfo {.inline.} = + result.variantType = + when T is SomeSignedInt or T is SomeUnsignedInt: + VariantType.Int + elif T is bool: + VariantType.Bool + elif T is SomeFloat: + VariantType.Real + elif T is string or T is GodotString: + VariantType.String + elif T is Vector2: + VariantType.Vector2 + elif T is Rect2: + VariantType.Rect2 + elif T is Vector3: + VariantType.Vector3 + elif T is Transform2D: + VariantType.Transform2D + elif T is Plane: + VariantType.Plane + elif T is Quat: + VariantType.Quat + elif T is AABB: + VariantType.AABB + elif T is Basis: + VariantType.Basis + elif T is Transform: + VariantType.Transform + elif T is Color: + VariantType.Color + elif T is RID: + VariantType.RID + elif T is ptr GodotObject: + VariantType.Object + elif T is NodePath: + VariantType.NodePath + elif T is Dictionary: + VariantType.Dictionary + elif T is Array: + VariantType.Array + elif T is PoolByteArray: + VariantType.PoolByteArray + elif T is PoolIntArray: + VariantType.PoolIntArray + elif T is PoolRealArray: + VariantType.PoolRealArray + elif T is PoolStringArray: + VariantType.PoolStringArray + elif T is PoolVector2Array: + VariantType.PoolVector2Array + elif T is PoolVector3Array: + VariantType.PoolVector3Array + elif T is PoolColorArray: + VariantType.PoolColorArray + else: + VariantType.Nil -proc godotVariantType*(T: typedesc[SomeGodotOrNum]): VariantType {.inline.} = - when T is SomeSignedInt or T is SomeUnsignedInt: - VariantType.Int - elif T is bool: - VariantType.Bool - elif T is SomeFloat: - VariantType.Real - elif T is string or T is GodotString: - VariantType.String - elif T is Vector2: - VariantType.Vector2 - elif T is Rect2: - VariantType.Rect2 - elif T is Vector3: - VariantType.Vector3 - elif T is Transform2D: - VariantType.Transform2D - elif T is Plane: - VariantType.Plane - elif T is Quat: - VariantType.Quat - elif T is Rect3: - VariantType.Rect3 - elif T is Basis: - VariantType.Basis - elif T is Transform: - VariantType.Transform - elif T is Color: - VariantType.Color - elif T is NodePath: - VariantType.NodePath - elif T is RID: - VariantType.RID - elif T is GodotObject: - VariantType.Object - elif T is Dictionary: - VariantType.Dictionary - elif T is Array: - VariantType.Array - elif T is PoolByteArray: - VariantType.PoolByteArray - elif T is PoolIntArray: - VariantType.PoolIntArray - elif T is PoolRealArray: - VariantType.PoolRealArray - elif T is PoolStringArray: - VariantType.PoolStringArray - elif T is PoolVector2Array: - VariantType.PoolVector2Array - elif T is PoolVector3Array: - VariantType.PoolVector3Array - elif T is PoolColorArray: - VariantType.PoolColorArray +proc godotTypeInfo*(T: typedesc[range]): VariantType {.inline.} = + GodotTypeInfo( + variantType: VariantType.Int, + hint: GodotPropertyHint.Range, + hintStr: $low(T) & "," & $high(T) & ",1" + ) + +proc toVariant*[T: SomeGodotOrNum](val: T): Variant {.inline.} = + when val is ref: + if val.isNil: + newVariant() + else: + newVariant(val) else: - VariantType.Nil + newVariant(val) -proc toGodot*[T: SomeGodotOrNum](val: T): Variant {.inline.} = - result = variant(val) - -proc fromGodot*[T: SomeSignedInt or SomeUnsignedInt]( +proc fromVariant*[T: SomeSignedInt or SomeUnsignedInt]( self: var T, val: Variant): ConversionResult = - if val.getType() != VariantType.Int: - result = ConversionResult.TypeError - else: + if val.getType() == VariantType.Nil: + self = 0 + elif val.getType() == VariantType.Int or val.getType() == VariantType.Real: + # Real is allowed, because that's what the editor sets for Int values var intVal: (when T is SomeSignedInt: int64 else: uint64) intVal = when T is SomeSignedInt: val.asInt() else: val.asUint() - if intVal > high(T) or intVal < low(T): + const highT = when T is SomeSignedInt: high(T).int64 + else: high(T).uint64 + const lowT = when T is SomeSignedInt: low(T).int64 + else: low(T).uint64 + if intVal > highT or intVal < lowT: result = ConversionResult.RangeError else: self = T(intVal) - -proc fromGodot*[T: SomeFloat](self: var T, val: Variant): ConversionResult = - if val.getType() == VariantType.Real: - self = val.asReal() - elif val.getType() == VariantType.Int: - self = T(val.asInt()) else: result = ConversionResult.TypeError -proc fromGodot*[T: SomeGodot](self: var T, val: Variant): ConversionResult = - if godotVariantType(T) != val.getType(): +proc godotTypeInfo*(T: typedesc[enum]): GodotTypeInfo = + result = GodotTypeInfo( + variantType: VariantType.Int, + hint: GodotPropertyHint.Enum, + hintStr: "" + ) + for val in T: + if result.hintStr.len > 0: + result.hintStr.add(',') + result.hintStr.add($val) + +proc toVariant*[T: enum](self: T): Variant {.inline.} = + newVariant(int64(ord(self))) + +proc fromVariant*[T: enum](self: var T, + val: Variant): ConversionResult {.inline.} = + var intConv: int64 + result = fromVariant(intConv, val) + if result == ConversionResult.OK: + self = T(intConv) + +proc fromVariant*[T: SomeFloat](self: var T, val: Variant): ConversionResult = + if val.getType() == VariantType.Nil: + self = 0 + elif val.getType() == VariantType.Real or val.getType() == VariantType.Int: + self = T(val.asReal()) + else: + result = ConversionResult.TypeError + +proc fromVariant*[T: SomeGodot](self: var T, val: Variant): ConversionResult = + if val.getType() == VariantType.Nil: + return + const typeInfo = godotTypeInfo(T) + if typeInfo.variantType != val.getType(): return ConversionResult.TypeError when self is bool: self = val.asBool() @@ -367,8 +672,8 @@ proc fromGodot*[T: SomeGodot](self: var T, val: Variant): ConversionResult = self = val.asPlane() elif self is Quat: self = val.asQuat() - elif self is Rect3: - self = val.asRect3() + elif self is AABB: + self = val.asAABB() elif self is Basis: self = val.asBasis() elif self is Transform: @@ -405,122 +710,248 @@ proc fromGodot*[T: SomeGodot](self: var T, val: Variant): ConversionResult = # mustn't reach this result = ConversionError.TypeError -proc godotVariantType*(T: typedesc[string]): VariantType {.inline.} = - VariantType.String +proc godotTypeInfo*(T: typedesc[string]): GodotTypeInfo {.inline.} = + result.variantType = VariantType.String -proc toGodot*(s: string): Variant {.inline.} = - variant(s.toGodotString()) +proc toVariant*(s: string): Variant {.inline.} = + newVariant(s) -proc fromGodot*(s: var string, val: Variant): ConversionResult = - if val.getType() != VariantType.String: - result = ConversionResult.TypeError +proc fromVariant*(s: var string, val: Variant): ConversionResult = + if val.getType() == VariantType.String: + s = val.asString() + elif val.getType() == VariantType.Nil: + when (NimMajor, NimMinor, NimPatch) < (0, 19, 0): + s = nil + else: + s = "" else: - s = $val.asGodotString() + result = ConversionResult.TypeError -proc godotVariantType*(T: typedesc[seq]): VariantType = - VariantType.Array +template arrTypeInfo(T) = + result.variantType = VariantType.Array + mixin godotTypeInfo + type ItemT = type(( + block: + var s: T; + when T is seq: s[0] else: s[low(s)])) + when compiles(godotTypeInfo(ItemT)): + let itemTypeInfo = godotTypeInfo(ItemT) + result.hintStr = $ord(itemTypeInfo.variantType) + result.hintStr.add('/') + result.hintStr.add($ord(itemTypeInfo.hint)) + result.hintStr.add(':') + if not itemTypeInfo.hintStr.isNil: + result.hintStr.add(itemTypeInfo.hintStr) -proc godotVariantType*(T: typedesc[array]): VariantType = - VariantType.Array +proc godotTypeInfo*(T: typedesc[seq]): GodotTypeInfo = + arrTypeInfo(T) -proc toGodot*[T](s: openarray[T]): Variant = - var arr: Array - initArray(arr) - mixin toGodot +proc godotTypeInfo*(T: typedesc[array]): GodotTypeInfo = + arrTypeInfo(T) + +template arrayToVariant(s: untyped): Variant = + var arr = newArray() + mixin toVariant for item in s: - arr.add(toGodot(item)) - result = variant(arr) + arr.add(toVariant(item)) + newVariant(arr) -proc fromGodot*[T](s: var seq[T], val: Variant): ConversionResult = - if val.getType() != VariantType.Array: - result = ConversionResult.TypeError - else: +proc toVariant*[T](s: seq[T]): Variant = + if s.isNil: + return newVariant() + result = arrayToVariant(s) + +proc toVariant*[I, T](s: array[I, T]): Variant = + result = arrayToVariant(s) + +proc fromVariant*[T](s: var seq[T], val: Variant): ConversionResult = + if val.getType() == VariantType.Nil: + s = nil + elif val.getType() == VariantType.Array: let arr = val.asArray() - s = newSeq[T](arr.len) + var newS = newSeq[T](arr.len) for idx, item in arr: - mixin fromGodot - let convResult = fromGodot(s[idx], item) + mixin fromVariant + let convResult = fromVariant(newS[idx], item) if convResult != ConversionResult.OK: - s = nil return convResult - -proc fromGodot*[T: array](s: var T, val: Variant): ConversionResult = - if val.getType() != VariantType.Array: - result = ConversionResult.TypeError + shallowCopy(s, newS) else: + result = ConversionResult.TypeError + +proc fromVariant*[T: array](s: var T, val: Variant): ConversionResult = + if val.getType() == VariantType.Nil: + discard + elif val.getType() == VariantType.Array: let arr = val.asArray() if s.len != arr.len: return ConversionResult.TypeError - for idx, item in arr: - mixin fromGodot - let convResult = fromGodot(s[idx], item) + var nimIdx = low(s) # may not start from 0 and may even be an enum + for item in arr: + mixin fromVariant + let convResult = fromVariant(s[nimIdx], item) if convResult != ConversionResult.OK: return convResult - -proc godotVariantType*(T: typedesc[Table|TableRef]): VariantType {.inline.} = - VariantType.Dictionary - -proc toGodot*[T: Table or TableRef](t: T): Variant = - var dict: Dictionary - initDictionary(dict) - mixin toGodot - for k, v in t.pairs(): - dict[toGodot(k)] = toGodot(v) - result = variant(dict) - -proc fromGodot*[T: Table or TableRef](t: var T, val: Variant): ConversionResult = - if val.getType() != VariantType.Dictionary: - result = ConversionResult.TypeError + if nimIdx != high(s): + inc nimIdx else: + result = ConversionResult.TypeError + +proc godotTypeInfo*[T](OptT: typedesc[Option[T]]): GodotTypeInfo = + when compiles(godotTypeInfo(T)): + result.variantType = godotTypeInfo(T) + else: + result.variantType = VariantType.Nil + +proc toVariant*[T](option: Option[T]): Variant = + if option.isSome(): + result = toVariant(option.unsafeGet()) + else: + result = newVariant() + +proc fromVariant*[T](option: var Option[T], val: Variant): ConversionResult = + if val.getType() == VariantType.Nil: + option = none(T) + else: + var v: T + result = fromVariant(v, val) + if result == ConversionResult.OK: + option = some(result) + +proc godotTypeInfo*(T: typedesc[Table|TableRef|OrderedTable|OrderedTableRef]): GodotTypeInfo {.inline.} = + result.variantType = VariantType.Dictionary + +proc toVariant*[T: Table or TableRef or OrderedTable or OrderedTableRef](t: T): Variant = + when t is ref: + if t.isNil: + return newVariant() + var dict = newDictionary() + mixin toVariant + for k, v in t.pairs(): + dict[toVariant(k)] = toVariant(v) + result = newVariant(dict) + +proc fromVariant*[T: Table or TableRef or OrderedTable or OrderedTableRef](t: var T, + val: Variant): ConversionResult = + if val.getType() == VariantType.Nil: + when t is ref: + t = nil + elif val.getType() == VariantType.Dictionary: let dict = val.asDictionary() - mixin fromGodot + mixin fromVariant when t is Table: t = initTable[type(t.keys()), type(t.values())]() - else: + elif t is TableRef: t = newTable[type(t.keys()), type(t.values())]() + elif t is OrderedTable: + t = initOrderedTable[type(t.keys()), type(t.values())]() + else: + t = newOrderedTable[type(t.keys()), type(t.values())]() for k, v in dict: var nimKey: type(t.keys()) var nimVal: type(t.values()) - let keyResult = fromGodot(nimKey, k) + let keyResult = fromVariant(nimKey, k) if keyResult != ConversionResult.OK: when t is ref: t = nil return keyResult - let valResult = fromGodot(nimVal, v) + let valResult = fromVariant(nimVal, v) if valResult != ConversionResult.OK: when t is ref: t = nil return valResult t[nimKey] = nimVal - -proc godotToNim*[T](val: Variant): (T, ConversionResult) = - mixin fromGodot - result[1] = fromGodot(result[0], val) - -proc nimToGodot*[T](val: T): Variant = - mixin toGodot - when compiles(toGodot(val)): - result = toGodot(val) else: - printError("Failed to convert Nim value of type " & T.name & - " into Variant") - initNilVariant(result) + result = ConversionResult.TypeError -{.emit: """/*TYPESECTION*/ -void NimMain(void); -N_NOINLINE(void, setStackBottom)(void* thestackbottom); -""".} +when (NimMajor, NimMinor, NimPatch) < (0, 19, 0): + {.emit: """/*TYPESECTION*/ + N_LIB_EXPORT N_CDECL(void, NimMain)(void); + N_NOINLINE(void, setStackBottom)(void* thestackbottom); + """.} -const stackIncreases = defined(emscripten) +var nativeLibHandle: pointer +proc getNativeLibHandle*(): pointer = + ## Returns NativeScript library handle used to register type information + ## in Godot. + return nativeLibHandle -proc godot_native_init() {.cdecl, exportc, dynlib.} = - let stackBottom = godotStackBottom() +proc godot_nativescript_init(handle: pointer) {. + cdecl, exportc, dynlib.} = + nativeLibHandle = handle + + var stackBottom {.volatile.}: pointer + stackBottom = addr(stackBottom) {.emit: """ NimMain(); - setStackBottom(`stackBottom`); """.} + when (NimMajor, NimMinor, NimPatch) < (0, 19, 0): + {.emit: """ + setStackBottom((void*)(&`stackBottom`)); + """.} + else: + nimGC_setStackBottom(stackBottom) GC_fullCollect() GC_disable() -proc godot_native_terminate() {.cdecl, exportc, dynlib.} = - discard +proc godot_gdnative_init(options: ptr GDNativeInitOptions) {. + cdecl, exportc, dynlib.} = + gdNativeLibraryObj = options.gdNativeLibrary + setGDNativeAPI(options.gdNativeAPIStruct, options) + +proc godot_gdnative_terminate(options: ptr GDNativeTerminateOptions) {. + cdecl, exportc, dynlib.} = + if not options[].inEditor or not compileOption("threads"): + deallocHeap(runFinalizers = not options[].inEditor, allowGcAfterwards = false) + +const nimGcStepLengthUs {.intdefine.} = 2000 + +var idleCallbacks {.threadvar.}: seq[proc () {.closure.}] +idleCallbacks = newSeq[proc () {.closure.}]() + +var isMainThread {.threadvar.}: bool +isMainThread = true + +proc registerFrameCallback*(cb: proc () {.closure.}) = + # Registers a callback to be called on the main thread at the end + # of each frame. + if not isMainThread: + const err = cstring"registerFrameIdleCallback is called from non-main thread. Ignoring." + godotPrintError(err, cstring"registerFrameCallback", + cstring"godotnim.nim", 0) + else: + idleCallbacks.add(cb) + +{.push stackTrace: off.} + +proc godot_nativescript_frame() {.cdecl, exportc, dynlib.} = + var stackBottom {.volatile.}: pointer + stackBottom = addr(stackBottom) + when (NimMajor, NimMinor, NimPatch) < (0, 19, 0): + {.emit: """ + setStackBottom((void*)(&`stackBottom`)); + """.} + else: + nimGC_setStackBottom(stackBottom) + for cb in idleCallbacks: + cb() + GC_step(nimGcStepLengthUs, true, 0) + +when not defined(release): + onUnhandledException = proc(errorMsg: string) = + printError("Unhandled Nim exception: " & errorMsg) + +proc godot_nativescript_thread_enter() {.cdecl, exportc, dynlib.} = + when compileOption("threads"): + setupForeignThreadGc() + else: + const err = cstring"A foreign thread is created, but app is compiled without --threads:on. Bad things will happen if Nim code is invoked from this thread. If you see this warning when running the editor and you don't actually use threads, ignore it." + var s = err.toGodotString() + godotPrint(s) + s.deinit() + +proc godot_nativescript_thread_exit() {.cdecl, exportc, dynlib.} = + when compileOption("threads"): + teardownForeignThreadGc() + +{.pop.} # stackTrace: off diff --git a/godot/nim/nim.cfg b/godot/nim/nim.cfg new file mode 100644 index 0000000..add9a4d --- /dev/null +++ b/godot/nim/nim.cfg @@ -0,0 +1,2 @@ +--path:"$projectdir/../" +-d:useRealtimeGc \ No newline at end of file diff --git a/godot/nimdoc.cfg b/godot/nimdoc.cfg new file mode 100644 index 0000000..d4e8565 --- /dev/null +++ b/godot/nimdoc.cfg @@ -0,0 +1,5 @@ +doc.item.seesrc = """  Source +Edit +""" \ No newline at end of file diff --git a/godot/nimruntime.nim b/godot/nimruntime.nim deleted file mode 100644 index 0a55844..0000000 --- a/godot/nimruntime.nim +++ /dev/null @@ -1,14 +0,0 @@ -# Copyright 2017 Xored Software, Inc. - -import asyncdispatch -import godot, node - -gdobj NimRuntime of Node: - method process*(delta: float32) = - if asyncdispatch.hasPendingOperations(): - poll(0) - GC_step(2000, false, 0) - -when not defined(release): - onUnhandledException = proc(errorMsg: string) = - printError("Unhandled Nim exception: " & errorMsg)