├── docs
├── nim.cfg
├── godotapi.rst
├── docpublish.nim
├── docbuild.nim
└── index.rst
├── godot
├── core
│ ├── nim.cfg
│ ├── rids.nim
│ ├── godotbase.nim
│ ├── nodepaths.nim
│ ├── planes.nim
│ ├── quats.nim
│ ├── colors.nim
│ ├── aabb.nim
│ ├── godotcoretypes.nim
│ ├── transforms.nim
│ ├── transform2d.nim
│ ├── dictionaries.nim
│ ├── arrays.nim
│ ├── rect2.nim
│ ├── poolarrays.nim
│ ├── vector2.nim
│ ├── vector3.nim
│ ├── variants.nim
│ └── basis.nim
├── internal
│ ├── nim.cfg
│ ├── backwardcompat.inc.nim
│ ├── godotnodepaths.nim
│ ├── godotstrings.nim
│ ├── godotdictionaries.nim
│ ├── godotarrays.nim
│ ├── godotvariants.nim
│ ├── godotpoolarrays.nim
│ └── godotinternaltypes.nim
├── godot.nim.cfg
├── nim
│ ├── nim.cfg
│ ├── godotmacros.nim
│ └── godotnim.nim
├── nimdoc.cfg
├── godot.nim
└── godotinternal.nim
├── godot.nimble
├── .gitignore
├── .vscode
└── settings.json
├── README.md
├── LICENSE
└── .travis.yml
/docs/nim.cfg:
--------------------------------------------------------------------------------
1 | --threads:on
--------------------------------------------------------------------------------
/godot/core/nim.cfg:
--------------------------------------------------------------------------------
1 | --path:"$projectdir/../"
--------------------------------------------------------------------------------
/godot/internal/nim.cfg:
--------------------------------------------------------------------------------
1 | --path:"$projectdir/../"
--------------------------------------------------------------------------------
/godot/godot.nim.cfg:
--------------------------------------------------------------------------------
1 | --path:"$projectdir"
2 | -d:useRealtimeGc
--------------------------------------------------------------------------------
/godot/nim/nim.cfg:
--------------------------------------------------------------------------------
1 | --path:"$projectdir/../"
2 | -d:useRealtimeGc
--------------------------------------------------------------------------------
/godot.nimble:
--------------------------------------------------------------------------------
1 | version = "0.8.5"
2 | author = "Xored Software, Inc."
3 | description = "Godot Engine bindings"
4 | license = "MIT"
5 | srcDir = "godot"
6 |
7 | requires "nim >= 0.17.3", "compiler >= 0.17.3"
8 |
--------------------------------------------------------------------------------
/godot/nimdoc.cfg:
--------------------------------------------------------------------------------
1 | doc.item.seesrc = """ Source
4 | Edit
5 | """
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | nimcache/
2 |
3 | /godot/apigen/apigen
4 | /godot/apigen/apigen.exe
5 | /godot/godotapigen
6 | /godot/godotapigen.exe
7 |
8 | /docgen
9 | /docs/docbuild
10 | /docs/docbuild.exe
11 | /docs/docpublish
12 | /docs/docpublish.exe
13 |
14 | .DS_Store
--------------------------------------------------------------------------------
/docs/godotapi.rst:
--------------------------------------------------------------------------------
1 | ===============
2 | Godot API (Nim)
3 | ===============
4 |
5 | :Godot Git Hash: |godothash|
6 |
7 | .. contents::
8 |
9 | This is an auto-generated index of Godot API. It's built from Git changeset
10 | $GODOTAPI_CHANGESET_HASH.
11 |
12 | $AUTO_GENERATED_GODOTAPI_LIST
--------------------------------------------------------------------------------
/.vscode/settings.json:
--------------------------------------------------------------------------------
1 | {
2 | "editor.tabSize": 2,
3 | "editor.rulers": [80],
4 | "editor.insertSpaces": true,
5 | "editor.detectIndentation": false,
6 | "files.eol": "\n",
7 | "files.trimTrailingWhitespace": true,
8 | "nim.project": ["godot/godot.nim",
9 | "godot/godotapigen.nim"],
10 | "nim.buildOnSave": false,
11 | "nim.lintOnSave": true,
12 | "nim.licenseString": "# Copyright 2018 Xored Software, Inc.\n\n",
13 | "files.exclude": {
14 | "**/nimcache/**": true
15 | }
16 | }
--------------------------------------------------------------------------------
/godot/internal/backwardcompat.inc.nim:
--------------------------------------------------------------------------------
1 | # Copyright 2019 Xored Software, Inc.
2 |
3 | when (NimMajor, NimMinor, NimPatch) < (0, 19, 0):
4 | import macros, sets
5 |
6 | proc strVal(n: NimNode): string {.used.} =
7 | case n.kind
8 | of nnkIdent:
9 | $n.ident
10 | of nnkSym:
11 | $n.symbol
12 | else:
13 | macros.strVal(n)
14 |
15 | proc toHashSet[A](keys: openArray[A]): HashSet[A] {.inline, used.} =
16 | toSet(keys)
17 |
18 | proc initHashSet[A](): HashSet[A] {.inline, used.} =
19 | initSet[A]()
20 |
--------------------------------------------------------------------------------
/godot/godot.nim:
--------------------------------------------------------------------------------
1 | # Copyright 2018 Xored Software, Inc.
2 |
3 | import core/godotbase, godotinternal
4 | import core/godotcoretypes
5 | import core/vector2, core/rect2, core/vector3, core/transform2d, core/planes,
6 | core/quats
7 | import core/aabb, core/basis, core/transforms, core/colors, core/nodepaths,
8 | core/rids
9 | import core/dictionaries, core/arrays, core/poolarrays, core/variants
10 |
11 | import nim/godotmacros, nim/godotnim
12 |
13 | export godotbase, godotcoretypes, vector2, rect2, vector3, transform2d, planes,
14 | quats, aabb, basis, transforms, colors, nodepaths, rids, dictionaries,
15 | arrays, poolarrays, variants
16 | export godotmacros, godotnim
17 |
18 | export GodotPropertyHint, GodotPropertyUsage
--------------------------------------------------------------------------------
/godot/core/rids.nim:
--------------------------------------------------------------------------------
1 | # Copyright (c) 2018 Xored Software, Inc.
2 |
3 | import hashes
4 |
5 | import godotcoretypes, internal/godotinternaltypes, gdnativeapi
6 |
7 | proc initRID*(): RID {.inline.} =
8 | getGDNativeAPI().ridNew(result)
9 |
10 | proc initRID*(obj: ptr GodotObject): RID {.inline.} =
11 | getGDNativeAPI().ridNewWithResource(result, obj)
12 |
13 | proc id*(self: RID): uint32 {.inline.} =
14 | cast[uint32](getGDNativeAPI().ridGetId(self))
15 |
16 | proc `$`*(self: RID): string {.inline.} =
17 | $self.id
18 |
19 | proc hash*(self: RID): Hash {.inline.} =
20 | self.id.hash()
21 |
22 | proc `==`*(a, b: RID): bool {.inline.} =
23 | getGDNativeAPI().ridOperatorEqual(a, b)
24 |
25 | proc `<`*(a, b: RID): bool {.inline.} =
26 | getGDNativeAPI().ridOperatorLess(a, b)
27 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Nim bindings for Godot Engine
2 |
3 | Nim bindings for Godot 3 based on [GDNative](https://godotengine.org/article/dlscript-here).
4 |
5 | Documentation: https://pragmagic.github.io/godot-nim/
6 |
7 | ## Made with godot-nim
8 |
9 | The library is production-ready and has been used to create these games:
10 |
11 | - [Frayhem](https://frayhem.com/) - mobile online 3v3 brawler
12 | - [Summon Age](https://summonage.com/) - mobile hero collection RPG
13 | - [Turing Complete](https://turingcomplete.game/) - computer science game
14 |
15 | ## Links
16 |
17 | - [Godot Engine](https://www.godotengine.org/)
18 | - [Nim](https://nim-lang.org/)
19 |
20 | ## License
21 |
22 | This project is licensed under the MIT license. Read [LICENSE](LICENSE) file for details.
23 |
24 | Copyright (c) 2018-2021 Gearage LLC.
25 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | godot-nim - Nim bindings for Godot Engine
2 |
3 | The MIT License
4 |
5 | Copyright (c) 2018 Xored Software Inc.
6 |
7 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
8 | associated documentation files (the "Software"), to deal in the Software without restriction,
9 | including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense,
10 | and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so,
11 | subject to the following conditions:
12 |
13 | The above copyright notice and this permission notice shall be included in all copies or substantial
14 | portions of the Software.
15 |
16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
17 | NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
18 | IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
19 | WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH
20 | THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21 |
--------------------------------------------------------------------------------
/godot/internal/godotnodepaths.nim:
--------------------------------------------------------------------------------
1 | # Copyright 2018 Xored Software, Inc.
2 |
3 | import godotinternaltypes, gdnativeapi
4 |
5 | proc initGodotNodePath*(dest: var GodotNodePath; s: GodotString) {.inline.} =
6 | getGDNativeAPI().nodePathNew(dest, s)
7 |
8 | proc initGodotNodePath*(dest: var GodotNodePath;
9 | src: GodotNodePath) {.inline.} =
10 | getGDNativeAPI().nodePathNewCopy(dest, src)
11 |
12 | proc deinit*(self: var GodotNodePath) {.inline.} =
13 | getGDNativeAPI().nodePathDestroy(self)
14 |
15 | proc toGodotString*(self: GodotNodePath): GodotString {.inline.} =
16 | getGDNativeAPI().nodePathAsString(self)
17 |
18 | proc isAbsolute*(self: GodotNodePath): bool {.inline.} =
19 | getGDNativeAPI().nodePathIsAbsolute(self)
20 |
21 | proc nameCount*(self: GodotNodePath): cint {.inline.} =
22 | getGDNativeAPI().nodePathGetNameCount(self)
23 |
24 | proc getName*(self: GodotNodePath; idx: cint): GodotString {.inline.} =
25 | getGDNativeAPI().nodePathGetName(self, idx)
26 |
27 | proc subnameCount*(self: GodotNodePath): cint {.inline.} =
28 | getGDNativeAPI().nodePathGetSubnameCount(self)
29 |
30 | proc getSubname*(self: GodotNodePath; idx: cint): GodotString {.inline.} =
31 | getGDNativeAPI().nodePathGetSubname(self, idx)
32 |
33 | proc getConcatenatedSubnames*(self: GodotNodePath): GodotString {.inline.} =
34 | getGDNativeAPI().nodePathGetConcatenatedSubnames(self)
35 |
36 | proc isEmpty*(self: GodotNodePath): bool {.inline.} =
37 | getGDNativeAPI().nodePathIsEmpty(self)
38 |
39 | proc `==`*(a, b: GodotNodePath): bool {.inline.} =
40 | getGDNativeAPI().nodePathOperatorEqual(a, b)
41 |
--------------------------------------------------------------------------------
/godot/core/godotbase.nim:
--------------------------------------------------------------------------------
1 | # Copyright (c) 2018 Xored Software, Inc.
2 |
3 | import math, godotinternal
4 |
5 | # math helpers
6 |
7 | {.push stackTrace: off.}
8 | const EPSILON = 0.00001'f32
9 | proc isEqualApprox*(a, b: float32): bool {.inline, noinit.} =
10 | abs(a - b) < EPSILON
11 |
12 | proc isEqualApprox*(a, b: float64): bool {.inline, noinit.} =
13 | abs(a - b) < EPSILON
14 |
15 | proc sign*(a: float32): float32 {.inline, noinit.} =
16 | if a < 0: -1.0'f32 else: 1.0'f32
17 |
18 | proc sign*(a: float64): float64 {.inline, noinit.} =
19 | if a < 0: -1.0'f64 else: 1.0'f64
20 |
21 | proc stepify*(value, step: float64): float64 {.inline, noinit.} =
22 | if step != 0'f64:
23 | floor(value / step + 0.5'f64) * step
24 | else:
25 | value
26 |
27 | proc stepify*(value, step: float32): float32 {.inline, noinit.} =
28 | if step != 0'f32:
29 | floor(value / step + 0.5'f32) * step
30 | else:
31 | value
32 |
33 | when (NimMajor, NimMinor, NimPatch) < (0, 20, 4):
34 | # Newer Nim has these procs in system module
35 |
36 | proc min*(x, y: float32): float32 {.inline, noinit.} =
37 | if x <= y: x else: y
38 |
39 | proc abs*(x: float32): float32 {.inline, noinit.} =
40 | if x < 0.0: -x else: x
41 |
42 | proc max*(x, y: float32): float32 {.inline, noinit.} =
43 | if y <= x: x else: y
44 |
45 | {.pop.} # stackTrace: off
46 |
47 | template printWarning*(warning: typed) =
48 | ## Prints ``warning`` to Godot log, adding filename and line information.
49 | let instInfo = instantiationInfo()
50 | godotPrintWarning(cstring($warning), cstring"", cstring(instInfo.filename), instInfo.line.cint)
51 |
52 | template printError*(error: typed) =
53 | ## Prints ``error`` to Godot log, adding filename and line information.
54 | let instInfo = instantiationInfo()
55 | godotPrintError(cstring($error), cstring"", cstring(instInfo.filename), instInfo.line.cint)
56 |
57 | proc print*(parts: varargs[string, `$`]) =
58 | ## Prints concatenated ``parts`` to Godot log.
59 | var combined = ""
60 | for v in parts:
61 | combined.add(v)
62 | var s = combined.toGodotString()
63 | godotPrint(s)
64 | s.deinit()
65 |
--------------------------------------------------------------------------------
/godot/internal/godotstrings.nim:
--------------------------------------------------------------------------------
1 | # Copyright (c) 2018 Xored Software, Inc.
2 |
3 | import godotinternaltypes, gdnativeapi
4 |
5 | proc initGodotString(dest: var GodotString) {.inline, raises: [].} =
6 | getGDNativeAPI().stringNew(dest)
7 |
8 | proc initGodotString(dest: var GodotString; contents: cstring;
9 | size: cint) {.inline.} =
10 | ## Initializes ``dest`` from UTF-8 ``contents``
11 | dest = getGDNativeAPI().stringCharsToUtf8WithLen(contents, size)
12 |
13 | proc `==`*(self, b: GodotString): bool {.inline.} =
14 | getGDNativeAPI().stringOperatorEqual(self, b)
15 |
16 | proc `<`*(self, b: GodotString): bool {.inline.} =
17 | getGDNativeAPI().stringOperatorLess(self, b)
18 |
19 | proc `&`*(self, b: GodotString): GodotString {.inline.} =
20 | getGDNativeAPI().stringOperatorPlus(self, b)
21 |
22 | proc deinit*(self: var GodotString) {.inline.} =
23 | getGDNativeAPI().stringDestroy(self)
24 |
25 | proc len*(self: GodotString): cint {.inline.} =
26 | getGDNativeAPI().stringLength(self)
27 |
28 | proc dataPtr*(self: GodotString): ptr cwchar_t {.inline.} =
29 | getGDNativeAPI().stringWideStr(self)
30 |
31 | proc `$`*(self: GodotString): string =
32 | ## Converts the ``GodotString`` into Nim string
33 | var charStr = getGDNativeAPI().stringUtf8(self)
34 | let length = getGDNativeAPI().charStringLength(charStr)
35 | result = newString(length)
36 | if length > 0:
37 | copyMem(addr result[0], getGDNativeAPI().charStringGetData(charStr), length)
38 | getGDNativeAPI().charStringDestroy(charStr)
39 |
40 | proc toGodotString*(s: string): GodotString {.inline.} =
41 | ## Converts the Nim string into ``GodotString``
42 | when (NimMajor, NimMinor, NimPatch) < (0, 19, 0):
43 | if s.isNil:
44 | initGodotString(result)
45 | else:
46 | initGodotString(result, cstring(s), cint(s.len + 1))
47 | else:
48 | initGodotString(result, cstring(s), cint(s.len + 1))
49 |
50 | proc toGodotString*(s: cstring): GodotString {.inline.} =
51 | ## Converts the cstring into ``GodotString``
52 | if s.isNil:
53 | initGodotString(result)
54 | else:
55 | initGodotString(result, s, cint(s.len + 1))
56 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | sudo: false
2 | language: c
3 | os:
4 | - osx
5 | compiler: clang
6 | env:
7 | global:
8 | - secure: o+IZkRS6J7bGYkiilm10KDeCTDIVHszZ9dPvb93cdUKX/9hFVRiUjDOvNXqBdyOv43JIAsRTppym4B2pfcp9cwLoVBJNW70GKhp6ChLZm3wFdabScWKemuG2YtAUyGiSmxbVmUZ4baltnADyGFHuYWgHLjx6AKO26SqrXRLJ0I1IzGNKKNIfoyZzm7qdFDGJRnSC7L+y1pOITK7dpy60D1vat4FhOLaz2K7L8T8tZYZFK7yyxKduFUlY3cy4z3TpjxMa9/ksCiPiuPDN5xOrVIw0AtgZ2gYodZJUEnfaRzFkgcZ4OJuTAMNMalu52mVAVAoDt4yc7BnbtfsYJzfIjTeLjjWKWz8mqqp/HpxcfVnmPKxV5zeN8UhbosT8vNjwretWbQcFndzt0ohK7E8uMsnDGER7sGPEhCZCttkId96gi7Ro1awPIKCqLaMqB43Bwo48nnW0oQgrfWe1ZKtREXWI4F1F2GMbU8Jsvv0N5GnPGd4RDieBH5KIkJXcttAwRk8AUQ4U5PVkQ/OK9xm9BH2tB0vrjZ4FZWnFPapKVcPUYw9deyyXOXwSMmDpuwkJIjqi3tRyBWJG9+tUlAJw8zyFkCPeN9kzyVH/PhbacwBMdSxew24VLAWWCUhQHCP+fcjpKio8uDUFQN3javIRV4N3mHJ9v0VAF7Ixzh8AviQ=
9 |
10 | addons:
11 | apt:
12 | sources:
13 | - ubuntu-toolchain-r-test
14 | - llvm-toolchain-trusty-3.9
15 | packages:
16 | - build-essential
17 | - scons
18 | - pkg-config
19 | - libx11-dev
20 | - libxcursor-dev
21 | - libasound2-dev
22 | - libfreetype6-dev
23 | - libgl1-mesa-dev
24 | - libglu1-mesa-dev
25 | - libssl-dev
26 | - libxinerama-dev
27 | - libxrandr-dev
28 |
29 | before_install:
30 | - if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then rvm --default use 2.3; brew update; brew install scons ; fi
31 |
32 | install:
33 | - if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then export GODOT_PLATFORM=osx; else export GODOT_PLATFORM=x11; fi
34 | - git clone --depth=1 https://github.com/nim-lang/Nim.git
35 | - cd Nim
36 | - git checkout devel
37 | - sh ci/build.sh
38 | - export PATH=$PATH:"`pwd`/bin"
39 | - ./koch tools -d:release
40 | - nimble install -y
41 | - cd ..
42 | - git clone --depth=1 https://github.com/godotengine/godot.git godotengine
43 | - cd godotengine
44 | - scons -j 3 platform=$GODOT_PLATFORM
45 | - export GODOT_BIN="`pwd`/bin/godot.$GODOT_PLATFORM.tools.64"
46 | - cd ..
47 |
48 | script:
49 | - set -e
50 | - mkdir godotapi
51 | - nim c -d:release -r godot/godotapigen.nim "$GODOT_BIN" godotapi
52 | - nim c -d:useRealtimeGc --path:godot -c godotapi/godotall.nim
53 | - nim c -d:release -r docs/docpublish.nim
54 |
--------------------------------------------------------------------------------
/godot/core/nodepaths.nim:
--------------------------------------------------------------------------------
1 | # Copyright 2018 Xored Software, Inc.
2 |
3 | import hashes
4 |
5 | import internal/godotinternaltypes, internal/godotnodepaths,
6 | internal/godotstrings
7 |
8 | type
9 | NodePath* = ref object
10 | path: GodotNodePath
11 |
12 | proc nodePathFinalizer(path: NodePath) =
13 | path.path.deinit()
14 |
15 | proc newNodePath*(path: GodotNodePath): NodePath =
16 | ## Moves the GodotNodePath into Nim wrapper. The ``path`` will be destroyed
17 | ## automatically when the result is no longer referenced.
18 | new(result, nodePathFinalizer)
19 | result.path = path
20 |
21 | proc newNodePath*(s: string): NodePath =
22 | new(result, nodePathFinalizer)
23 | var str = s.toGodotString()
24 | initGodotNodePath(result.path, str)
25 | str.deinit()
26 |
27 | proc godotNodePath*(path: NodePath): ptr GodotNodePath {.inline.} =
28 | ## WARNING: do not keep the returned value for longer than the lifetime of
29 | ## ``path``
30 | result = addr path.path
31 |
32 | proc `$`*(self: NodePath): string {.inline.} =
33 | var s = self.path.toGodotString()
34 | result = $s
35 | s.deinit()
36 |
37 | proc hash*(self: NodePath): Hash {.inline.} =
38 | ($self).hash()
39 |
40 | proc isAbsolute*(self: NodePath): bool {.inline.} =
41 | self.path.isAbsolute()
42 |
43 | proc nameCount*(self: NodePath): int {.inline.} =
44 | int(self.path.nameCount())
45 |
46 | proc getName*(self: NodePath; idx: int): string {.inline.} =
47 | var s = self.path.getName(idx.cint)
48 | result = $s
49 | s.deinit()
50 |
51 | proc subnameCount*(self: NodePath): int {.inline.} =
52 | int(self.path.subnameCount())
53 |
54 | proc getSubname*(self: NodePath; idx: int): string {.inline.} =
55 | var s = self.path.getSubname(idx.cint)
56 | result = $s
57 | s.deinit()
58 |
59 | proc getConcatenatedSubnames*(self: NodePath): string {.inline.} =
60 | var s = self.path.getConcatenatedSubnames()
61 | result = $s
62 | s.deinit()
63 |
64 | proc isEmpty*(self: NodePath): bool {.inline.} =
65 | self.path.isEmpty()
66 |
67 | proc `==`*(a, b: NodePath): bool =
68 | if a.isNil and b.isNil: return true
69 | if a.isNil != b.isNil: return false
70 | result = a.path == b.path
71 |
72 | converter fromString*(s: string): NodePath =
73 | newNodePath(s)
74 |
--------------------------------------------------------------------------------
/godot/internal/godotdictionaries.nim:
--------------------------------------------------------------------------------
1 | # Copyright (c) 2018 Xored Software, Inc.
2 |
3 | import godotinternaltypes, gdnativeapi
4 |
5 | proc initGodotDictionary*(dest: var GodotDictionary) {.inline.} =
6 | getGDNativeAPI().dictionaryNew(dest)
7 |
8 | proc initGodotDictionary*(dest: var GodotDictionary;
9 | src: GodotDictionary) {.inline.} =
10 | getGDNativeAPI().dictionaryNewCopy(dest, src)
11 |
12 | proc deinit*(self: var GodotDictionary) {.inline.} =
13 | getGDNativeAPI().dictionaryDestroy(self)
14 |
15 | proc len*(self: GodotDictionary): cint {.inline.} =
16 | getGDNativeAPI().dictionarySize(self)
17 |
18 | proc isEmpty*(self: GodotDictionary): bool {.inline.} =
19 | getGDNativeAPI().dictionaryEmpty(self)
20 |
21 | proc clear*(self: var GodotDictionary) {.inline.} =
22 | getGDNativeAPI().dictionaryClear(self)
23 |
24 | proc contains*(self: GodotDictionary; key: GodotVariant): bool {.inline.} =
25 | getGDNativeAPI().dictionaryHas(self, key)
26 |
27 | proc contains*(self: GodotDictionary; keys: GodotArray): bool {.inline.} =
28 | getGDNativeAPI().dictionaryHasAll(self, keys)
29 |
30 | proc del*(self: var GodotDictionary; key: GodotVariant) {.inline.} =
31 | getGDNativeAPI().dictionaryErase(self, key)
32 |
33 | proc godotHash*(self: GodotDictionary): cint {.inline.} =
34 | getGDNativeAPI().dictionaryHash(self, )
35 |
36 | proc keys*(self: GodotDictionary): GodotArray {.inline.} =
37 | getGDNativeAPI().dictionaryKeys(self)
38 |
39 | proc values*(self: GodotDictionary): GodotArray {.inline.} =
40 | getGDNativeAPI().dictionaryValues(self)
41 |
42 | proc `[]`*(self: GodotDictionary; key: GodotVariant): GodotVariant {.inline.} =
43 | getGDNativeAPI().dictionaryGet(self, key)
44 |
45 | proc `[]=`*(self: var GodotDictionary; key, value: GodotVariant) {.inline.} =
46 | getGDNativeAPI().dictionarySet(self, key, value)
47 |
48 | proc mget*(self: var GodotDictionary;
49 | key: GodotVariant): ptr GodotVariant {.inline.} =
50 | getGDNativeAPI().dictionaryOperatorIndex(self, key)
51 |
52 | proc `==`*(self, other: GodotDictionary): bool {.inline.} =
53 | getGDNativeAPI().dictionaryOperatorEqual(self, other)
54 |
55 | proc toJson*(self: GodotDictionary): GodotString {.inline.} =
56 | getGDNativeAPI().dictionaryToJson(self)
57 |
--------------------------------------------------------------------------------
/godot/core/planes.nim:
--------------------------------------------------------------------------------
1 | # Copyright (c) 2018 Xored Software, Inc.
2 |
3 | import hashes
4 |
5 | import vector3
6 |
7 | import internal/godotinternaltypes, internal/godotstrings
8 | import godotcoretypes, gdnativeapi
9 |
10 | proc initPlane*(a, b, c, d: float32): Plane {.inline.} =
11 | getGDNativeAPI().planeNewWithReals(result, a, b, c, d)
12 |
13 | proc initPlane*(v1, v2, v3: Vector3): Plane {.inline.} =
14 | getGDNativeAPI().planeNewWithVectors(result, v1, v2, v3)
15 |
16 | proc initPlane*(normal: Vector3; d: float32): Plane {.inline.} =
17 | result = Plane(
18 | normal: normal,
19 | d: d
20 | )
21 |
22 | proc `$`*(self: Plane): string {.inline.} =
23 | $getGDNativeAPI().planeAsString(self)
24 |
25 | proc hash*(self: Plane): Hash {.inline, noinit.} =
26 | !$(self.normal.hash() !& self.d.hash())
27 |
28 | proc normalized*(self: Plane): Plane {.inline.} =
29 | getGDNativeAPI().planeNormalized(self).toPlane()
30 |
31 | proc center*(self: Plane): Vector3 {.inline.} =
32 | getGDNativeAPI().planeCenter(self).toVector3()
33 |
34 | proc getAnyPoint*(self: Plane): Vector3 {.inline.} =
35 | getGDNativeAPI().planeGetAnyPoint(self).toVector3()
36 |
37 | proc isPointOver*(self: Plane; point: Vector3): bool {.inline.} =
38 | getGDNativeAPI().planeIsPointOver(self, point)
39 |
40 | proc distanceTo*(self: Plane; point: Vector3): float32 {.inline.} =
41 | getGDNativeAPI().planeDistanceTo(self, point)
42 |
43 | proc contains*(self: Plane; point: Vector3;
44 | epsilon: float32): bool {.inline.} =
45 | getGDNativeAPI().planeHasPoint(self, point, epsilon)
46 |
47 | proc project*(self: Plane; point: Vector3): Vector3 {.inline.} =
48 | getGDNativeAPI().planeProject(self, point).toVector3()
49 |
50 | proc intersect3*(self: Plane; dest: var Vector3;
51 | b, c: Plane): bool {.inline.} =
52 | getGDNativeAPI().planeIntersect3(self, dest, b, c)
53 |
54 | proc intersectsRay*(self: Plane; dest: var Vector3;
55 | v, dir: Vector3): bool {.inline.} =
56 | getGDNativeAPI().planeIntersectsRay(self, dest, v, dir)
57 |
58 | proc intersectsSegment*(self: Plane; dest: var Vector3;
59 | segmentBegin, segmentEnd: Vector3): bool {.inline.} =
60 | getGDNativeAPI().planeIntersectsSegment(self, dest, segmentBegin, segmentEnd)
61 |
62 | proc `-`*(self: Plane): Plane {.inline.} =
63 | getGDNativeAPI().planeOperatorNeg(self).toPlane()
64 |
65 | proc `==`*(a, b: Plane): bool {.inline.} =
66 | getGDNativeAPI().planeOperatorEqual(a, b)
67 |
--------------------------------------------------------------------------------
/godot/core/quats.nim:
--------------------------------------------------------------------------------
1 | # Copyright (c) 2018 Xored Software, Inc.
2 |
3 | import hashes
4 |
5 | import internal/godotinternaltypes, internal/godotstrings
6 | import godotcoretypes, gdnativeapi
7 |
8 | proc initQuat*(x, y, z, w: float32): Quat {.inline.} =
9 | result = Quat(
10 | x: x,
11 | y: y,
12 | z: z,
13 | w: w
14 | )
15 |
16 | proc initQuat*(axis: Vector3; angle: float32): Quat {.inline.} =
17 | getGDNativeAPI().quatNewWithAxisAngle(result, axis, angle)
18 |
19 | proc `$`*(self: Quat): string {.inline.} =
20 | $getGDNativeAPI().quatAsString(self)
21 |
22 | proc hash*(self: Quat): Hash {.inline.} =
23 | !$(self.x.hash() !& self.y.hash() !& self.z.hash() !& self.w.hash())
24 |
25 | proc length*(self: Quat): float32 {.inline.} =
26 | getGDNativeAPI().quatLength(self)
27 |
28 | proc lengthSquared*(self: Quat): float32 {.inline.} =
29 | getGDNativeAPI().quatLengthSquared(self)
30 |
31 | proc normalized*(self: Quat): Quat {.inline.} =
32 | getGDNativeAPI().quatNormalized(self).toQuat()
33 |
34 | proc isNormalized*(self: Quat): bool {.inline.} =
35 | getGDNativeAPI().quatIsNormalized(self)
36 |
37 | proc inverse*(self: Quat): Quat {.inline.} =
38 | getGDNativeAPI().quatInverse(self).toQuat()
39 |
40 | proc dot*(a, b: Quat): float32 {.inline.} =
41 | getGDNativeAPI().quatDot(a, b)
42 |
43 | proc xform*(self: Quat; v: Vector3): Vector3 {.inline.} =
44 | getGDNativeAPI().quatXform(self, v).toVector3()
45 |
46 | proc slerp*(self: Quat; b: Quat; t: float32): Quat {.inline.} =
47 | getGDNativeAPI().quatSlerp(self, b, t).toQuat()
48 |
49 | proc slerpni*(self: Quat; b: Quat; t: float32): Quat {.inline.} =
50 | getGDNativeAPI().quatSlerpni(self, b, t).toQuat()
51 |
52 | proc cubicSlerp*(self, b, preA, postB: Quat;
53 | t: float32): Quat {.inline.} =
54 | getGDNativeAPI().quatCubicSlerp(self, b, preA, postB, t).toQuat()
55 |
56 | proc `*`*(a: Quat, b: float32): Quat {.inline.} =
57 | getGDNativeAPI().quatOperatorMultiply(a, b).toQuat()
58 |
59 | proc `*=`*(a: var Quat, b: float32) {.inline.} =
60 | a = a * b
61 |
62 | proc `+`*(a, b: Quat): Quat {.inline.} =
63 | getGDNativeAPI().quatOperatorAdd(a, b).toQuat()
64 |
65 | proc `+=`*(a: var Quat, b: Quat) {.inline.} =
66 | a = a + b
67 |
68 | proc `-`*(a, b: Quat): Quat {.inline.} =
69 | getGDNativeAPI().quatOperatorSubtract(a, b).toQuat()
70 |
71 | proc `-=`* (a: var Quat, b: Quat) {.inline.} =
72 | a = a - b
73 |
74 | proc `/`*(self: Quat; b: float32): Quat {.inline.} =
75 | getGDNativeAPI().quatOperatorDivide(self, b).toQuat()
76 |
77 | proc `/=`*(self: var Quat, b: float32) {.inline.} =
78 | self = self / b
79 |
80 | proc `==`*(a, b: Quat): bool {.inline.} =
81 | getGDNativeAPI().quatOperatorEqual(a, b)
82 |
83 | proc `-`*(self: Quat): Quat {.inline.} =
84 | getGDNativeAPI().quatOperatorNeg(self).toQuat()
85 |
--------------------------------------------------------------------------------
/godot/core/colors.nim:
--------------------------------------------------------------------------------
1 | # Copyright (c) 2018 Xored Software, Inc.
2 |
3 | import hashes
4 |
5 | import godotcoretypes, gdnativeapi
6 |
7 | proc initColor*(r, g, b: float32; a: float32 = 1.0'f32): Color {.inline.} =
8 | Color(
9 | r: r,
10 | g: g,
11 | b: b,
12 | a: a
13 | )
14 |
15 | proc initColor*(): Color {.inline.} =
16 | ## Initializes black color with 1.0 alpha
17 | initColor(0, 0, 0)
18 |
19 | proc h*(self: Color): float32 {.inline.} =
20 | getGDNativeAPI().colorGetH(self)
21 |
22 | proc s*(self: Color): float32 {.inline.} =
23 | getGDNativeAPI().colorGetS(self)
24 |
25 | proc v*(self: Color): float32 {.inline.} =
26 | getGDNativeAPI().colorGetV(self)
27 |
28 | proc `$`*(self: Color): string {.inline.} =
29 | result = newStringOfCap(50)
30 | result.add($self.r)
31 | result.add(", ")
32 | result.add($self.g)
33 | result.add(", ")
34 | result.add($self.b)
35 | result.add(", ")
36 | result.add($self.a)
37 |
38 | proc hash*(self: Color): Hash {.inline.} =
39 | !$(self.r.hash() !& self.g.hash() !& self.b.hash() !& self.a.hash())
40 |
41 | proc toHex(val: float32, target: var string, targetIdx: int) =
42 | let val = clamp(int(val * 255), 0, 255)
43 | let nums = [(val and 0xF0) shr 4, val and 0xF]
44 | for i, num in nums:
45 | target[targetIdx + i] = if num < 10: chr(ord('0') + num)
46 | else: chr(ord('A') + (num - 10))
47 |
48 | proc toHtml*(self: Color, withAlpha: bool): string =
49 | let size = if withAlpha: 8 else: 6
50 | result = newString(size)
51 | toHex(self.r, result, 0)
52 | toHex(self.g, result, 2)
53 | toHex(self.b, result, 4)
54 | if withAlpha:
55 | toHex(self.b, result, 6)
56 |
57 | proc toARGB32*(self: Color): uint32 {.inline.} =
58 | result = uint8(self.a * 255)
59 | result = (result shl 8) or uint8(self.r * 255)
60 | result = (result shl 8) or uint8(self.g * 255)
61 | result = (result shl 8) or uint8(self.b * 255)
62 |
63 | proc gray*(self: Color): float32 {.inline.} =
64 | getGDNativeAPI().colorGray(self)
65 |
66 | proc inverted*(self: Color): Color {.inline.} =
67 | getGDNativeAPI().colorInverted(self).toColor()
68 |
69 | proc contrasted*(self: Color): Color {.inline.} =
70 | getGDNativeAPI().colorContrasted(self).toColor()
71 |
72 | proc lerp*(self: Color; b: Color; t: float32): Color {.inline.} =
73 | getGDNativeAPI().colorLinearInterpolate(self, b, t).toColor()
74 |
75 | proc blend*(self: Color; over: Color): Color {.inline.} =
76 | getGDNativeAPI().colorBlend(self, over).toColor()
77 |
78 | proc `==`*(a, b: Color): bool {.inline.} =
79 | a.r == b.r and a.g == b.g and a.b == b.b and a.a == b.a
80 |
81 | proc `<`*(a, b: Color): bool =
82 | if a.r == b.r:
83 | if a.g == b.g:
84 | if a.b == b.b:
85 | return a.a < b.a
86 | return a.b < b.b
87 | return a.g < b.g
88 | return a.r < b.r
89 |
--------------------------------------------------------------------------------
/godot/core/aabb.nim:
--------------------------------------------------------------------------------
1 | # Copyright (c) 2018 Xored Software, Inc.
2 |
3 | import hashes
4 |
5 | import vector3
6 | import internal/godotinternaltypes, internal/godotstrings
7 | import godotcoretypes, gdnativeapi
8 |
9 | proc initAABB*(pos, size: Vector3): AABB {.inline.} =
10 | AABB(position: pos, size: size)
11 |
12 | proc `$`*(self: AABB): string {.inline.} =
13 | $getGDNativeAPI().aabbAsString(self)
14 |
15 | proc hash*(self: AABB): Hash {.inline.} =
16 | !$(self.position.hash() !& self.size.hash())
17 |
18 | proc area*(self: AABB): float32 {.inline.} =
19 | getGDNativeAPI().aabbGetArea(self)
20 |
21 | proc hasNoArea*(self: AABB): bool {.inline.} =
22 | getGDNativeAPI().aabbHasNoArea(self)
23 |
24 | proc hasNoSurface*(self: AABB): bool {.inline.} =
25 | getGDNativeAPI().aabbHasNoSurface(self)
26 |
27 | proc intersects*(self, other: AABB): bool {.inline.} =
28 | getGDNativeAPI().aabbIntersects(self, other)
29 |
30 | proc encloses*(self, other: AABB): bool {.inline.} =
31 | getGDNativeAPI().aabbEncloses(self, other)
32 |
33 | proc merge*(self, other: AABB): AABB {.inline.} =
34 | getGDNativeAPI().aabbMerge(self, other).toAABB()
35 |
36 | proc intersection*(self, other: AABB): AABB {.inline.} =
37 | getGDNativeAPI().aabbIntersection(self, other).toAABB()
38 |
39 | proc intersectsPlane*(self: AABB; plane: Plane): bool {.inline.} =
40 | getGDNativeAPI().aabbIntersectsPlane(self, plane)
41 |
42 | proc intersectsSegment*(self: AABB; start, to: Vector3): bool {.inline.} =
43 | getGDNativeAPI().aabbIntersectsSegment(self, start, to)
44 |
45 | proc contains*(self: AABB; point: Vector3): bool {.inline.} =
46 | getGDNativeAPI().aabbHasPoint(self, point)
47 |
48 | proc getSupport*(self: AABB; dir: Vector3): Vector3 {.inline.} =
49 | getGDNativeAPI().aabbGetSupport(self, dir).toVector3()
50 |
51 | proc getLongestAxis*(self: AABB): Vector3 {.inline.} =
52 | getGDNativeAPI().aabbGetLongestAxis(self).toVector3()
53 |
54 | proc getLongestAxisIndex*(self: AABB): cint {.inline.} =
55 | getGDNativeAPI().aabbGetLongestAxisIndex(self)
56 |
57 | proc getLongestAxisSize*(self: AABB): float32 {.inline.} =
58 | getGDNativeAPI().aabbGetLongestAxisSize(self)
59 |
60 | proc getShortestAxis*(self: AABB): Vector3 {.inline.} =
61 | getGDNativeAPI().aabbGetShortestAxis(self).toVector3()
62 |
63 | proc getShortestAxisIndex*(self: AABB): cint {.inline.} =
64 | getGDNativeAPI().aabbGetShortestAxisIndex(self)
65 |
66 | proc getShortestAxisSize*(self: AABB): float32 {.inline.} =
67 | getGDNativeAPI().aabbGetShortestAxisSize(self)
68 |
69 | proc expand*(self: AABB; toPoint: Vector3): AABB {.inline.} =
70 | getGDNativeAPI().aabbExpand(self, toPoint).toAABB()
71 |
72 | proc grow*(self: AABB; by: float32): AABB {.inline.} =
73 | getGDNativeAPI().aabbGrow(self, by).toAABB()
74 |
75 | proc getEndpoint*(self: AABB; idx: cint): Vector3 {.inline.} =
76 | getGDNativeAPI().aabbGetEndpoint(self, idx).toVector3()
77 |
78 | proc `==`*(a, b: AABB): bool {.inline.} =
79 | getGDNativeAPI().aabbOperatorEqual(a, b)
80 |
--------------------------------------------------------------------------------
/godot/core/godotcoretypes.nim:
--------------------------------------------------------------------------------
1 | # Copyright 2018 Xored Software, Inc.
2 |
3 | type
4 | Color* {.byref.} = object
5 | r*: float32
6 | g*: float32
7 | b*: float32
8 | a*: float32
9 |
10 | Vector3* {.byref.} = object
11 | x*: float32
12 | y*: float32
13 | z*: float32
14 |
15 | Vector2* {.byref.} = object
16 | x*: float32
17 | y*: float32
18 |
19 | Plane* {.byref.} = object
20 | normal*: Vector3
21 | d*: float32
22 |
23 | Basis* {.byref.} = object
24 | elements*: array[3, Vector3]
25 |
26 | Quat* {.byref.} = object
27 | x*: float32
28 | y*: float32
29 | z*: float32
30 | w*: float32
31 |
32 | AABB* {.byref.} = object
33 | position*: Vector3
34 | size*: Vector3
35 |
36 | Rect2* {.byref.} = object
37 | position*: Vector2
38 | size*: Vector2
39 |
40 | Transform2D* {.byref.} = object
41 | elements*: array[3, Vector2]
42 |
43 | Transform* {.byref.} = object
44 | basis*: Basis
45 | origin*: Vector3
46 |
47 | RID* {.byref.} = object
48 | data: array[sizeof(int), byte]
49 |
50 | Error* {.size: sizeof(cint), pure.} = enum
51 | OK,
52 | Failed, ## Generic fail error
53 | Unavailable, ## What is requested is unsupported/unavailable
54 | Unconfigured, ## The object being used hasnt been properly set up yet
55 | Unauthorized, ## Missing credentials for requested resource
56 | ParameterRangeError, ## Parameter given out of range (5)
57 | OutOfMemory, ## Out of memory
58 | FileNotFound,
59 | FileBadDrive,
60 | FileBadPath,
61 | FileNoPermission, ## (10)
62 | FileAlreadyInUse,
63 | FileCantOpen,
64 | FileCantWrite,
65 | FileCantRead,
66 | FileUnrecognized, ## (15)
67 | FileCorrupt,
68 | FileMissingDependencies,
69 | FileEOF,
70 | CantOpen, ## Can't open a resource/socket/file
71 | CantCreate, ## (20)
72 | QueryFailed,
73 | AlreadyInUse,
74 | Locked, ## resource is locked
75 | Timeout,
76 | CantConnect, ## (25)
77 | CantResolve,
78 | ConnectionError,
79 | CantAquireResource,
80 | CantFork,
81 | InvalidData, ## Data passed is invalid (30)
82 | InvalidParameter, ## Parameter passed is invalid
83 | AlreadyExists, ## When adding, item already exists
84 | DoesNotExist, ## When retrieving/erasing, it item does not exist
85 | DatabaseCantRead, ## Database is full
86 | DatabaseCantWrite, ## Database is full (35)
87 | CompilationFailed,
88 | MethodNotFound,
89 | LinkFailed,
90 | ScriptFailed,
91 | CyclicLink, ## (40)
92 | InvalidDeclaration,
93 | DuplicateSymbol,
94 | PauseError,
95 | Busy,
96 | Skip, ## (45)
97 | Help, ## user requested help!!
98 | Bug,
99 | ## a bug in the software certainly happened, due to a double
100 | ## check failing or unexpected behavior.
101 | PrinterOnFire, ## the parallel port printer is engulfed in flames
102 | WTF ## shit happens, has never been used, though
103 |
--------------------------------------------------------------------------------
/godot/core/transforms.nim:
--------------------------------------------------------------------------------
1 | # Copyright (c) 2018 Xored Software, Inc.
2 |
3 | import hashes
4 |
5 | import internal/godotinternaltypes, internal/godotstrings
6 | import godotcoretypes, gdnativeapi
7 | import basis, vector3
8 |
9 | proc initTransform*(): Transform {.inline.} =
10 | result.basis = initBasis()
11 |
12 | proc initTransform*(xAxis, yAxis, zAxis,
13 | origin: Vector3): Transform {.inline.} =
14 | var basis: Basis
15 | basis.setAxis(0, xAxis)
16 | basis.setAxis(1, yAxis)
17 | basis.setAxis(2, zAxis)
18 | Transform(basis: basis, origin: origin)
19 |
20 | proc initTransform*(basis: Basis, origin: Vector3): Transform {.inline.} =
21 | Transform(basis: basis, origin: origin)
22 |
23 | proc `$`*(self: Transform): string {.inline.} =
24 | $getGDNativeAPI().transformAsString(self)
25 |
26 | proc hash*(self: Transform): Hash {.inline.} =
27 | !$(self.basis.hash() !& self.origin.hash())
28 |
29 | proc inverse*(self: Transform): Transform {.inline.} =
30 | getGDNativeAPI().transformInverse(self).toTransform()
31 |
32 | proc affineInverse*(self: Transform): Transform {.inline.} =
33 | getGDNativeAPI().transformAffineInverse(self).toTransform()
34 |
35 | proc orthonormalized*(self: Transform): Transform {.inline.} =
36 | getGDNativeAPI().transformOrthonormalized(self).toTransform()
37 |
38 | proc rotated*(self: Transform; axis: Vector3;
39 | phi: float32): Transform {.inline.} =
40 | getGDNativeAPI().transformRotated(self, axis, phi).toTransform()
41 |
42 | proc scaled*(self: Transform; scale: Vector3): Transform {.inline.} =
43 | getGDNativeAPI().transformScaled(self, scale).toTransform()
44 |
45 | proc translated*(self: Transform; offset: Vector3): Transform {.inline.} =
46 | getGDNativeAPI().transformTranslated(self, offset).toTransform()
47 |
48 | proc lookingAt*(self: Transform; target, up: Vector3): Transform {.inline.} =
49 | getGDNativeAPI().transformLookingAt(self, target, up).toTransform()
50 |
51 | proc xformPlane*(self: Transform; plane: Plane): Plane {.inline.} =
52 | getGDNativeAPI().transformXformPlane(self, plane).toPlane()
53 |
54 | proc xformInvPlane*(self: Transform; plane: Plane): Plane {.inline.} =
55 | getGDNativeAPI().transformXformInvPlane(self, plane).toPlane()
56 |
57 | proc xformVector3*(self: Transform; v: Vector3): Vector3 {.inline.} =
58 | getGDNativeAPI().transformXformVector3(self, v).toVector3()
59 |
60 | proc xformInvVector3*(self: Transform; v: Vector3): Vector3 {.inline.} =
61 | getGDNativeAPI().transformXformInvVector3(self, v).toVector3()
62 |
63 | proc xformAABB*(self: Transform; rect: AABB): AABB {.inline.} =
64 | getGDNativeAPI().transformXformAABB(self, rect).toAABB()
65 |
66 | proc xformInvAABB*(self: Transform; rect: AABB): AABB {.inline.} =
67 | getGDNativeAPI().transformXformInvAABB(self, rect).toAABB()
68 |
69 | proc `==`*(self: Transform; b: Transform): bool {.inline.} =
70 | getGDNativeAPI().transformOperatorEqual(self, b)
71 |
72 | proc `*`*(self, other: Transform): Transform {.inline.} =
73 | getGDNativeAPI().transformOperatorMultiply(self, other).toTransform()
74 |
75 | proc `*=`*(self: var Transform, other: Transform) {.inline.} =
76 | self = self * other
77 |
--------------------------------------------------------------------------------
/godot/core/transform2d.nim:
--------------------------------------------------------------------------------
1 | # Copyright (c) 2018 Xored Software, Inc.
2 |
3 | import hashes, vector2
4 |
5 | import internal/godotinternaltypes, internal/godotstrings
6 | import godotcoretypes, gdnativeapi
7 |
8 | proc initTransform2D*(): Transform2D {.inline.} =
9 | getGDNativeAPI().transform2DNewIdentity(result)
10 |
11 | proc initTransform2D*(rot: float32; pos: Vector2): Transform2D {.inline.} =
12 | getGDNativeAPI().transform2DNew(result, rot, pos)
13 |
14 | proc initTransform2D*(xAxis, yAxis, origin: Vector2): Transform2D {.inline.} =
15 | getGDNativeAPI().transform2DNewAxisOrigin(result, xAxis, yAxis, origin)
16 |
17 | proc `$`*(self: Transform2D): string {.inline.} =
18 | $getGDNativeAPI().transform2DAsString(self)
19 |
20 | proc hash*(self: Transform2D): Hash {.inline, noinit.} =
21 | !$(self.elements[0].hash() !& self.elements[1].hash() !& self.elements[2].hash())
22 |
23 | proc inverse*(self: Transform2D): Transform2D {.inline.} =
24 | getGDNativeAPI().transform2DInverse(self).toTransform2D()
25 |
26 | proc affineInverse*(self: Transform2D): Transform2D {.inline.} =
27 | getGDNativeAPI().transform2DAffineInverse(self).toTransform2D()
28 |
29 | proc rotation*(self: Transform2D): float32 {.inline.} =
30 | getGDNativeAPI().transform2DGetRotation(self)
31 |
32 | proc origin*(self: Transform2D): Vector2 {.inline.} =
33 | getGDNativeAPI().transform2DGetOrigin(self).toVector2()
34 |
35 | proc scale*(self: Transform2D): Vector2 {.inline.} =
36 | getGDNativeAPI().transform2DGetScale(self).toVector2()
37 |
38 | proc orthonormalized*(self: Transform2D): Transform2D {.inline.} =
39 | getGDNativeAPI().transform2DOrthonormalized(self).toTransform2D()
40 |
41 | proc rotated*(self: Transform2D; phi: float32): Transform2D {.inline.} =
42 | getGDNativeAPI().transform2DRotated(self, phi).toTransform2D()
43 |
44 | proc scaled*(self: Transform2D; scale: Vector2): Transform2D {.inline.} =
45 | getGDNativeAPI().transform2DScaled(self, scale).toTransform2D()
46 |
47 | proc translated*(self: Transform2D; offset: Vector2): Transform2D {.inline.} =
48 | getGDNativeAPI().transform2DTranslated(self, offset).toTransform2D()
49 |
50 | proc xformVector2*(self: Transform2D; v: Vector2): Vector2 {.inline.} =
51 | getGDNativeAPI().transform2DXformVector2(self, v).toVector2()
52 |
53 | proc xformInvVector2*(self: Transform2D; v: Vector2): Vector2 {.inline.} =
54 | getGDNativeAPI().transform2DXformInvVector2(self, v).toVector2()
55 |
56 | proc basisXformVector2*(self: Transform2D; v: Vector2): Vector2 {.inline.} =
57 | getGDNativeAPI().transform2DBasisXformVector2(self, v).toVector2()
58 |
59 | proc basisXformInvVector2*(self: Transform2D; v: Vector2): Vector2 {.inline.} =
60 | getGDNativeAPI().transform2DBasisXformInvVector2(self, v).toVector2()
61 |
62 | proc xformRect2*(self: Transform2D; rect: Rect2): Rect2 {.inline.} =
63 | getGDNativeAPI().transform2DXformRect2(self, rect).toRect2()
64 |
65 | proc xformInvRect2*(self: Transform2D; rect: Rect2): Rect2 {.inline.} =
66 | getGDNativeAPI().transform2DXformInvRect2(self, rect).toRect2()
67 |
68 | proc interpolateWith*(self, m: Transform2D;
69 | c: float32): Transform2D {.inline.} =
70 | getGDNativeAPI().transform2DInterpolateWith(self, m, c).toTransform2D()
71 |
72 | proc `==`*(a, b: Transform2D): bool {.inline.} =
73 | getGDNativeAPI().transform2DOperatorEqual(a, b)
74 |
75 | proc `*`*(a, b: Transform2D): Transform2D {.inline.} =
76 | getGDNativeAPI().transform2DOperatorMultiply(a, b).toTransform2D()
77 |
78 | proc `*=`*(a: var Transform2D, b: Transform2D) {.inline.} =
79 | a = a * b
80 |
--------------------------------------------------------------------------------
/docs/docpublish.nim:
--------------------------------------------------------------------------------
1 | # Copyright 2018 Xored Software, Inc.
2 |
3 | import os, pegs, strutils
4 | import docbuild
5 |
6 | const indexTemplate = """
7 |
godot-nim docs index
8 |
9 | Documentation of Nim bindings for Godot Engine (GitHub)
10 | $VERSION_LIST
11 |
12 |
13 | """
14 |
15 | proc execOrQuit(cmd: string) =
16 | let ret = execShellCmd(cmd)
17 | if ret != 0:
18 | quit(ret)
19 |
20 | proc walkDirRecRelative(dir: string, cb: proc (file: string), start = "") =
21 | for kind, path in walkDir(dir, relative = true):
22 | if kind in {pcFile, pcLinkToFile}:
23 | cb(if start.len > 0: start / path else: path)
24 | elif kind in {pcDir, pcLinkToDir}:
25 | let fullPath = if start.len > 0: start / path else: path
26 | walkDirRecRelative(dir / fullPath, cb, fullPath)
27 |
28 | proc publish(docDir, gitHubToken, repoSlug, branch, tag, changeset: string) =
29 | let release = if branch == "master": branch else: tag
30 | let commitComment = if release == "master":
31 | "Update master documentation for changeset " & changeset
32 | else:
33 | "Update documentation for " & tag
34 |
35 | const repoDir = "gh-pages"
36 | execOrQuit(
37 | "git clone --depth=1 --branch=gh-pages https://github.com/$#.git $#" %
38 | [repoSlug, repoDir])
39 | try:
40 | removeDir(repoDir/release)
41 | createDir(repoDir/release)
42 | var versionList = newStringOfCap(4096)
43 | for kind, path in walkDir(repoDir, relative = true):
44 | if kind == pcDir and not path.startsWith("."):
45 | versionList.add("$1
" % path)
46 | let index = indexTemplate.replace("$REPO_SLUG", repoSlug).
47 | replace("$VERSION_LIST", versionList)
48 | writeFile(repoDir/"index.html", index)
49 |
50 | walkDirRecRelative(docDir) do (file: string):
51 | createDir(parentDir(repoDir/release/file))
52 | copyFile(docDir/file, repoDir/release/file)
53 |
54 | setCurrentDir(repoDir)
55 | try:
56 | execOrQuit("git add --all")
57 | execOrQuit("git commit -m \"$#\"" % commitComment)
58 | execOrQuit("git push -fq \"https://$#@github.com/$#.git\" gh-pages" %
59 | [gitHubToken, repoSlug])
60 | finally:
61 | setCurrentDir("..")
62 | finally:
63 | removeDir(repoDir)
64 |
65 | when isMainModule:
66 | proc getEnvOrQuit(key: string): string =
67 | result = getEnv(key)
68 | if result.len == 0:
69 | echo "Expected environment variable: " & key
70 | quit(1)
71 |
72 | let pr = getEnv("TRAVIS_PULL_REQUEST")
73 | if pr.len > 0 and pr != "false":
74 | echo "This is a PR build. Skipping."
75 | quit(0)
76 |
77 | let repoSlug = getEnvOrQuit("TRAVIS_REPO_SLUG")
78 | let branch = getEnvOrQuit("TRAVIS_BRANCH")
79 | let changeset = getEnvOrQuit("TRAVIS_COMMIT")
80 | let tag = getEnv("TRAVIS_TAG")
81 |
82 | # let repoSlug = "pragmagic/godot-nim"
83 | # let branch = "master"
84 | # let changeset = "0fd0101432c1fed1004f50b035fcf74f75f004a8"
85 | # let tag = ""
86 |
87 | let gitHubToken = getEnvOrQuit("GITHUB_TOKEN")
88 |
89 | if branch != "master" and not (tag =~ peg"^ 'v' \d+ '.' \d+ '.' \d+ $"):
90 | echo "This is not master or tagged changeset. Skipping."
91 | quit(0)
92 |
93 | let godotBin = getEnvOrQuit("GODOT_BIN")
94 |
95 | const docDir = "docgen"
96 | buildDocs(docDir, getCurrentDir(), godotBin)
97 | publish(docDir, gitHubToken, repoSlug, branch, tag, changeset)
98 |
--------------------------------------------------------------------------------
/godot/core/dictionaries.nim:
--------------------------------------------------------------------------------
1 | # Copyright 2018 Xored Software, Inc.
2 |
3 | import hashes
4 | import internal/godotinternaltypes, internal/godotdictionaries,
5 | internal/godotvariants, internal/godotstrings
6 |
7 | type
8 | Dictionary* = ref object
9 | godotDictionary: GodotDictionary
10 |
11 | proc dictionaryFinalizer(dict: Dictionary) =
12 | dict.godotDictionary.deinit()
13 |
14 | proc newDictionary*(): Dictionary {.inline.} =
15 | new(result, dictionaryFinalizer)
16 | initGodotDictionary(result.godotDictionary)
17 |
18 | proc newDictionary*(dict: GodotDictionary): Dictionary {.inline.} =
19 | new(result, dictionaryFinalizer)
20 | result.godotDictionary = dict
21 |
22 | proc godotDictionary*(dict: Dictionary): ptr GodotDictionary =
23 | ## WARNING: do not keep the returned value for longer than the lifetime of
24 | ## ``dict``
25 | addr dict.godotDictionary
26 |
27 | proc len*(self: Dictionary): int {.inline.} =
28 | self.godotDictionary.len.int
29 |
30 | proc isEmpty*(self: Dictionary): bool {.inline.} =
31 | self.godotDictionary.isEmpty()
32 |
33 | proc clear*(self: Dictionary) {.inline.} =
34 | self.godotDictionary.clear()
35 |
36 | proc hash*(self: Dictionary): Hash {.inline.} =
37 | hash(self.godotDictionary.godotHash())
38 |
39 | import variants, arrays
40 |
41 | proc newVariant*(dict: Dictionary): Variant {.inline.} =
42 | new(result, variantFinalizer)
43 | initGodotVariant(result.godotVariant[], dict.godotDictionary)
44 |
45 | proc asDictionary*(self: Variant): Dictionary {.inline.} =
46 | newDictionary(self.godotVariant[].asGodotDictionary())
47 |
48 | proc contains*(self: Dictionary; key: Variant): bool {.inline.}=
49 | self.godotDictionary.contains(key.godotVariant[])
50 |
51 | proc contains*(self: Dictionary; keys: Array): bool {.inline.} =
52 | self.godotDictionary.contains(keys.godotArray[])
53 |
54 | proc del*(self: Dictionary; key: Variant) {.inline.} =
55 | self.godotDictionary.del(key.godotVariant[])
56 |
57 | proc keys*(self: Dictionary): Array {.inline.} =
58 | newArray(self.godotDictionary.keys())
59 |
60 | proc values*(self: Dictionary): Array {.inline.} =
61 | newArray(self.godotDictionary.values())
62 |
63 | proc `[]`*(self: Dictionary; key: Variant): Variant {.inline.} =
64 | newVariant(self.godotDictionary[key.godotVariant[]])
65 |
66 | proc `[]`*(self: Dictionary; keyStr: string): Variant {.inline.} =
67 | var godotVariant: GodotVariant
68 | var godotStr = keyStr.toGodotString()
69 | initGodotVariant(godotVariant, godotStr)
70 | result = newVariant(self.godotDictionary[godotVariant])
71 | godotStr.deinit()
72 | godotVariant.deinit()
73 |
74 | proc `[]=`*(self: Dictionary; key, value: Variant) {.inline.} =
75 | self.godotDictionary[key.godotVariant[]] = value.godotVariant[]
76 |
77 | proc `==`*(self, other: Dictionary): bool {.inline.} =
78 | if self.isNil and other.isNil: return true
79 | if self.isNil != other.isNil: return false
80 | result = self.godotDictionary == other.godotDictionary
81 |
82 | proc toJson*(self: Dictionary): string {.inline.} =
83 | var s = self.godotDictionary.toJson()
84 | result = $s
85 | s.deinit()
86 |
87 | iterator keys*(dict: Dictionary): Variant =
88 | let keyArr = dict.keys()
89 | for key in keyArr:
90 | yield key
91 |
92 | iterator values*(dict: Dictionary): Variant =
93 | let valArr = dict.values()
94 | for val in valArr:
95 | yield val
96 |
97 | iterator pairs*(dict: Dictionary): tuple[key, val: Variant] =
98 | for key in keys(dict):
99 | yield (key, dict[key])
100 |
101 | proc `$`*(self: Dictionary): string =
102 | result = newStringOfCap(32)
103 | result.add('{')
104 | for k, v in self:
105 | if result.len > 1:
106 | result.add(", ")
107 | result.add($k)
108 | result.add(": ")
109 | result.add($v)
110 | result.add('}')
111 |
--------------------------------------------------------------------------------
/godot/core/arrays.nim:
--------------------------------------------------------------------------------
1 | # Copyright 2018 Xored Software, Inc.
2 |
3 | import hashes
4 | import internal/godotinternaltypes, internal/godotarrays
5 |
6 | type
7 | Array* = ref object
8 | godotArray: GodotArray
9 |
10 | proc godotArray*(arr: Array): ptr GodotArray {.inline.} =
11 | ## WARNING: do not keep the returned value for longer than the lifetime of
12 | ## ``arr``
13 | addr arr.godotArray
14 |
15 | proc arrayFinalizer(arr: Array) =
16 | arr.godotArray.deinit()
17 |
18 | proc newArray*(arr: GodotArray): Array {.inline.} =
19 | new(result, arrayFinalizer)
20 | result.godotArray = arr
21 |
22 | import variants
23 |
24 | proc newArray*(s: varargs[Variant]): Array =
25 | new(result, arrayFinalizer)
26 | initGodotArray(result.godotArray)
27 | for v in s:
28 | result.godotArray.add(v.godotVariant[])
29 |
30 | proc newArray*(s: openarray[Variant]): Array =
31 | result = newArray()
32 | for v in s:
33 | result.godotArray.add(v.godotVariant[])
34 |
35 | import poolarrays
36 |
37 | proc newArray*(pca: PoolColorArray): Array {.inline.} =
38 | new(result, arrayFinalizer)
39 | initGodotArray(result.godotArray, pca.godotPoolColorArray[])
40 |
41 | proc newArray*(pv3a: PoolVector3Array): Array {.inline.} =
42 | new(result, arrayFinalizer)
43 | initGodotArray(result.godotArray, pv3a.godotPoolVector3Array[])
44 |
45 | proc newArray*(pv2a: PoolVector2Array): Array {.inline.} =
46 | new(result, arrayFinalizer)
47 | initGodotArray(result.godotArray, pv2a.godotPoolVector2Array[])
48 |
49 | proc newArray*(psa: PoolStringArray): Array {.inline.} =
50 | new(result, arrayFinalizer)
51 | initGodotArray(result.godotArray, psa.godotPoolStringArray[])
52 |
53 | proc newArray*(pra: PoolRealArray): Array {.inline.} =
54 | new(result, arrayFinalizer)
55 | initGodotArray(result.godotArray, pra.godotPoolRealArray[])
56 |
57 | proc newArray*(pia: PoolIntArray): Array {.inline.} =
58 | new(result, arrayFinalizer)
59 | initGodotArray(result.godotArray, pia.godotPoolIntArray[])
60 |
61 | proc newArray*(pba: PoolByteArray): Array {.inline.} =
62 | new(result, arrayFinalizer)
63 | initGodotArray(result.godotArray, pba.godotPoolByteArray[])
64 |
65 | proc `[]=`*(self: Array; idx: int; value: Variant) {.inline.} =
66 | self.godotArray[idx.cint] = value.godotVariant[]
67 |
68 | proc `[]`*(self: Array; idx: int): Variant {.inline.} =
69 | newVariant(self.godotArray[idx.cint])
70 |
71 | proc add*(self: Array; value: Variant) {.inline.} =
72 | self.godotArray.add(value.godotVariant[])
73 |
74 | proc clear*(self: Array) {.inline.} =
75 | self.godotArray.clear()
76 |
77 | proc count*(self: Array; value: Variant): int {.inline.} =
78 | self.godotArray.count(value.godotVariant[]).int
79 |
80 | proc isEmpty*(self: Array): bool {.inline.} =
81 | self.godotArray.isEmpty()
82 |
83 | proc erase*(self: Array; value: Variant) {.inline.} =
84 | self.godotArray.erase(value.godotVariant[])
85 |
86 | proc first*(self: Array): Variant {.inline.} =
87 | newVariant(self.godotArray.first())
88 |
89 | proc last*(self: Array): Variant {.inline.} =
90 | newVariant(self.godotArray.last())
91 |
92 | proc find*(self: Array; what: Variant; f: int): int {.inline.} =
93 | self.godotArray.find(what.godotVariant[], f.cint).int
94 |
95 | proc findLast*(self: Array; what: Variant): int {.inline.} =
96 | self.godotArray.findLast(what.godotVariant[]).int
97 |
98 | proc contains*(self: Array; value: Variant): bool {.inline.} =
99 | self.godotArray.contains(value.godotVariant[])
100 |
101 | proc hash*(self: Array): Hash {.inline.} =
102 | hash(self.godotArray.godotHash())
103 |
104 | proc insert*(self: Array; pos: int; value: Variant) {.inline.} =
105 | self.godotArray.insert(pos.cint, value.godotVariant[])
106 |
107 | proc reverse*(self: Array) {.inline.} =
108 | self.godotArray.reverse()
109 |
110 | proc popLast*(self: Array): Variant {.inline.} =
111 | newVariant(self.godotArray.popLast())
112 |
113 | proc popFirst*(self: Array): Variant {.inline.} =
114 | newVariant(self.godotArray.popFirst())
115 |
116 | proc addLast*(self: Array; value: Variant) {.inline.} =
117 | self.godotArray.addLast(value.godotVariant[])
118 |
119 | proc addFirst*(self: Array; value: Variant) {.inline.} =
120 | self.godotArray.addFirst(value.godotVariant[])
121 |
122 | proc delete*(self: Array; idx: int) {.inline.} =
123 | self.godotArray.delete(idx.cint)
124 |
125 | proc setLen*(self: Array; size: int) {.inline.} =
126 | self.godotArray.setLen(size.cint)
127 |
128 | proc rfind*(self: Array; what: Variant; fromIdx: int): int {.inline.} =
129 | self.godotArray.rfind(what.godotVariant[], fromIdx.cint).int
130 |
131 | proc len*(self: Array): int {.inline.} =
132 | self.godotArray.len.int
133 |
134 | proc sort*(self: Array) {.inline.} =
135 | self.godotArray.sort()
136 |
137 | iterator items*(self: Array): Variant =
138 | for i in 0..= (b.position.x + b.size.x):
31 | return false
32 | if a.position.x + a.size.x <= b.position.x:
33 | return false
34 | if a.position.y >= (b.position.y + b.size.y):
35 | return false
36 | if a.position.y + a.size.y <= b.position.y:
37 | return false
38 | result = true
39 |
40 | proc distanceTo*(self: Rect2, p: Vector2): float32 {.noinit.} =
41 | var inside = true
42 | if p.x < self.position.x:
43 | let d = self.position.x - p.x
44 | result = d
45 | inside = false
46 | if p.y < self.position.y:
47 | let d = self.position.y - p.y
48 | result = if inside: d else: min(result, d)
49 | inside = false
50 | if p.x >= (self.position.x + self.size.x):
51 | let d = p.x - (self.position.x + self.size.x)
52 | result = if inside: d else: min(result, d)
53 | inside = false
54 | if p.y >= (self.position.y + self.size.y):
55 | let d = p.y - (self.position.y + self.size.y)
56 | result = if inside: d else: min(result, d)
57 | inside = false
58 |
59 | if inside:
60 | result = 0'f32
61 |
62 | proc encloses*(a, b: Rect2): bool {.inline, noinit.} =
63 | b.position.x >= a.position.x and b.position.y >= a.position.y and
64 | (b.position.x + b.size.x) < (a.position.x + a.size.x) and
65 | (b.position.y + b.size.y) < (a.position.y + a.size.y)
66 |
67 | proc hasNoArea*(self: Rect2): bool {.inline, noinit.} =
68 | self.size.x <= 0 or self.size.y <= 0
69 |
70 | proc clip*(self, b: Rect2): Rect2 {.inline, noinit.} =
71 | if not self.intersects(b):
72 | return initRect2()
73 |
74 | result = self
75 |
76 | result.position.x = max(b.position.x, self.position.x)
77 | result.position.y = max(b.position.y, self.position.y)
78 |
79 | let bEnd = b.position + b.size
80 | let selfEnd = self.position + self.size
81 |
82 | result.size.x = min(bEnd.x, selfEnd.x) - result.position.x
83 | result.size.y = min(bEnd.y, selfEnd.y) - result.position.y
84 |
85 | proc merge*(self, b: Rect2): Rect2 {.inline, noinit.} =
86 | result.position.x = min(b.position.x, self.position.x)
87 | result.position.y = min(b.position.y, self.position.y)
88 |
89 | result.size.x = max(b.position.x + b.size.x, self.position.x + self.size.x)
90 | result.size.y = max(b.position.y + b.size.y, self.position.y + self.size.y)
91 | result.size -= result.position
92 |
93 | proc contains*(self: Rect2; point: Vector2): bool {.inline, noinit.} =
94 | if point.x < self.position.x:
95 | return false
96 | if point.y < self.position.y:
97 | return false
98 |
99 | if point.x >= self.position.x + self.size.x:
100 | return false
101 | if point.y >= self.position.y + self.size.y:
102 | return false
103 |
104 | result = true
105 |
106 | proc grow*(self: Rect2; by: float32): Rect2 {.inline, noinit.} =
107 | ## Returns Rect2 enlarged by the specified size in every direction.
108 | result = self
109 |
110 | result.position.x -= by
111 | result.position.y -= by
112 |
113 | result.size.x += by * 2
114 | result.size.y += by * 2
115 |
116 | proc growIndividual*(self: Rect2, left, top: float32,
117 | right, bottom: float32): Rect2 {.inline, noinit.} =
118 | result = self
119 | result.position.x -= left
120 | result.position.y -= top
121 | result.size.x += left + right
122 | result.size.y += top + bottom
123 |
124 | proc expandTo*(self: var Rect2, to: Vector2) {.inline.} =
125 | var startPoint = self.position
126 | var endPoint = self.position + self.size
127 |
128 | if to.x < startPoint.x:
129 | startPoint.x = to.x
130 | if to.y < startPoint.y:
131 | startPoint.y = to.y
132 |
133 | if to.x > endPoint.x:
134 | endPoint.x = to.x
135 | if to.y > endPoint.y:
136 | endPoint.y = to.y
137 |
138 | self.position = startPoint
139 | self.size = endPoint - startPoint
140 |
141 | proc expand*(self: Rect2; to: Vector2): Rect2 {.inline, noinit.} =
142 | result = self
143 | result.expandTo(to)
144 |
145 | proc abs*(self: Rect2): Rect2 {.inline, noinit.} =
146 | Rect2(position: vec2(self.position.x + min(self.size.x, 0'f32),
147 | self.position.y + min(self.size.y, 0'f32)),
148 | size: abs(self.size))
149 |
150 | proc `==`*(a, b: Rect2): bool {.inline, noinit.} =
151 | a.position == b.position and a.size == b.size
152 |
153 | {.pop.} # stackTrace: off
--------------------------------------------------------------------------------
/godot/godotinternal.nim:
--------------------------------------------------------------------------------
1 | # Copyright 2018 Xored Software, Inc.
2 |
3 | import internal/godotinternaltypes, internal/godotarrays,
4 | internal/godotnodepaths, internal/godotpoolarrays, internal/godotstrings,
5 | internal/godotvariants, internal/godotdictionaries
6 |
7 | import gdnativeapi
8 | export godotinternaltypes, godotarrays, godotnodepaths, godotpoolarrays,
9 | godotstrings, godotvariants, godotdictionaries
10 |
11 | proc getMethod*(className: cstring;
12 | methodName: cstring): ptr GodotMethodBind {.inline.} =
13 | getGDNativeAPI().methodBindGetMethod(className, methodName)
14 |
15 | proc ptrCall*(methodBind: ptr GodotMethodBind;
16 | instance: ptr GodotObject;
17 | args: ptr array[MAX_ARG_COUNT, pointer];
18 | ret: pointer) {.inline.} =
19 | getGDNativeAPI().methodBindPtrCall(methodBind, instance, args, ret)
20 |
21 | proc call*(methodBind: ptr GodotMethodBind;
22 | instance: ptr GodotObject;
23 | args: ptr array[MAX_ARG_COUNT, ptr GodotVariant]; argCount: cint;
24 | callError: var VariantCallError): GodotVariant {.inline.} =
25 | getGDNativeAPI().methodBindCall(
26 | methodBind, instance, args, argCount, callError)
27 |
28 | proc nativeScriptRegisterClass*(libHandle: pointer; name, base: cstring;
29 | createFunc: GodotInstanceCreateFunc;
30 | destroyFunc: GodotInstanceDestroyFunc)
31 | {.inline.} =
32 | getGDNativeAPI().nativeScriptRegisterClass(
33 | libHandle, name, base, createFunc, destroyFunc)
34 |
35 | proc nativeScriptRegisterToolClass*(libHandle: pointer; name, base: cstring;
36 | createFunc: GodotInstanceCreateFunc;
37 | destroyFunc: GodotInstanceDestroyFunc)
38 | {.inline.} =
39 | getGDNativeAPI().nativeScriptRegisterToolClass(
40 | libHandle, name, base, createFunc, destroyFunc)
41 |
42 | proc nativeScriptRegisterMethod*(libHandle: pointer;
43 | name: cstring; function_name: cstring;
44 | attr: GodotMethodAttributes;
45 | meth: GodotInstanceMethod) {.inline.} =
46 | getGDNativeAPI().nativeScriptRegisterMethod(
47 | libHandle, name, functionName, attr, meth)
48 |
49 | proc nativeScriptRegisterProperty*(libHandle: pointer;
50 | name, path: cstring;
51 | attr: ptr GodotPropertyAttributes;
52 | setFunc: GodotPropertySetFunc;
53 | getFunc: GodotPropertyGetFunc) {.inline.} =
54 | getGDNativeAPI().nativeScriptRegisterProperty(
55 | libHandle, name, path, attr, setFunc, getFunc)
56 |
57 | proc nativeScriptRegisterSignal*(libHandle: pointer; name: cstring;
58 | signal: GodotSignal) {.inline.} =
59 | getGDNativeAPI().nativeScriptRegisterSignal(libHandle, name, signal)
60 |
61 | proc getUserdata*(instance: ptr GodotObject): pointer {.inline.} =
62 | getGDNativeAPI().nativeScriptGetUserdata(instance)
63 |
64 | proc getClassConstructor*(className: cstring): GodotClassConstructor
65 | {.inline.} =
66 | getGDNativeAPI().getClassConstructor(className)
67 |
68 | proc deinit*(o: ptr GodotObject) {.inline.} =
69 | getGDNativeAPI().objectDestroy(o)
70 |
71 | # print using Godot's error handler list
72 |
73 | proc godotPrintError*(description, function, file: cstring;
74 | line: cint) {.inline.} =
75 | getGDNativeAPI().printError(description, function, file, line)
76 |
77 | proc godotPrintWarning*(description, function, file: cstring;
78 | line: cint) {.inline.} =
79 | getGDNativeAPI().printWarning(description, function, file, line)
80 |
81 | proc godotPrint*(message: GodotString) {.inline.} =
82 | getGDNativeAPI().print(message)
83 |
84 | var getClassMethodBind: ptr GodotMethodBind
85 | proc getClassName*(o: ptr GodotObject): string =
86 | if getClassMethodBind.isNil:
87 | getClassMethodBind = getMethod(cstring"Object", cstring"get_class")
88 | var ret: GodotString
89 | getClassMethodBind.ptrCall(o, nil, addr ret)
90 | result = $ret
91 | deinit(ret)
92 | if result.len > 2 and result[^2] == 'S' and result[^1] == 'W':
93 | # There are physics type not known by ClassDB
94 | result = result[0..result.len-3]
95 |
96 | proc getClassNameRaw*(o: ptr GodotObject): GodotString =
97 | if getClassMethodBind.isNil:
98 | getClassMethodBind = getMethod(cstring"Object", cstring"get_class")
99 | getClassMethodBind.ptrCall(o, nil, addr result)
100 |
101 | proc getGodotSingleton*(name: cstring): ptr GodotObject {.inline.} =
102 | getGDNativeAPI().globalGetSingleton(name)
103 |
104 | # System Functions
105 |
106 | proc godotAlloc*(bytes: cint): pointer {.inline.} =
107 | ## Allocates the specified number of bytes.
108 | ## Using this instead of stdlib proc will help Godot track how much memory
109 | ## is in use in debug mode.
110 | getGDNativeAPI().alloc(bytes)
111 |
112 | proc godotRealloc*(p: pointer; bytes: cint): pointer {.inline.} =
113 | ## Reallocates the pointer for the specified number of bytes.
114 | ## Using this instead of stdlib proc will help Godot track how much memory
115 | ## is in use in debug mode.
116 | getGDNativeAPI().realloc(p, bytes)
117 |
118 | proc godotFree*(p: pointer) {.inline.} =
119 | ## Frees the memory pointed to by the pointer.
120 | ## Using this instead of stdlib proc will help Godot track how much memory
121 | ## is in use in debug mode.
122 | getGDNativeAPI().free(p)
123 |
--------------------------------------------------------------------------------
/docs/docbuild.nim:
--------------------------------------------------------------------------------
1 | # Copyright 2018 Xored Software, Inc.
2 |
3 | import threadpool, os, osproc, strutils, sequtils, pegs
4 |
5 | import "../godot/godotapigen.nim"
6 |
7 | const dirs = ["godot"/"core", "godot"/"internal", "godot"/"nim"]
8 | const files = ["godot"/"godotapigen.nim", "godot"/"godotinternal.nim",
9 | "godot"/"godot.nim"]
10 | const indexFile = "docs"/"index.rst"
11 | const gitHubUrl = "https://github.com/pragmagic/godot-nim"
12 |
13 | proc outName(outDir, file: string): string =
14 | outDir / file.extractFilename().changeFileExt("html")
15 |
16 | template quoted(s: string): string =
17 | ('"' & s & '"')
18 |
19 | proc execOrFail(cmd: string) =
20 | echo "[exec] " & cmd
21 | let ret = execShellCmd(cmd)
22 | if ret != 0:
23 | raise newException(
24 | Exception, "Command quit with exit code " & $ret & ": " & cmd)
25 |
26 | template withDir(dir: string, body: typed) =
27 | let curDir = getCurrentDir()
28 | setCurrentDir(dir)
29 | try:
30 | body
31 | finally:
32 | setCurrentDir(curDir)
33 |
34 | iterator walkDirRec(dir: string, filter: set[PathComponent],
35 | extensions: openarray[string]): string =
36 | for file in walkDirRec(dir, filter):
37 | if not extensions.anyIt(file.endsWith(it)): continue
38 | yield file
39 |
40 | proc genApiFiles(targetDir, godotBin: string) =
41 | let jsonFile = targetDir / "api.json"
42 | try:
43 | execOrFail(quoted(godotBin) &
44 | " --gdnative-generate-json-api " & quoted(jsonFile))
45 | except:
46 | # this fails unstably even if api.json is created successfully
47 | discard
48 | if not fileExists(jsonFile):
49 | raise newException(Exception, "Failed to generate Godot API wrappers")
50 |
51 | genApi(targetDir, jsonFile)
52 |
53 | writeFile(targetDir / "nim.cfg", "path=\"$projectdir/../../godot\"")
54 |
55 | proc extractVersion(nimbleFile: string): string =
56 | let contents = readFile(nimbleFile)
57 | var matches: array[1, string]
58 | doAssert match(contents, peg"""'version' \s* '=' \s* '"' {@} '"' """, matches)
59 | result = matches[0]
60 |
61 | proc fixupHrefs(file: string) =
62 | var contents = readFile(file)
63 | contents = contents.replacef(
64 | peg"""'href="' ('internal'/'core'/'nim') '/' {@} '"' """,
65 | "href=\"$#\"")
66 | if file.contains("godotapi"):
67 | contents = contents.replacef(
68 | peg"""'href="' {('godotinternal' / 'godot') '.html"'} """,
69 | "href=\"../$#")
70 | writeFile(file, contents)
71 |
72 | proc getGitHash(): string =
73 | result = execProcess("git rev-parse HEAD")
74 | if result.len > 0:
75 | result = result.replace("\L", "").replace("\r", "")
76 |
77 | proc buildDocs*(outDir, godotNimDir, godotBin: string) =
78 | removeDir(outDir)
79 | createDir(outDir)
80 | let outDirAbs = expandFilename(outDir)
81 | let godotBinAbs = expandFilename(godotBin)
82 |
83 | setCurrentDir(godotNimDir)
84 |
85 | let godotNimVersion = extractVersion("godot.nimble")
86 | putEnv("godotnimversion", godotNimVersion)
87 | putEnv("godotnimgithub", gitHubUrl)
88 | let gitCommit = getGitHash()
89 |
90 | var allNimFiles = newSeq[string]()
91 | allNimFiles.add(files)
92 | for dir in dirs:
93 | for file in walkDirRec(dir, {pcFile, pcDir}, [".nim"]):
94 | allNimFiles.add(file)
95 | for file in allNimFiles:
96 | spawn execOrFail(
97 | "nim doc -d:useRealtimeGc --path:godot -o:" &
98 | quoted(outName(outDirAbs, file)) &
99 | " --git.url:" & quoted(gitHubUrl) &
100 | " --git.commit:" & quoted(gitCommit) &
101 | ' ' & quoted(file))
102 |
103 | let godotApiFolder = outDirAbs / "godotapi"
104 | createDir(godotApiFolder)
105 | genApiFiles(godotApiFolder, godotBinAbs)
106 | for file in walkDirRec(godotApiFolder, {pcFile, pcDir}, [".nim"]):
107 | spawn execOrFail("nim doc -d:useRealtimeGc --path:godot -o:" &
108 | quoted(outName(godotApiFolder, file)) & ' ' & quoted(file))
109 |
110 | sync()
111 |
112 | var gitHash: string
113 | withDir(godotBinAbs.parentDir()):
114 | gitHash = getGitHash()
115 | if gitHash.len == 0:
116 | raise newException(Exception,
117 | "Godot executable is not under Git repository")
118 |
119 | var indexContent = readFile(indexFile)
120 | var apiList = newStringOfCap(4096)
121 | for file in walkDirRec(godotApiFolder, {pcFile, pcDir}):
122 | if not file.endsWith(".html"):
123 | removeFile(file)
124 | else:
125 | let moduleHtml = file.extractFileName()
126 | let moduleName = moduleHtml.changeFileExt("")
127 | apiList.add("* `" & moduleName & " `_\L")
128 | indexContent = indexContent.replace("$GODOTAPI_CHANGESET_HASH", gitHash).
129 | replace("$AUTO_GENERATED_GODOTAPI_LIST", apiList).
130 | replace("$GODOTNIM_GITHUB_URL", gitHubUrl)
131 |
132 | let tmpRst = outDirAbs/"index.rst"
133 | writeFile(tmpRst, indexContent)
134 | try:
135 | execOrFail("nim rst2html -o:" & quoted(outName(outDirAbs, tmpRst)) &
136 | ' ' & quoted(tmpRst))
137 | finally:
138 | removeFile(tmpRst)
139 |
140 | for file in walkDirRec(outDir, {pcFile, pcDir}, [".html"]):
141 | spawn fixupHrefs(file)
142 |
143 | sync()
144 |
145 | when isMainModule:
146 | const outDir = "docgen"
147 |
148 | if not fileExists("godot.nimble"):
149 | echo "Must be executed from godot-nim root dir"
150 | quit(-1)
151 |
152 | let godotBin = getEnv("GODOT_BIN")
153 | if godotBin.len == 0:
154 | echo "GODOT_BIN environment variable must point to Godot executable"
155 | quit(-1)
156 |
157 | try:
158 | buildDocs(outDir, getCurrentDir(), godotBin)
159 | except:
160 | echo getCurrentExceptionMsg()
161 | quit(-1)
162 |
--------------------------------------------------------------------------------
/godot/internal/godotarrays.nim:
--------------------------------------------------------------------------------
1 | # Copyright (c) 2018 Xored Software, Inc.
2 |
3 | import godotinternaltypes, gdnativeapi, core/godotcoretypes
4 |
5 | proc len*(self: GodotArray): cint {.inline.} =
6 | getGDNativeAPI().arraySize(self)
7 |
8 | import hashes
9 |
10 | proc initGodotArray*(dest: var GodotArray) {.inline.} =
11 | getGDNativeAPI().arrayNew(dest)
12 |
13 | proc initGodotArray*(dest: var GodotArray;
14 | pca: GodotPoolColorArray) {.inline.} =
15 | getGDNativeAPI().arrayNewPoolColorArray(dest, pca)
16 |
17 | proc initGodotArray*(dest: var GodotArray;
18 | pv3a: GodotPoolVector3Array) {.inline.} =
19 | getGDNativeAPI().arrayNewPoolVector3Array(dest, pv3a)
20 |
21 | proc initGodotArray*(dest: var GodotArray;
22 | pv2a: GodotPoolVector2Array) {.inline.} =
23 | getGDNativeAPI().arrayNewPoolVector2Array(dest, pv2a)
24 |
25 | proc initGodotArray*(dest: var GodotArray;
26 | psa: GodotPoolStringArray) {.inline.} =
27 | getGDNativeAPI().arrayNewPoolStringArray(dest, psa)
28 |
29 | proc initGodotArray*(dest: var GodotArray;
30 | pra: GodotPoolRealArray) {.inline.} =
31 | getGDNativeAPI().arrayNewPoolRealArray(dest, pra)
32 |
33 | proc initGodotArray*(dest: var GodotArray;
34 | pia: GodotPoolIntArray) {.inline.} =
35 | getGDNativeAPI().arrayNewPoolIntArray(dest, pia)
36 |
37 | proc initGodotArray*(dest: var GodotArray;
38 | pba: GodotPoolByteArray) {.inline.} =
39 | getGDNativeAPI().arrayNewPoolByteArray(dest, pba)
40 |
41 | proc initGodotArray*(dest: var GodotArray; src: GodotArray) {.inline.} =
42 | getGDNativeAPI().arrayNewCopy(dest, src)
43 |
44 | proc deinit*(self: var GodotArray) {.inline.} =
45 | getGDNativeAPI().arrayDestroy(self)
46 |
47 | proc `[]=`*(self: var GodotArray; idx: cint; value: GodotVariant) {.inline.} =
48 | getGDNativeAPI().arraySet(self, idx, value)
49 |
50 | proc `[]`*(self: GodotArray; idx: cint): GodotVariant {.inline.} =
51 | getGDNativeAPI().arrayGet(self, idx)
52 |
53 | proc mget*(self: var GodotArray; idx: cint): ptr GodotVariant {.inline.} =
54 | getGDNativeAPI().arrayOperatorIndex(self, idx)
55 |
56 | proc add*(self: var GodotArray; value: GodotVariant) {.inline.} =
57 | getGDNativeAPI().arrayPushBack(self, value)
58 |
59 | proc clear*(self: var GodotArray) {.inline.} =
60 | getGDNativeAPI().arrayClear(self)
61 |
62 | proc count*(self: GodotArray; value: GodotVariant): cint {.inline.} =
63 | getGDNativeAPI().arrayCount(self, value)
64 |
65 | proc isEmpty*(self: GodotArray): bool {.inline.} =
66 | getGDNativeAPI().arrayEmpty(self)
67 |
68 | proc erase*(self: var GodotArray; value: GodotVariant) {.inline.} =
69 | getGDNativeAPI().arrayErase(self, value)
70 |
71 | proc first*(self: GodotArray): GodotVariant {.inline.} =
72 | getGDNativeAPI().arrayFront(self)
73 |
74 | proc last*(self: GodotArray): GodotVariant {.inline.} =
75 | getGDNativeAPI().arrayBack(self)
76 |
77 | proc find*(self: GodotArray; what: GodotVariant;
78 | fromIdx: cint): cint {.inline.} =
79 | getGDNativeAPI().arrayFind(self, what, fromIdx)
80 |
81 | proc findLast*(self: GodotArray; what: GodotVariant): cint {.inline.} =
82 | getGDNativeAPI().arrayFindLast(self, what)
83 |
84 | proc contains*(self: GodotArray; value: GodotVariant): bool {.inline.} =
85 | getGDNativeAPI().arrayHas(self, value)
86 |
87 | proc godotHash*(self: GodotArray): cint {.inline.} =
88 | getGDNativeAPI().arrayHash(self)
89 |
90 | proc hash*(self: GodotArray): Hash {.inline.} =
91 | hash(godotHash(self))
92 |
93 | proc insert*(self: var GodotArray; pos: cint;
94 | value: GodotVariant): Error {.discardable, inline.} =
95 | getGDNativeAPI().arrayInsert(self, pos, value)
96 |
97 | proc reverse*(self: var GodotArray) {.inline.} =
98 | getGDNativeAPI().arrayInvert(self)
99 |
100 | proc popLast*(self: var GodotArray): GodotVariant {.inline.} =
101 | getGDNativeAPI().arrayPopBack(self)
102 |
103 | proc popFirst*(self: var GodotArray): GodotVariant {.inline.} =
104 | getGDNativeAPI().arrayPopFront(self)
105 |
106 | proc addLast*(self: var GodotArray; value: GodotVariant) {.inline.} =
107 | getGDNativeAPI().arrayPushBack(self, value)
108 |
109 | proc addFirst*(self: var GodotArray; value: GodotVariant) {.inline.} =
110 | getGDNativeAPI().arrayPushFront(self, value)
111 |
112 | proc delete*(self: var GodotArray; idx: cint) {.inline.} =
113 | getGDNativeAPI().arrayRemove(self, idx)
114 |
115 | proc setLen*(self: var GodotArray; size: cint) {.inline.} =
116 | getGDNativeAPI().arrayResize(self, size)
117 |
118 | proc rfind*(self: GodotArray; what: GodotVariant;
119 | fromIdx: cint): cint {.inline.} =
120 | getGDNativeAPI().arrayRFind(self, what, fromIdx)
121 |
122 | proc sort*(self: var GodotArray) {.inline.} =
123 | getGDNativeAPI().arraySort(self)
124 |
125 | proc sortCustom*(self: var GodotArray; obj: ptr GodotObject;
126 | funcName: GodotString) {.inline.} =
127 | getGDNativeAPI().arraySortCustom(self, obj, funcName)
128 |
129 | proc binarySearch*(self: var GodotArray, val: ptr GodotVariant,
130 | before: bool) {.inline.} =
131 | getGDNativeAPI().arrayBSearch(self, val, before)
132 |
133 | proc binarySearchCustom*(self: var GodotArray, val: ptr GodotVariant,
134 | obj: ptr GodotObject, funcName: GodotString,
135 | before: bool) {.inline.} =
136 | getGDNativeAPI().arrayBSearchCustom(self, val, obj, funcName, before)
137 |
138 | iterator items*(self: GodotArray): GodotVariant =
139 | for i in 0.cint.. 1:
160 | result.add(", ")
161 | result.add($item)
162 | result.add(']')
163 |
--------------------------------------------------------------------------------
/godot/core/poolarrays.nim:
--------------------------------------------------------------------------------
1 | # Copyright 2018 Xored Software, Inc.
2 |
3 | import hashes
4 |
5 | import godotcoretypes
6 | import internal/godotinternaltypes, internal/godotpoolarrays,
7 | internal/godotstrings
8 | import vector2, vector3, colors
9 |
10 | template definePoolArrayBase(T, GodotT, DataT, fieldName, newProcName,
11 | initProcName) =
12 | type
13 | T* = ref object
14 | fieldName: GodotT
15 |
16 | proc poolArrayFinalizer(arr: T) =
17 | arr.fieldName.deinit()
18 |
19 | proc newProcName*(): T {.inline.} =
20 | new(result, poolArrayFinalizer)
21 | initProcName(result.fieldName)
22 |
23 | proc fieldName*(self: T): ptr GodotT {.inline.} =
24 | ## WARNING: do not keep the returned value for longer than the lifetime of
25 | ## the array.
26 | addr self.fieldName
27 |
28 | proc newProcName*(arr: GodotT): T {.inline.} =
29 | new(result, poolArrayFinalizer)
30 | result.fieldName = arr
31 |
32 | proc hash*(arr: T): Hash =
33 | for item in arr.fieldName.items():
34 | result = result !&
35 | (when type(item) is GodotString: ($item).hash() else: item.hash())
36 | result = !$result
37 |
38 | definePoolArrayBase(PoolByteArray, GodotPoolByteArray, uint8,
39 | godotPoolByteArray, newPoolByteArray,
40 | initGodotPoolByteArray)
41 | definePoolArrayBase(PoolIntArray, GodotPoolIntArray, cint,
42 | godotPoolIntArray, newPoolIntArray,
43 | initGodotPoolIntArray)
44 | definePoolArrayBase(PoolRealArray, GodotPoolRealArray, float32,
45 | godotPoolRealArray, newPoolRealArray,
46 | initGodotPoolRealArray)
47 | definePoolArrayBase(PoolVector2Array, GodotPoolVector2Array, Vector2,
48 | godotPoolVector2Array, newPoolVector2Array,
49 | initGodotPoolVector2Array)
50 | definePoolArrayBase(PoolVector3Array, GodotPoolVector3Array, Vector3,
51 | godotPoolVector3Array, newPoolVector3Array,
52 | initGodotPoolVector3Array)
53 | definePoolArrayBase(PoolColorArray, GodotPoolColorArray, Color,
54 | godotPoolColorArray, newPoolColorArray,
55 | initGodotPoolColorArray)
56 | definePoolArrayBase(PoolStringArray, GodotPoolStringArray, string,
57 | godotPoolStringArray, newPoolStringArray,
58 | initGodotPoolStringArray)
59 |
60 | import arrays
61 |
62 | template definePoolArray(T, GodotT, DataT, fieldName, newProcName, initProcName;
63 | noData = false) =
64 |
65 | proc newProcName*(arr: Array): T {.inline.} =
66 | new(result, poolArrayFinalizer)
67 | initProcName(result.fieldName, arr.godotArray[])
68 |
69 | proc add*(self: T; arr: T) {.inline.} =
70 | self.fieldName.add(arr.fieldName)
71 |
72 | proc delete*(self: T; idx: int) {.inline.} =
73 | self.fieldName.delete(idx.cint)
74 |
75 | proc reverse*(self: T) {.inline.} =
76 | self.fieldName.reverse()
77 |
78 | proc setLen*(self: T; size: int) {.inline.} =
79 | self.fieldName.setLen(size.cint)
80 |
81 | proc len*(self: T): int {.inline.} =
82 | self.fieldName.len.int
83 |
84 | proc subarray*(self: T, idxFrom, idxTo: int): T {.inline.} =
85 | ## Indexes are inclusive, negative values count from the end of the array.
86 | assert(idxFrom >= low(cint) and idxFrom <= high(cint) and
87 | idxTo >= low(cint) and idxTo <= high(cint))
88 | newProcName(self.fieldName.subarray(idxFrom.cint, idxTo.cint))
89 |
90 | when not noData:
91 | proc add*(self: T; data: DataT) {.inline.} =
92 | self.fieldName.add(data)
93 |
94 | proc insert*(self: T; idx: int; data: DataT): Error {.inline.} =
95 | self.fieldName.insert(idx.cint, data)
96 |
97 | proc `[]=`*(self: T; idx: int; data: DataT) {.inline.} =
98 | self.fieldName[idx.cint] = data
99 |
100 | proc `[]`*(self: T; idx: int): DataT {.inline.} =
101 | self.fieldName[idx.cint]
102 |
103 | iterator items*(arr: T): DataT =
104 | for item in arr.fieldName.items:
105 | yield item
106 |
107 | iterator pairs*(arr: T): tuple[key: int, val: DataT] =
108 | for pair in arr.fieldName.pairs:
109 | yield (pair[0].int, pair[1])
110 |
111 | iterator mitems*(arr: T): var DataT =
112 | for item in arr.fieldName.mitems:
113 | yield item
114 |
115 | iterator mpairs*(arr: T): tuple[key: int, val: var DataT] =
116 | for pair in arr.fieldName.mpairs:
117 | yield (pair[0].int, pair[1])
118 |
119 | definePoolArray(PoolByteArray, GodotPoolByteArray, uint8,
120 | godotPoolByteArray, newPoolByteArray,
121 | initGodotPoolByteArray)
122 | definePoolArray(PoolIntArray, GodotPoolIntArray, cint,
123 | godotPoolIntArray, newPoolIntArray,
124 | initGodotPoolIntArray)
125 | definePoolArray(PoolRealArray, GodotPoolRealArray, float32,
126 | godotPoolRealArray, newPoolRealArray,
127 | initGodotPoolRealArray)
128 | definePoolArray(PoolVector2Array, GodotPoolVector2Array, Vector2,
129 | godotPoolVector2Array, newPoolVector2Array,
130 | initGodotPoolVector2Array)
131 | definePoolArray(PoolVector3Array, GodotPoolVector3Array, Vector3,
132 | godotPoolVector3Array, newPoolVector3Array,
133 | initGodotPoolVector3Array)
134 | definePoolArray(PoolColorArray, GodotPoolColorArray, Color,
135 | godotPoolColorArray, newPoolColorArray,
136 | initGodotPoolColorArray)
137 | definePoolArray(PoolStringArray, GodotPoolStringArray, string,
138 | godotPoolStringArray, newPoolStringArray,
139 | initGodotPoolStringArray, true)
140 |
141 | proc add*(self: PoolStringArray; data: string) =
142 | var s = data.toGodotString()
143 | self.godotPoolStringArray.add(s)
144 | s.deinit()
145 |
146 | proc insert*(self: PoolStringArray; idx: int; data: string): Error =
147 | var s = data.toGodotString()
148 | result = self.godotPoolStringArray.insert(idx.cint, s)
149 | s.deinit()
150 |
151 | proc `[]=`*(self: PoolStringArray; idx: int; data: string) =
152 | var s = data.toGodotString()
153 | self.godotPoolStringArray[idx.cint] = s
154 | s.deinit()
155 |
156 | proc `[]`*(self: PoolStringArray; idx: int): string =
157 | var s = self.godotPoolStringArray[idx.cint]
158 | result = $s
159 | s.deinit()
160 |
161 | iterator items*(arr: PoolStringArray): string =
162 | for i in 0..`*(self, other: Vector2): bool {.inline, noinit.} =
78 | if self.x == other.x:
79 | self.y > other.y
80 | else:
81 | self.x > other.x
82 |
83 | proc `-`*(self: Vector2): Vector2 {.inline, noinit.} =
84 | Vector2(x: -self.x, y: -self.y)
85 |
86 | proc length*(self: Vector2): float32 {.inline, noinit.} =
87 | sqrt(self.x * self.x + self.y * self.y)
88 |
89 | proc lengthSquared*(self: Vector2): float32 {.inline, noinit.} =
90 | self.x * self.x + self.y * self.y
91 |
92 | proc normalize*(self: var Vector2) {.inline.} =
93 | var len = self.x * self.x + self.y * self.y
94 | if len != 0:
95 | len = sqrt(len)
96 | self.x /= len
97 | self.y /= len
98 |
99 | proc normalized*(self: Vector2): Vector2 {.inline, noinit.} =
100 | result = self
101 | result.normalize()
102 |
103 | proc angle*(self: Vector2): float32 {.inline, noinit.} =
104 | arctan2(self.y, self.x)
105 |
106 | proc isNormalized*(self: Vector2): bool {.inline, noinit.} =
107 | isEqualApprox(self.lengthSquared(), 1.0)
108 |
109 | proc distanceTo*(self, to: Vector2): float32 {.inline, noinit.} =
110 | sqrt((self.x - to.x) * (self.x - to.x) + (self.y - to.y) * (self.y - to.y))
111 |
112 | proc distanceSquaredTo*(self, to: Vector2): float32 {.inline, noinit.} =
113 | (self.x - to.x) * (self.x - to.x) + (self.y - to.y) * (self.y - to.y)
114 |
115 | proc dot*(a, b: Vector2): float32 {.inline, noinit.} =
116 | a.x * b.x + a.y * b.y
117 |
118 | proc cross*(a, b: Vector2): float32 {.inline, noinit.} =
119 | a.x * b.y - a.y * b.x
120 |
121 | proc cross*(self: Vector2, scalar: float32): Vector2 {.inline, noinit.} =
122 | Vector2(x: scalar * self.y, y: -scalar * self.x)
123 |
124 | proc angleTo*(self, to: Vector2): float32 {.noinit.} =
125 | arctan2(cross(self, to), dot(self, to))
126 |
127 | proc angleToPoint*(self, to: Vector2): float32 {.inline, noinit.} =
128 | arctan2(self.y - to.y, self.x - to.x)
129 |
130 | proc floor*(self: Vector2): Vector2 {.inline, noinit.} =
131 | Vector2(x: floor(self.x), y: floor(self.y))
132 |
133 | proc planeProject*(self: Vector2, d: float32,
134 | vec: Vector2): Vector2 {.noinit.} =
135 | vec - self * (self.dot(vec) - d)
136 |
137 | proc project*(self, other: Vector2): Vector2 {.noinit.} =
138 | self * (other.dot(self) / self.dot(self))
139 |
140 | proc lerp*(self, b: Vector2; t: float32): Vector2 {.inline, noinit.} =
141 | result = self
142 | result.x += t * (b.x - self.x)
143 | result.y += t * (b.y - self.y)
144 |
145 | proc cubicInterpolate*(self, b, preA, postB: Vector2;
146 | t: float32): Vector2 {.noinit.} =
147 | let p0 = preA
148 | let p1 = self
149 | let p2 = b
150 | let p3 = postB
151 |
152 | let t2 = t * t
153 | let t3 = t2 * t
154 |
155 | result = 0.5'f32 * ((p1 * 2.0'f32)) +
156 | (-p0 + p2) * t +
157 | (2.0 * p0 - 5.0 * p1 + 4 * p2 - p3) * t2 +
158 | (-p0 + 3.0 * p1 - 3.0 * p2 + p3) * t3
159 |
160 | proc setRotation*(self: var Vector2, radians: float32) {.inline, noinit.} =
161 | self.x = cos(radians)
162 | self.y = sin(radians)
163 |
164 | proc rotated*(self: Vector2; phi: float32): Vector2 {.inline, noinit.} =
165 | result.setRotation(phi)
166 | result *= self.length()
167 |
168 | proc tangent*(self: Vector2): Vector2 {.inline, noinit.} =
169 | Vector2(x: self.y, y: -self.x)
170 |
171 | proc snapped*(self: Vector2; by: Vector2): Vector2 {.inline, noinit.} =
172 | Vector2(x: stepify(self.x, by.x), y: stepify(self.y, by.y))
173 |
174 | proc aspect*(self: Vector2): float32 {.inline, noinit.} =
175 | self.x / self.y
176 |
177 | proc slide*(self, n: Vector2): Vector2 {.noinit.} =
178 | when not defined(release):
179 | if not n.isNormalized():
180 | printError("Normal not normalized in slide. " & getStackTrace())
181 | return vec2()
182 | result = self - n * self.dot(n)
183 |
184 | proc reflect*(self, n: Vector2): Vector2 {.noinit.} =
185 | when not defined(release):
186 | if not n.isNormalized():
187 | printError("Normal not normalized in bounce. " & getStackTrace())
188 | return vec2()
189 | result = 2.0 * n * self.dot(n) - self
190 |
191 | proc bounce*(self, n: Vector2): Vector2 {.inline, noinit.} =
192 | -self.reflect(n)
193 |
194 | proc abs*(self: Vector2): Vector2 {.inline, noinit.} =
195 | Vector2(x: abs(self.x), y: abs(self.y))
196 |
197 | proc clamped*(self: Vector2; length: float32): Vector2 {.noinit.} =
198 | let len = self.length()
199 | result = self
200 | if len > 0 and length < len:
201 | result /= len
202 | result *= length
203 |
204 | proc moveToward*(vFrom, to: Vector2, delta: float32): Vector2 =
205 | let
206 | vd = to - vFrom
207 | vLen = vd.length
208 |
209 | if vLen <= delta or vLen < EPSILON:
210 | result = to
211 | else:
212 | result = vFrom + (vd / vLen) * delta
213 |
214 | {.pop.} # stackTrace: off
215 |
--------------------------------------------------------------------------------
/godot/core/vector3.nim:
--------------------------------------------------------------------------------
1 | # Copyright (c) 2018 Xored Software, Inc.
2 |
3 | import math, hashes
4 | import godotbase, godotcoretypes
5 |
6 | const EPSILON = 0.00001'f32
7 |
8 | {.push stackTrace: off.}
9 |
10 | proc vec3*(): Vector3 {.inline.} =
11 | Vector3()
12 |
13 | proc vec3*(x, y, z: float32): Vector3 {.inline.} =
14 | Vector3(x: x, y: y, z: z)
15 |
16 | proc `$`*(self: Vector3): string {.inline.} =
17 | result = newStringOfCap(40)
18 | result.add('(')
19 | result.add($self.x)
20 | result.add(", ")
21 | result.add($self.y)
22 | result.add(", ")
23 | result.add($self.z)
24 | result.add(')')
25 |
26 | proc hash*(self: Vector3): Hash {.inline, noinit.} =
27 | !$(self.x.hash() !& self.y.hash() !& self.z.hash())
28 |
29 | proc `+`*(a, b: Vector3): Vector3 {.inline.} =
30 | result.x = a.x + b.x
31 | result.y = a.y + b.y
32 | result.z = a.z + b.z
33 |
34 | proc `+=`*(a: var Vector3, b: Vector3) {.inline.} =
35 | a.x += b.x
36 | a.y += b.y
37 | a.z += b.z
38 |
39 | proc `-`*(a, b: Vector3): Vector3 {.inline.} =
40 | result.x = a.x - b.x
41 | result.y = a.y - b.y
42 | result.z = a.z - b.z
43 |
44 | proc `-=`*(a: var Vector3, b: Vector3) {.inline.} =
45 | a.x -= b.x
46 | a.y -= b.y
47 | a.z -= b.z
48 |
49 | proc `*`*(a, b: Vector3): Vector3 {.inline.} =
50 | result.x = a.x * b.x
51 | result.y = a.y * b.y
52 | result.z = a.z * b.z
53 |
54 | proc `*=`*(a: var Vector3, b: Vector3) {.inline.}=
55 | a.x *= b.x
56 | a.y *= b.y
57 | a.z *= b.z
58 |
59 | proc `*`*(a: Vector3; b: float32): Vector3 {.inline.} =
60 | result.x = a.x * b
61 | result.y = a.y * b
62 | result.z = a.z * b
63 |
64 | proc `*`*(b: float32; a: Vector3): Vector3 {.inline.} =
65 | a * b
66 |
67 | proc `*=`*(a: var Vector3; b: float32) {.inline.} =
68 | a.x *= b
69 | a.y *= b
70 | a.z *= b
71 |
72 | proc `/`*(a, b: Vector3): Vector3 =
73 | result.x = a.x / b.x
74 | result.y = a.y / b.y
75 | result.z = a.z / b.z
76 |
77 | proc `/=`*(a: var Vector3; b: Vector3) {.inline.} =
78 | a.x /= b.x
79 | a.y /= b.y
80 | a.z /= b.z
81 |
82 | proc `/`*(a: Vector3; b: float32): Vector3 =
83 | result.x = a.x / b
84 | result.y = a.y / b
85 | result.z = a.z / b
86 |
87 | proc `/=`*(a: var Vector3; b: float32) {.inline.} =
88 | a.x /= b
89 | a.y /= b
90 | a.z /= b
91 |
92 | proc `==`*(a, b: Vector3): bool {.inline.} =
93 | a.x == b.x and a.y == b.y and a.z == b.z
94 |
95 | proc `<`*(a, b: Vector3): bool =
96 | if a.x == b.x:
97 | if a.y == b.y:
98 | return a.z < b.z
99 | return a.y < b.y
100 | return a.x < b.x
101 |
102 | proc `-`*(self: Vector3): Vector3 =
103 | result.x = -self.x
104 | result.y = -self.y
105 | result.z = -self.z
106 |
107 | proc `[]`*(self: Vector3, idx: range[0..2]): float32 {.inline.} =
108 | cast[array[3, float32]](self)[idx]
109 |
110 | proc `[]`*(self: var Vector3, idx: range[0..2]): var float32 {.inline.} =
111 | cast[ptr array[3, float32]](addr self)[][idx]
112 |
113 | proc `[]=`*(self: var Vector3, idx: range[0..2],
114 | val: float32) {.inline.} =
115 | case idx:
116 | of 0: self.x = val
117 | of 1: self.y = val
118 | of 2: self.z = val
119 |
120 | proc minAxis*(self: Vector3): int {.inline.} =
121 | if self.x < self.y:
122 | if self.x < self.z: 0 else: 2
123 | else:
124 | if self.y < self.z: 1 else: 2
125 |
126 | proc maxAxis*(self: Vector3): int {.inline.} =
127 | if self.x < self.y:
128 | if self.y < self.z: 2 else: 1
129 | else:
130 | if self.x < self.z: 2 else: 0
131 |
132 | proc length*(self: Vector3): float32 {.inline.} =
133 | let x2 = self.x * self.x
134 | let y2 = self.y * self.y
135 | let z2 = self.z * self.z
136 |
137 | result = sqrt(x2 + y2 + z2)
138 |
139 | proc lengthSquared*(self: Vector3): float32 {.inline.} =
140 | let x2 = self.x * self.x
141 | let y2 = self.y * self.y
142 | let z2 = self.z * self.z
143 |
144 | result = x2 + y2 + z2
145 |
146 | proc normalize*(self: var Vector3) {.inline.} =
147 | let len = self.length()
148 | if len == 0:
149 | self.x = 0
150 | self.y = 0
151 | self.z = 0
152 | else:
153 | self.x /= len
154 | self.y /= len
155 | self.z /= len
156 |
157 | proc normalized*(self: Vector3): Vector3 {.inline.} =
158 | result = self
159 | result.normalize()
160 |
161 | proc isNormalized*(self: Vector3): bool {.inline.} =
162 | self.lengthSquared().isEqualApprox(1.0'f32)
163 |
164 | proc zero*(self: var Vector3) {.inline.} =
165 | self.x = 0
166 | self.y = 0
167 | self.z = 0
168 |
169 | proc inverse*(self: Vector3): Vector3 {.inline.} =
170 | vec3(1.0'f32 / self.x, 1.0'f32 / self.y, 1.0'f32 / self.z)
171 |
172 | proc cross*(self, other: Vector3): Vector3 {.inline.} =
173 | vec3(
174 | self.y * other.z - self.z * other.y,
175 | self.z * other.x - self.x * other.z,
176 | self.x * other.y - self.y * other.x)
177 |
178 | proc dot*(self, other: Vector3): float32 {.inline.} =
179 | self.x * other.x + self.y * other.y + self.z * other.z
180 |
181 | proc abs*(self: Vector3): Vector3 {.inline.} =
182 | vec3(abs(self.x), abs(self.y), abs(self.z))
183 |
184 | proc sign*(self: Vector3): Vector3 {.inline.} =
185 | vec3(sign(self.x), sign(self.y), sign(self.z))
186 |
187 | proc floor*(self: Vector3): Vector3 {.inline.} =
188 | vec3(floor(self.x), floor(self.y), floor(self.z))
189 |
190 | proc ceil*(self: Vector3): Vector3 {.inline.} =
191 | vec3(ceil(self.x), ceil(self.y), ceil(self.z))
192 |
193 | proc lerp*(self: Vector3, other: Vector3, t: float32): Vector3 {.inline.} =
194 | vec3(
195 | self.x + t * (other.x - self.x),
196 | self.y + t * (other.y - self.y),
197 | self.z + t * (other.z - self.z)
198 | )
199 |
200 | proc distanceTo*(self, other: Vector3): float32 {.inline.} =
201 | (other - self).length()
202 |
203 | proc distanceSquaredTo*(self, other: Vector3): float32 {.inline.} =
204 | (other - self).lengthSquared()
205 |
206 | proc angleTo*(self, other: Vector3): float32 {.inline.} =
207 | arctan2(self.cross(other).length(), self.dot(other))
208 |
209 | proc slide*(self, n: Vector3): Vector3 {.inline.} =
210 | assert(n.isNormalized())
211 | result = self - n * self.dot(n)
212 |
213 | proc reflect*(self, n: Vector3): Vector3 {.inline.} =
214 | assert(n.isNormalized())
215 | result = 2.0'f32 * n * self.dot(n) - self
216 |
217 | proc bounce*(self, n: Vector3): Vector3 {.inline.} =
218 | -self.reflect(n)
219 |
220 | proc snap*(self: var Vector3, other: Vector3) =
221 | self.x = stepify(self.x, other.x)
222 | self.y = stepify(self.y, other.y)
223 | self.z = stepify(self.z, other.z)
224 |
225 | proc snapped*(self: Vector3, other: Vector3): Vector3 =
226 | result = self
227 | result.snap(other)
228 |
229 | proc cubicInterpolate*(self, b, preA, postB: Vector3;
230 | t: float32): Vector3 =
231 | let p0 = preA
232 | let p1 = self
233 | let p2 = b
234 | let p3 = postB
235 |
236 | let t2 = t * t
237 | let t3 = t2 * t
238 |
239 | result = 0.5 * ((p1 * 2.0) +
240 | (-p0 + p2) * t +
241 | (2.0 * p0 - 5.0 * p1 + 4 * p2 - p3) * t2 +
242 | (-p0 + 3.0 * p1 - 3.0 * p2 + p3) * t3)
243 |
244 | proc moveToward*(vFrom, to: Vector3, delta: float32): Vector3 =
245 | let
246 | vd = to - vFrom
247 | vLen = vd.length
248 |
249 | if vLen <= delta or vLen < EPSILON:
250 | result = to
251 | else:
252 | result = vFrom + (vd / vLen) * delta
253 |
254 | {.pop.} # stackTrace: off
--------------------------------------------------------------------------------
/docs/index.rst:
--------------------------------------------------------------------------------
1 | =============================
2 | Nim bindings for Godot Engine
3 | =============================
4 |
5 | :Author: Ruslan Mustakov
6 | :Version: |godotnimversion|
7 | :GitHub: `$GODOTNIM_GITHUB_URL <$GODOTNIM_GITHUB_URL>`_
8 | :License: MIT
9 |
10 | .. contents::
11 |
12 | ``godot-nim`` library allows to create games on
13 | `Godot Engine `_ with
14 | `Nim programming language `_. Nim is a statically typed
15 | language with an elegant Python-like syntax that compiles to native code.
16 | It is garbage-collected, but its GC supports real-time mode which this library
17 | makes use of. It means the GC will never run during game frames and will use
18 | fixed amount of frame idle time to collect garbage. This leads to no stalls
19 | and close to zero compromise on performance comparing to native languages with
20 | manual memory management.
21 |
22 | If you are not familiar with Nim yet, it is recommended to go through the
23 | `official tutorial `_.
24 |
25 | `VSCode `_ is the recommended editor for
26 | working with Nim code. It is cross-platform and has the excellent
27 | `nim plugin `_
28 | that supports most of the features you would expect from an IDE.
29 | It also has `godot-tools plugin `_
30 | which adds features for editing GDScript and Godot resource files.
31 |
32 |
33 | Getting Started
34 | ===============
35 |
36 | Getting Godot
37 | --------------
38 |
39 | The library requires Godot version 3.0, which you can get here:
40 | https://godotengine.org/download
41 |
42 | Installing Nim
43 | -------------
44 |
45 | The library requires Nim version 0.18.0 or newer, which you can get here:
46 | https://nim-lang.org/install.html
47 |
48 | Make sure you also have ``nimble`` (Nim's package manager) installed.
49 |
50 | Creating Project
51 | ----------------
52 |
53 | The fastest way to set up a Godot-Nim project is to use the existing stub:
54 |
55 | .. code-block:: bash
56 | git clone --depth=1 https://github.com/pragmagic/godot-nim-stub.git myproject
57 |
58 | (you can then delete the .git directory within to untie the project from the
59 | stub repository)
60 |
61 | The stub contains the necessary build configuration to compile your code for
62 | desktop and mobile platforms, as well as a couple of very simple scenes to
63 | help you get started. Consult the stub's `README
64 | `_ for information about
65 | compiling the project.
66 |
67 |
68 | Adding Nim to Existing Project
69 | ------------------------------
70 |
71 | If you would like to use Nim in an existing project:
72 |
73 | 1. Copy ``nakefile.nim`` file and ``src`` directory from the stub described
74 | in the previous section above your Godot project folder. Adjust paths in
75 | build scripts (``nakefile.nim``, ``src/stub.nimble``) according to your
76 | own project structure.
77 |
78 | 2. Copy ``nimlib.gdnlib`` to your Godot project folder. It is a
79 | GDNative library resource that contains paths to dynamic libraries
80 | compiled by Nim.
81 |
82 | Next Steps
83 | ----------
84 |
85 | Once you are familiarized with the build process (it's as simple as running
86 | ``nake build`` after you are set up), it is recommended to go through
87 | `godotmacros `_ and `godotnim `_ module
88 | documentations. They describe special macros and procedures needed to define
89 | or instantiate Godot objects. After you learned that, the rest is similar to
90 | using any Nim library. These bindings do not limit any of Nim's capabilities,
91 | and you can use any Nim types as fields or parameters of Godot objects and
92 | their procedures (but, obviously, you may not be able to export some of them
93 | to Godot editor or GDScript, unless you define your own converters).
94 |
95 |
96 | Modules
97 | =======
98 |
99 | The binding library consists of three major modules:
100 |
101 | * `godot <#modules-godot-module>`_ - Contains core types and macro definitions.
102 | You need to import this in any module that defines or makes use of Godot
103 | types.
104 |
105 | * `godotinternal <#modules-godotinternal-module>`_ - Contains raw wrappers over
106 | few core types, such as ``GodotVariant``, ``GodotString``, ``GodotNodePath``,
107 | ``GodotDictionary``, pool arrays. These are used by ``godotapigen`` and macro
108 | implementations, and you don't have to use them at all in your code, unless
109 | you want to go into low-level details for some reason. Each of those types
110 | needs to be destructed manually with ``deinit`` procedure.
111 |
112 | * `godotapigen `_ - Wrapper generator based on data from
113 | Godot's ``ClassDB``. You only need to use it as a part of the build process.
114 |
115 |
116 | godot Module
117 | ------------
118 |
119 | Contains core types and macro definitions. You need to import this in any
120 | module that defines or makes use of Godot types. The sumbodules below are
121 | exported and you don't have to import any of them directly.
122 |
123 | * `godotnim `_ Defines ``NimGodotObject`` and Varaint converters
124 | for standard Nim types.
125 | * `godotmacros `_ Defines ``gdobj`` macro for defining
126 | Godot objects.
127 | * `variants `_ ``Variant`` type represents a "dynamic object"
128 | that many Godot procedures make use of.
129 | * `arrays `_ Defines ``Array`` of Variants.
130 | * `basis `_ Defines 3D ``Basis``.
131 | * `colors `_ Defines ARGB ``Color``.
132 | * `dictionaries `_ Defines ``Variant`` -> ``Variant``
133 | ``Dictionary``.
134 | * `nodepaths `_ Defines ``NodePath`` - a path to a ``Node``.
135 | * `planes `_ Defines 3D ``Plane``.
136 | * `poolarrays `_ Defines pooled arrays: ``PoolByteArray``,
137 | ``PoolIntArray``, ``PoolRealArray``, ``PoolVector2Array``,
138 | ``PoolVector3Array``, ``PoolColorArray``, ``PoolStringArray``.
139 | * `quats `_ Defines ``Quat`` (quaternion) describing object
140 | rotation in 3D space.
141 | * `rect2 `_ Defines ``Rect2`` - a 2D rectangle.
142 | * `aabb `_ Defines ``AABB`` - a 3D box.
143 | * `rids `_ Defines ``RID`` - a resource identifier.
144 | * `transform2d `_ Defines ``Transform2D``.
145 | * `transforms `_ Defines ``Transform``.
146 | * `vector2 `_ Defines ``Vector2``.
147 | * `vector3 `_ Defines ``Vector3``.
148 | * `godotbase `_ Defines ``Error`` type and few common math
149 | procedures missing in Nim's standard library.
150 |
151 |
152 | Godot API
153 | ---------
154 |
155 | This is an auto-generated list of Godot API modules. It's built from Godot
156 | changeset `$GODOTAPI_CHANGESET_HASH
157 | `_.
158 |
159 | $AUTO_GENERATED_GODOTAPI_LIST
160 |
161 |
162 | godotinternal Module
163 | --------------------
164 |
165 | Contains low-level wrappers over Godot types that require manual memory
166 | management. This module is used within ``godot-nim`` implementation and you
167 | don't need to import it unless you know what you are doing.
168 |
169 | * `godotdictionaries `_
170 | * `godotnodepaths `_
171 | * `godotpoolarrays `_
172 | * `godotstrings `_
173 | * `godotvariants `_
174 |
--------------------------------------------------------------------------------
/godot/internal/godotvariants.nim:
--------------------------------------------------------------------------------
1 | # Copyright 2018 Xored Software, Inc.
2 |
3 | import core/godotcoretypes, godotinternaltypes, gdnativeapi
4 |
5 | proc getType*(p: GodotVariant): VariantType {.inline.} =
6 | getGDNativeAPI().variantGetType(p)
7 |
8 | proc initGodotVariant*(dest: var GodotVariant) {.inline.} =
9 | getGDNativeAPI().variantNewNil(dest)
10 |
11 | proc initGodotVariant*(dest: var GodotVariant, src: GodotVariant) {.inline.} =
12 | getGDNativeAPI().variantNewCopy(dest, src)
13 |
14 | proc initGodotVariant*(dest: var GodotVariant; b: bool) {.inline.} =
15 | getGDNativeAPI().variantNewBool(dest, b)
16 |
17 | proc initGodotVariant*(dest: var GodotVariant; i: uint64) {.inline.} =
18 | getGDNativeAPI().variantNewUInt(dest, i)
19 |
20 | proc initGodotVariant*(dest: var GodotVariant; i: int64) {.inline.} =
21 | getGDNativeAPI().variantNewInt(dest, i)
22 |
23 | proc initGodotVariant*(dest: var GodotVariant; r: cdouble) {.inline.} =
24 | getGDNativeAPI().variantNewReal(dest, r)
25 |
26 | proc initGodotVariant*(dest: var GodotVariant; s: GodotString) {.inline.} =
27 | getGDNativeAPI().variantNewString(dest, s)
28 |
29 | proc initGodotVariant*(dest: var GodotVariant; v2: Vector2) {.inline.} =
30 | getGDNativeAPI().variantNewVector2(dest, v2)
31 |
32 | proc initGodotVariant*(dest: var GodotVariant; rect2: Rect2) {.inline.} =
33 | getGDNativeAPI().variantNewRect2(dest, rect2)
34 |
35 | proc initGodotVariant*(dest: var GodotVariant; v3: Vector3) {.inline.} =
36 | getGDNativeAPI().variantNewVector3(dest, v3)
37 |
38 | proc initGodotVariant*(dest: var GodotVariant; t2d: Transform2D) {.inline.} =
39 | getGDNativeAPI().variantNewTransform2D(dest, t2d)
40 |
41 | proc initGodotVariant*(dest: var GodotVariant; plane: Plane) {.inline.} =
42 | getGDNativeAPI().variantNewPlane(dest, plane)
43 |
44 | proc initGodotVariant*(dest: var GodotVariant; quat: Quat) {.inline.} =
45 | getGDNativeAPI().variantNewQuat(dest, quat)
46 |
47 | proc initGodotVariant*(dest: var GodotVariant; aabb: AABB) {.inline.} =
48 | getGDNativeAPI().variantNewAABB(dest, aabb)
49 |
50 | proc initGodotVariant*(dest: var GodotVariant; basis: Basis) {.inline.} =
51 | getGDNativeAPI().variantNewBasis(dest, basis)
52 |
53 | proc initGodotVariant*(dest: var GodotVariant; trans: Transform) {.inline.} =
54 | getGDNativeAPI().variantNewTransform(dest, trans)
55 |
56 | proc initGodotVariant*(dest: var GodotVariant; color: Color) {.inline.} =
57 | getGDNativeAPI().variantNewColor(dest, color)
58 |
59 | proc initGodotVariant*(dest: var GodotVariant;
60 | nodePath: GodotNodePath) {.inline.} =
61 | getGDNativeAPI().variantNewNodePath(dest, nodePath)
62 |
63 | proc initGodotVariant*(dest: var GodotVariant; rid: RID) {.inline.} =
64 | getGDNativeAPI().variantNewRID(dest, rid)
65 |
66 | proc initGodotVariant*(dest: var GodotVariant;
67 | obj: ptr GodotObject) {.inline.} =
68 | getGDNativeAPI().variantNewObject(dest, obj)
69 |
70 | proc initGodotVariant*(dest: var GodotVariant; arr: GodotArray) {.inline.} =
71 | getGDNativeAPI().variantNewArray(dest, arr)
72 |
73 | proc initGodotVariant*(dest: var GodotVariant;
74 | pba: GodotPoolByteArray) {.inline.} =
75 | getGDNativeAPI().variantNewPoolByteArray(dest, pba)
76 |
77 | proc initGodotVariant*(dest: var GodotVariant;
78 | pia: GodotPoolIntArray) {.inline.} =
79 | getGDNativeAPI().variantNewPoolIntArray(dest, pia)
80 |
81 | proc initGodotVariant*(dest: var GodotVariant;
82 | pra: GodotPoolRealArray) {.inline.} =
83 | getGDNativeAPI().variantNewPoolRealArray(dest, pra)
84 |
85 | proc initGodotVariant*(dest: var GodotVariant;
86 | psa: GodotPoolStringArray) {.inline.} =
87 | getGDNativeAPI().variantNewPoolStringArray(dest, psa)
88 |
89 | proc initGodotVariant*(dest: var GodotVariant;
90 | pv2a: GodotPoolVector2Array) {.inline.} =
91 | getGDNativeAPI().variantNewPoolVector2Array(dest, pv2a)
92 |
93 | proc initGodotVariant*(dest: var GodotVariant;
94 | pv3a: GodotPoolVector3Array) {.inline.} =
95 | getGDNativeAPI().variantNewPoolVector3Array(dest, pv3a)
96 |
97 | proc initGodotVariant*(dest: var GodotVariant;
98 | pca: GodotPoolColorArray) {.inline.} =
99 | getGDNativeAPI().variantNewPoolColorArray(dest, pca)
100 |
101 | proc initGodotVariant*(dest: var GodotVariant;
102 | dict: GodotDictionary) {.inline.} =
103 | getGDNativeAPI().variantNewDictionary(dest, dict)
104 |
105 | proc deinit*(v: var GodotVariant) {.inline.} =
106 | getGDNativeAPI().variantDestroy(v)
107 |
108 | proc asBool*(self: GodotVariant): bool {.inline.} =
109 | getGDNativeAPI().variantAsBool(self)
110 |
111 | proc asUInt*(self: GodotVariant): uint64 {.inline.} =
112 | getGDNativeAPI().variantAsUInt(self)
113 |
114 | proc asInt*(self: GodotVariant): int64 {.inline.} =
115 | getGDNativeAPI().variantAsInt(self)
116 |
117 | proc asReal*(self: GodotVariant): cdouble {.inline.} =
118 | getGDNativeAPI().variantAsReal(self)
119 |
120 | proc asGodotString*(self: GodotVariant): GodotString {.inline.} =
121 | getGDNativeAPI().variantAsString(self)
122 |
123 | proc asVector2*(self: GodotVariant): Vector2 {.inline.} =
124 | getGDNativeAPI().variantAsVector2(self).toVector2()
125 |
126 | proc asRect2*(self: GodotVariant): Rect2 {.inline.} =
127 | getGDNativeAPI().variantAsRect2(self).toRect2()
128 |
129 | proc asVector3*(self: GodotVariant): Vector3 {.inline.} =
130 | getGDNativeAPI().variantAsVector3(self).toVector3()
131 |
132 | proc asTransform2D*(self: GodotVariant): Transform2D {.inline.} =
133 | getGDNativeAPI().variantAsTransform2D(self).toTransform2D()
134 |
135 | proc asPlane*(self: GodotVariant): Plane {.inline.} =
136 | getGDNativeAPI().variantAsPlane(self).toPlane()
137 |
138 | proc asQuat*(self: GodotVariant): Quat {.inline.} =
139 | getGDNativeAPI().variantAsQuat(self).toQuat()
140 |
141 | proc asAABB*(self: GodotVariant): AABB {.inline.} =
142 | getGDNativeAPI().variantAsAABB(self).toAABB()
143 |
144 | proc asBasis*(self: GodotVariant): Basis {.inline.} =
145 | getGDNativeAPI().variantAsBasis(self).toBasis()
146 |
147 | proc asTransform*(self: GodotVariant): Transform {.inline.} =
148 | getGDNativeAPI().variantAsTransform(self).toTransform()
149 |
150 | proc asColor*(self: GodotVariant): Color {.inline.} =
151 | getGDNativeAPI().variantAsColor(self).toColor()
152 |
153 | proc asNodePath*(self: GodotVariant): GodotNodePath {.inline.} =
154 | getGDNativeAPI().variantAsNodePath(self)
155 |
156 | proc asRID*(self: GodotVariant): RID {.inline.} =
157 | getGDNativeAPI().variantAsRID(self)
158 |
159 | proc asGodotObject*(self: GodotVariant): ptr GodotObject {.inline.} =
160 | getGDNativeAPI().variantAsObject(self)
161 |
162 | proc asGodotArray*(self: GodotVariant): GodotArray {.inline.} =
163 | getGDNativeAPI().variantAsArray(self)
164 |
165 | proc asGodotPoolByteArray*(self: GodotVariant): GodotPoolByteArray {.inline.} =
166 | getGDNativeAPI().variantAsPoolByteArray(self)
167 |
168 | proc asGodotPoolIntArray*(self: GodotVariant): GodotPoolIntArray {.inline.} =
169 | getGDNativeAPI().variantAsPoolIntArray(self)
170 |
171 | proc asGodotPoolRealArray*(self: GodotVariant): GodotPoolRealArray {.inline.} =
172 | getGDNativeAPI().variantAsPoolRealArray(self)
173 |
174 | proc asGodotPoolStringArray*(self: GodotVariant): GodotPoolStringArray
175 | {.inline.} =
176 | getGDNativeAPI().variantAsPoolStringArray(self)
177 |
178 | proc asGodotPoolVector2Array*(self: GodotVariant): GodotPoolVector2Array
179 | {.inline.} =
180 | getGDNativeAPI().variantAsPoolVector2Array(self)
181 |
182 | proc asGodotPoolVector3Array*(self: GodotVariant): GodotPoolVector3Array
183 | {.inline.} =
184 | getGDNativeAPI().variantAsPoolVector3Array(self)
185 |
186 | proc asGodotPoolColorArray*(self: GodotVariant): GodotPoolColorArray
187 | {.inline.} =
188 | getGDNativeAPI().variantAsPoolColorArray(self)
189 |
190 | proc asGodotDictionary*(self: GodotVariant): GodotDictionary {.inline.} =
191 | getGDNativeAPI().variantAsDictionary(self)
192 |
193 | proc call*(self: var GodotVariant; meth: GodotString;
194 | args: ptr array[256, ptr GodotVariant]; argCount: cint;
195 | error: var VariantCallError): GodotVariant {.inline.} =
196 | getGDNativeAPI().variantCall(self, meth, args, argCount, error)
197 |
198 | proc hasMethod*(self: GodotVariant; meth: GodotString): bool {.inline.} =
199 | getGDNativeAPI().variantHasMethod(self, meth)
200 |
201 | proc `==`*(self, other: GodotVariant): bool {.inline.} =
202 | getGDNativeAPI().variantOperatorEqual(self, other)
203 |
204 | proc `<`*(self, other: GodotVariant): bool {.inline.} =
205 | getGDNativeAPI().variantOperatorLess(self, other)
206 |
207 | proc hashCompare*(self, other: GodotVariant): bool {.inline.} =
208 | getGDNativeAPI().variantHashCompare(self, other)
209 |
210 | proc booleanize*(self: GodotVariant): bool {.inline.} =
211 | getGDNativeAPI().variantBooleanize(self)
212 |
213 | import godotstrings
214 | proc `$`*(self: GodotVariant): string =
215 | var s = self.asGodotString()
216 | result = $s
217 | s.deinit()
218 |
--------------------------------------------------------------------------------
/godot/core/variants.nim:
--------------------------------------------------------------------------------
1 | import tables, hashes
2 |
3 | import godotcoretypes
4 | import internal/godotinternaltypes, internal/godotvariants,
5 | internal/godotstrings, internal/godotdictionaries,
6 | internal/godotarrays
7 |
8 | type
9 | Variant* = ref object
10 | godotVariant: GodotVariant
11 | noDeinit: bool # used to avoid copying when passing the variant to Godot
12 |
13 | export VariantType, VariantCallErrorType, VariantCallError
14 |
15 | proc markNoDeinit*(v: Variant) {.inline.} =
16 | ## Makes it so that internal GodotVariant object will not be destroyed
17 | ## when the reference is gone. Use only if you know what you are doing.
18 | v.noDeinit = true
19 |
20 | proc godotVariant*(v: Variant): ptr GodotVariant {.inline.} =
21 | ## WARNING: do not keep the returned value for longer than the lifetime of
22 | ## ``v``
23 | addr v.godotVariant
24 |
25 | proc getType*(v: Variant): VariantType =
26 | v.godotVariant.getType()
27 |
28 | proc variantFinalizer*(v: Variant) =
29 | if not v.noDeinit:
30 | v.godotVariant.deinit()
31 |
32 | proc `$`*(self: Variant): string {.inline.} =
33 | $self.godotVariant
34 |
35 | proc newVariant*(): Variant {.inline.} =
36 | new(result, variantFinalizer)
37 | initGodotVariant(result.godotVariant)
38 |
39 | proc newVariant*(v: Variant): Variant {.inline.} =
40 | ## Makes a copy
41 | new(result, variantFinalizer)
42 | initGodotVariant(result.godotVariant, v.godotVariant)
43 |
44 | proc newVariant*(v: GodotVariant): Variant {.inline.} =
45 | new(result, variantFinalizer)
46 | result.godotVariant = v
47 |
48 | proc newVariant*(b: bool): Variant {.inline.} =
49 | new(result, variantFinalizer)
50 | initGodotVariant(result.godotVariant, b)
51 |
52 | # resolves Nim call ambiguities well
53 | template numConstructor(T, ConvT) =
54 | proc newVariant*(i: T): Variant {.inline.} =
55 | new(result, variantFinalizer)
56 | initGodotVariant(result.godotVariant, ConvT(i))
57 |
58 | numConstructor(uint8, uint64)
59 | numConstructor(uint16, uint64)
60 | numConstructor(uint32, uint64)
61 | numConstructor(uint64, uint64)
62 | numConstructor(uint, uint64)
63 |
64 | numConstructor(int8, int64)
65 | numConstructor(int16, int64)
66 | numConstructor(int32, int64)
67 | numConstructor(int64, int64)
68 | numConstructor(int, int64)
69 |
70 | proc newVariant*(r: cdouble): Variant {.inline.} =
71 | new(result, variantFinalizer)
72 | initGodotVariant(result.godotVariant, r)
73 |
74 | proc newVariant*(s: string): Variant {.inline.} =
75 | new(result, variantFinalizer)
76 | when (NimMajor, NimMinor, NimPatch) < (0, 19, 0):
77 | if s.isNil:
78 | initGodotVariant(result.godotVariant)
79 | return
80 | var godotStr = s.toGodotString()
81 | initGodotVariant(result.godotVariant, godotStr)
82 | godotStr.deinit()
83 |
84 | import basis, nodepaths
85 | import planes, quats, rect2, aabb, rids
86 | import transforms, transform2d, vector2
87 | import vector3, colors
88 |
89 | proc newVariant*(v2: Vector2): Variant {.inline.} =
90 | new(result, variantFinalizer)
91 | initGodotVariant(result.godotVariant, v2)
92 |
93 | proc newVariant*(rect2: Rect2): Variant {.inline.} =
94 | new(result, variantFinalizer)
95 | initGodotVariant(result.godotVariant, rect2)
96 |
97 | proc newVariant*(v3: Vector3): Variant {.inline.} =
98 | new(result, variantFinalizer)
99 | initGodotVariant(result.godotVariant, v3)
100 |
101 | proc newVariant*(t2d: Transform2D): Variant {.inline.} =
102 | new(result, variantFinalizer)
103 | initGodotVariant(result.godotVariant, t2d)
104 |
105 | proc newVariant*(plane: Plane): Variant {.inline.} =
106 | new(result, variantFinalizer)
107 | initGodotVariant(result.godotVariant, plane)
108 |
109 | proc newVariant*(quat: Quat): Variant {.inline.} =
110 | new(result, variantFinalizer)
111 | initGodotVariant(result.godotVariant, quat)
112 |
113 | proc newVariant*(aabb: AABB): Variant {.inline.} =
114 | new(result, variantFinalizer)
115 | initGodotVariant(result.godotVariant, aabb)
116 |
117 | proc newVariant*(basis: Basis): Variant {.inline.} =
118 | new(result, variantFinalizer)
119 | initGodotVariant(result.godotVariant, basis)
120 |
121 | proc newVariant*(trans: Transform): Variant {.inline.} =
122 | new(result, variantFinalizer)
123 | initGodotVariant(result.godotVariant, trans)
124 |
125 | proc newVariant*(color: Color): Variant {.inline.} =
126 | new(result, variantFinalizer)
127 | initGodotVariant(result.godotVariant, color)
128 |
129 | proc newVariant*(nodePath: NodePath): Variant {.inline.} =
130 | new(result, variantFinalizer)
131 | initGodotVariant(result.godotVariant, nodePath.godotNodePath[])
132 |
133 | proc newVariant*(godotNodePath: GodotNodePath): Variant {.inline.} =
134 | new(result, variantFinalizer)
135 | initGodotVariant(result.godotVariant, godotNodePath)
136 |
137 | proc newVariant*(rid: RID): Variant {.inline.} =
138 | new(result, variantFinalizer)
139 | initGodotVariant(result.godotVariant, rid)
140 |
141 | proc newVariant*(obj: ptr GodotObject): Variant {.inline.} =
142 | new(result, variantFinalizer)
143 | initGodotVariant(result.godotVariant, obj)
144 |
145 | import poolarrays
146 |
147 | proc newVariant*(pba: PoolByteArray): Variant {.inline.} =
148 | new(result, variantFinalizer)
149 | initGodotVariant(result.godotVariant, pba.godotPoolByteArray[])
150 |
151 | proc newVariant*(pia: PoolIntArray): Variant {.inline.} =
152 | new(result, variantFinalizer)
153 | initGodotVariant(result.godotVariant, pia.godotPoolIntArray[])
154 |
155 | proc newVariant*(pra: PoolRealArray): Variant {.inline.} =
156 | new(result, variantFinalizer)
157 | initGodotVariant(result.godotVariant, pra.godotPoolRealArray[])
158 |
159 | proc newVariant*(psa: PoolStringArray): Variant {.inline.} =
160 | new(result, variantFinalizer)
161 | initGodotVariant(result.godotVariant, psa.godotPoolStringArray[])
162 |
163 | proc newVariant*(pv2a: PoolVector2Array): Variant {.inline.} =
164 | new(result, variantFinalizer)
165 | initGodotVariant(result.godotVariant, pv2a.godotPoolVector2Array[])
166 |
167 | proc newVariant*(pv3a: PoolVector3Array): Variant {.inline.} =
168 | new(result, variantFinalizer)
169 | initGodotVariant(result.godotVariant, pv3a.godotPoolVector3Array[])
170 |
171 | proc newVariant*(pca: PoolColorArray): Variant {.inline.} =
172 | new(result, variantFinalizer)
173 | initGodotVariant(result.godotVariant, pca.godotPoolColorArray[])
174 |
175 | proc asBool*(self: Variant): bool {.inline.} =
176 | self.godotVariant.asBool()
177 |
178 | proc asUInt*(self: Variant): uint64 {.inline.} =
179 | self.godotVariant.asUInt()
180 |
181 | proc asInt*(self: Variant): int64 {.inline.} =
182 | self.godotVariant.asInt()
183 |
184 | proc asReal*(self: Variant): cdouble {.inline.} =
185 | self.godotVariant.asReal()
186 |
187 | proc asString*(self: Variant): string {.inline.} =
188 | $self
189 |
190 | proc asVector2*(self: Variant): Vector2 {.inline.} =
191 | self.godotVariant.asVector2()
192 |
193 | proc asRect2*(self: Variant): Rect2 {.inline.} =
194 | self.godotVariant.asRect2()
195 |
196 | proc asVector3*(self: Variant): Vector3 {.inline.} =
197 | self.godotVariant.asVector3()
198 |
199 | proc asTransform2D*(self: Variant): Transform2D {.inline.} =
200 | self.godotVariant.asTransform2D()
201 |
202 | proc asPlane*(self: Variant): Plane {.inline.} =
203 | self.godotVariant.asPlane()
204 |
205 | proc asQuat*(self: Variant): Quat {.inline.} =
206 | self.godotVariant.asQuat()
207 |
208 | proc asAABB*(self: Variant): AABB {.inline.} =
209 | self.godotVariant.asAABB()
210 |
211 | proc asBasis*(self: Variant): Basis {.inline.} =
212 | self.godotVariant.asBasis()
213 |
214 | proc asTransform*(self: Variant): Transform {.inline.} =
215 | self.godotVariant.asTransform()
216 |
217 | proc asColor*(self: Variant): Color {.inline.} =
218 | self.godotVariant.asColor()
219 |
220 | proc asNodePath*(self: Variant): NodePath {.inline.} =
221 | result = newNodePath(self.godotVariant.asNodePath())
222 |
223 | proc asRID*(self: Variant): RID {.inline.} =
224 | self.godotVariant.asRID()
225 |
226 | proc asGodotObject*(self: Variant): ptr GodotObject {.inline.} =
227 | self.godotVariant.asGodotObject()
228 |
229 | proc asPoolByteArray*(self: Variant): PoolByteArray {.inline.} =
230 | newPoolByteArray(self.godotVariant.asGodotPoolByteArray())
231 |
232 | proc asPoolIntArray*(self: Variant): PoolIntArray {.inline.} =
233 | newPoolIntArray(self.godotVariant.asGodotPoolIntArray())
234 |
235 | proc asPoolRealArray*(self: Variant): PoolRealArray {.inline.} =
236 | newPoolRealArray(self.godotVariant.asGodotPoolRealArray())
237 |
238 | proc asPoolStringArray*(self: Variant): PoolStringArray {.inline.} =
239 | newPoolStringArray(self.godotVariant.asGodotPoolStringArray())
240 |
241 | proc asPoolVector2Array*(self: Variant): PoolVector2Array {.inline.} =
242 | newPoolVector2Array(self.godotVariant.asGodotPoolVector2Array())
243 |
244 | proc asPoolVector3Array*(self: Variant): PoolVector3Array {.inline.} =
245 | newPoolVector3Array(self.godotVariant.asGodotPoolVector3Array())
246 |
247 | proc asPoolColorArray*(self: Variant): PoolColorArray {.inline.} =
248 | newPoolColorArray(self.godotVariant.asGodotPoolColorArray())
249 |
250 | proc hash*(self: Variant): Hash =
251 | proc objectHash(obj: ptr GodotObject): Hash =
252 | if not obj.isNil: cast[int](obj).hash() else: 0.hash()
253 | result = case self.getType():
254 | of VariantType.Nil: Hash(0)
255 | of VariantType.Bool: self.asBool().hash()
256 | of VariantType.Int: self.asInt().hash()
257 | of VariantType.Real: self.asReal().hash()
258 | of VariantType.String: self.asString().hash()
259 | of VariantType.Vector2: self.asVector2().hash()
260 | of VariantType.Rect2: self.asRect2().hash()
261 | of VariantType.Vector3: self.asVector3().hash()
262 | of VariantType.Transform2D: self.asTransform2D().hash()
263 | of VariantType.Plane: self.asPlane().hash()
264 | of VariantType.Quat: self.asQuat().hash()
265 | of VariantType.AABB: self.asAABB().hash()
266 | of VariantType.Basis: self.asBasis().hash()
267 | of VariantType.Transform: self.asTransform().hash()
268 | of VariantType.Color: self.asColor().hash()
269 | of VariantType.NodePath: self.asNodePath().hash()
270 | of VariantType.RID: self.asRID().hash()
271 | of VariantType.Object: self.asGodotObject().objectHash()
272 | of VariantType.Dictionary: hash(self.godotVariant.asGodotDictionary().godotHash())
273 | of VariantType.Array: hash(self.godotVariant.asGodotArray().godotHash())
274 | of VariantType.PoolByteArray: self.asPoolByteArray().hash()
275 | of VariantType.PoolIntArray: self.asPoolIntArray().hash()
276 | of VariantType.PoolRealArray: self.asPoolRealArray().hash()
277 | of VariantType.PoolStringArray: self.asPoolStringArray().hash()
278 | of VariantType.PoolVector2Array: self.asPoolVector2Array().hash()
279 | of VariantType.PoolVector3Array: self.asPoolVector3Array().hash()
280 | of VariantType.PoolColorArray: self.asPoolColorArray().hash()
281 |
282 | import arrays
283 |
284 | proc newVariant*(arr: Array): Variant {.inline.} =
285 | new(result, variantFinalizer)
286 | initGodotVariant(result.godotVariant, arr.godotArray[])
287 |
288 | proc asArray*(self: Variant): Array {.inline.} =
289 | newArray(self.godotVariant.asGodotArray())
290 |
291 | proc hasMethod*(self: Variant; meth: string): bool =
292 | var s = meth.toGodotString()
293 | result = self.godotVariant.hasMethod(s)
294 | s.deinit()
295 |
296 | proc `==`*(self, other: Variant): bool =
297 | if self.isNil and other.isNil: return true
298 | if self.isNil != other.isNil: return false
299 | result = self.godotVariant == other.godotVariant
300 |
301 | proc `<`*(self, other: Variant): bool =
302 | result = self.godotVariant < other.godotVariant
303 |
304 | proc hashCompare*(self, other: Variant): bool =
305 | self.godotVariant.hashCompare(other.godotVariant)
306 |
307 | proc booleanize*(self: Variant): bool =
308 | self.godotVariant.booleanize()
309 |
--------------------------------------------------------------------------------
/godot/internal/godotpoolarrays.nim:
--------------------------------------------------------------------------------
1 | # Copyright (c) 2018 Xored Software, Inc.
2 |
3 | import godotinternaltypes, gdnativeapi
4 | import core/godotcoretypes
5 |
6 | template genPoolArrayAPI(ArrayT, initIdent, DataT,
7 | newProc, newCopyProc, newWithArrayProc, appendProc,
8 | appendArrayProc, insertProc, invertProc, pushBackProc,
9 | removeProc, resizeProc, setProc, getProc, sizeProc,
10 | destroyProc, readProc, writeProc,
11 | readAccessPtrProc, writeAccessPtrProc,
12 | readAccessDestroyProc, writeAccessDestroyProc) =
13 | proc initIdent*(dest: var ArrayT) {.inline.} =
14 | getGDNativeAPI().newProc(dest)
15 |
16 | proc initIdent*(dest: var ArrayT; src: ArrayT) {.inline.} =
17 | getGDNativeAPI().newCopyProc(dest, src)
18 |
19 | proc initIdent*(dest: var ArrayT; arr: GodotArray) {.inline.} =
20 | getGDNativeAPI().newWithArrayProc(dest, arr)
21 |
22 | proc deinit*(self: var ArrayT) {.inline.} =
23 | getGDNativeAPI().destroyProc(self)
24 |
25 | proc add*(self: var ArrayT; data: DataT) {.inline.} =
26 | getGDNativeAPI().pushBackProc(self, data)
27 |
28 | proc add*(self: var ArrayT; arr: ArrayT) {.inline.} =
29 | getGDNativeAPI().appendArrayProc(self, arr)
30 |
31 | proc insert*(self: var ArrayT; idx: cint;
32 | data: DataT): Error {.inline.} =
33 | getGDNativeAPI().insertProc(self, idx, data)
34 |
35 | proc delete*(self: var ArrayT; idx: cint) {.inline.} =
36 | getGDNativeAPI().removeProc(self, idx)
37 |
38 | proc reverse*(self: var ArrayT) {.inline.} =
39 | getGDNativeAPI().invertProc(self)
40 |
41 | proc setLen*(self: var ArrayT; size: cint) {.inline.} =
42 | getGDNativeAPI().resizeProc(self, size)
43 |
44 | proc `[]=`*(self: var ArrayT; idx: cint; data: DataT) {.inline.} =
45 | getGDNativeAPI().setProc(self, idx, data)
46 |
47 | proc `[]`*(self: ArrayT; idx: cint): DataT {.inline.} =
48 | let data = getGDNativeAPI().getProc(self, idx)
49 | when DataT is Color:
50 | data.toColor()
51 | elif DataT is Vector2:
52 | data.toVector2()
53 | elif DataT is Vector3:
54 | data.toVector3()
55 | else:
56 | data
57 |
58 | proc len*(self: ArrayT): cint {.inline.} =
59 | getGDNativeAPI().sizeProc(self)
60 |
61 | iterator items*(self: ArrayT): DataT =
62 | let readAccess = getGDNativeAPI().readProc(self)
63 | let readPtr = getGDNativeAPI().readAccessPtrProc(readAccess)
64 | for i in 0.cint..= ownLen:
99 | let instInfo = instantiationInfo()
100 | getGDNativeAPI().printError(
101 | cstring"Invalid subarray begin index", cstring"subarray", instInfo.filename, instInfo.line.cint)
102 | return
103 | if actualIdxTo < 0 or actualIdxTo >= ownLen:
104 | let instInfo = instantiationInfo()
105 | getGDNativeAPI().printError(
106 | cstring"Invalid subarray end index", cstring"subarray", instInfo.filename, instInfo.line.cint)
107 | return
108 | let span = actualIdxTo - actualIdxFrom + 1
109 | result.setLen(span)
110 | let readAccess = getGDNativeAPI().readProc(self)
111 | let writeAccess = getGDNativeAPI().writeProc(result)
112 | let readPtr = getGDNativeAPI().readAccessPtrProc(readAccess).offset(actualIdxFrom)
113 | copyMem(getGDNativeAPI().writeAccessPtrProc(writeAccess), readPtr, span)
114 | getGDNativeAPI().readAccessDestroyProc(readAccess)
115 | getGDNativeAPI().writeAccessDestroyProc(writeAccess)
116 |
117 | genPoolArrayAPI(GodotPoolByteArray, initGodotPoolByteArray, byte,
118 | poolByteArrayNew,
119 | poolByteArrayNewCopy,
120 | poolByteArrayNewWithArray,
121 | poolByteArrayAppend,
122 | poolByteArrayAppendArray,
123 | poolByteArrayInsert,
124 | poolByteArrayInvert,
125 | poolByteArrayPushBack,
126 | poolByteArrayRemove,
127 | poolByteArrayResize,
128 | poolByteArraySet,
129 | poolByteArrayGet,
130 | poolByteArraySize,
131 | poolByteArrayDestroy,
132 | poolByteArrayRead,
133 | poolByteArrayWrite,
134 | poolByteArrayReadAccessPtr,
135 | poolByteArrayWriteAccessPtr,
136 | poolByteArrayReadAccessDestroy,
137 | poolByteArrayWriteAccessDestroy)
138 |
139 | genPoolArrayAPI(GodotPoolIntArray, initGodotPoolIntArray, cint,
140 | poolIntArrayNew,
141 | poolIntArrayNewCopy,
142 | poolIntArrayNewWithArray,
143 | poolIntArrayAppend,
144 | poolIntArrayAppendArray,
145 | poolIntArrayInsert,
146 | poolIntArrayInvert,
147 | poolIntArrayPushBack,
148 | poolIntArrayRemove,
149 | poolIntArrayResize,
150 | poolIntArraySet,
151 | poolIntArrayGet,
152 | poolIntArraySize,
153 | poolIntArrayDestroy,
154 | poolIntArrayRead,
155 | poolIntArrayWrite,
156 | poolIntArrayReadAccessPtr,
157 | poolIntArrayWriteAccessPtr,
158 | poolIntArrayReadAccessDestroy,
159 | poolIntArrayWriteAccessDestroy)
160 |
161 | genPoolArrayAPI(GodotPoolRealArray, initGodotPoolRealArray, float32,
162 | poolRealArrayNew,
163 | poolRealArrayNewCopy,
164 | poolRealArrayNewWithArray,
165 | poolRealArrayAppend,
166 | poolRealArrayAppendArray,
167 | poolRealArrayInsert,
168 | poolRealArrayInvert,
169 | poolRealArrayPushBack,
170 | poolRealArrayRemove,
171 | poolRealArrayResize,
172 | poolRealArraySet,
173 | poolRealArrayGet,
174 | poolRealArraySize,
175 | poolRealArrayDestroy,
176 | poolRealArrayRead,
177 | poolRealArrayWrite,
178 | poolRealArrayReadAccessPtr,
179 | poolRealArrayWriteAccessPtr,
180 | poolRealArrayReadAccessDestroy,
181 | poolRealArrayWriteAccessDestroy)
182 |
183 | genPoolArrayAPI(GodotPoolStringArray, initGodotPoolStringArray, GodotString,
184 | poolStringArrayNew,
185 | poolStringArrayNewCopy,
186 | poolStringArrayNewWithArray,
187 | poolStringArrayAppend,
188 | poolStringArrayAppendArray,
189 | poolStringArrayInsert,
190 | poolStringArrayInvert,
191 | poolStringArrayPushBack,
192 | poolStringArrayRemove,
193 | poolStringArrayResize,
194 | poolStringArraySet,
195 | poolStringArrayGet,
196 | poolStringArraySize,
197 | poolStringArrayDestroy,
198 | poolStringArrayRead,
199 | poolStringArrayWrite,
200 | poolStringArrayReadAccessPtr,
201 | poolStringArrayWriteAccessPtr,
202 | poolStringArrayReadAccessDestroy,
203 | poolStringArrayWriteAccessDestroy)
204 |
205 | genPoolArrayAPI(GodotPoolVector2Array, initGodotPoolVector2Array, Vector2,
206 | poolVector2ArrayNew,
207 | poolVector2ArrayNewCopy,
208 | poolVector2ArrayNewWithArray,
209 | poolVector2ArrayAppend,
210 | poolVector2ArrayAppendArray,
211 | poolVector2ArrayInsert,
212 | poolVector2ArrayInvert,
213 | poolVector2ArrayPushBack,
214 | poolVector2ArrayRemove,
215 | poolVector2ArrayResize,
216 | poolVector2ArraySet,
217 | poolVector2ArrayGet,
218 | poolVector2ArraySize,
219 | poolVector2ArrayDestroy,
220 | poolVector2ArrayRead,
221 | poolVector2ArrayWrite,
222 | poolVector2ArrayReadAccessPtr,
223 | poolVector2ArrayWriteAccessPtr,
224 | poolVector2ArrayReadAccessDestroy,
225 | poolVector2ArrayWriteAccessDestroy)
226 |
227 | genPoolArrayAPI(GodotPoolVector3Array, initGodotPoolVector3Array, Vector3,
228 | poolVector3ArrayNew,
229 | poolVector3ArrayNewCopy,
230 | poolVector3ArrayNewWithArray,
231 | poolVector3ArrayAppend,
232 | poolVector3ArrayAppendArray,
233 | poolVector3ArrayInsert,
234 | poolVector3ArrayInvert,
235 | poolVector3ArrayPushBack,
236 | poolVector3ArrayRemove,
237 | poolVector3ArrayResize,
238 | poolVector3ArraySet,
239 | poolVector3ArrayGet,
240 | poolVector3ArraySize,
241 | poolVector3ArrayDestroy,
242 | poolVector3ArrayRead,
243 | poolVector3ArrayWrite,
244 | poolVector3ArrayReadAccessPtr,
245 | poolVector3ArrayWriteAccessPtr,
246 | poolVector3ArrayReadAccessDestroy,
247 | poolVector3ArrayWriteAccessDestroy)
248 |
249 | genPoolArrayAPI(GodotPoolColorArray, initGodotPoolColorArray, Color,
250 | poolColorArrayNew,
251 | poolColorArrayNewCopy,
252 | poolColorArrayNewWithArray,
253 | poolColorArrayAppend,
254 | poolColorArrayAppendArray,
255 | poolColorArrayInsert,
256 | poolColorArrayInvert,
257 | poolColorArrayPushBack,
258 | poolColorArrayRemove,
259 | poolColorArrayResize,
260 | poolColorArraySet,
261 | poolColorArrayGet,
262 | poolColorArraySize,
263 | poolColorArrayDestroy,
264 | poolColorArrayRead,
265 | poolColorArrayWrite,
266 | poolColorArrayReadAccessPtr,
267 | poolColorArrayWriteAccessPtr,
268 | poolColorArrayReadAccessDestroy,
269 | poolColorArrayWriteAccessDestroy)
270 |
--------------------------------------------------------------------------------
/godot/internal/godotinternaltypes.nim:
--------------------------------------------------------------------------------
1 | # Copyright 2018 Xored Software, Inc.
2 |
3 | const MAX_ARG_COUNT* = 256
4 |
5 | type
6 | GodotArray* {.byref.} = object
7 | data: array[sizeof(int), byte]
8 |
9 | GodotDictionary* {.byref.} = object
10 | data: array[sizeof(int), byte]
11 |
12 | GodotNodePath* {.byref.} = object
13 | data: array[sizeof(int), byte]
14 |
15 | GodotObject* = object
16 |
17 | GodotPoolByteArray* {.byref.} = object
18 | data: array[sizeof(int), byte]
19 | GodotPoolByteArrayReadAccess* {.byref.} = object
20 | data: array[1, byte]
21 | GodotPoolByteArrayWriteAccess* {.byref.} = object
22 | data: array[1, byte]
23 |
24 | GodotPoolIntArray* {.byref.} = object
25 | data: array[sizeof(int), byte]
26 | GodotPoolIntArrayReadAccess* {.byref.} = object
27 | data: array[1, byte]
28 | GodotPoolIntArrayWriteAccess* {.byref.} = object
29 | data: array[1, byte]
30 |
31 | GodotPoolRealArray* {.byref.} = object
32 | data: array[sizeof(int), byte]
33 | GodotPoolRealArrayReadAccess* {.byref.} = object
34 | data: array[1, byte]
35 | GodotPoolRealArrayWriteAccess* {.byref.} = object
36 | data: array[1, byte]
37 |
38 | GodotPoolStringArray* {.byref.} = object
39 | data: array[sizeof(int), byte]
40 | GodotPoolStringArrayReadAccess* {.byref.} = object
41 | data: array[1, byte]
42 | GodotPoolStringArrayWriteAccess* {.byref.} = object
43 | data: array[1, byte]
44 |
45 | GodotPoolVector2Array* {.byref.} = object
46 | data: array[sizeof(int), byte]
47 | GodotPoolVector2ArrayReadAccess* {.byref.} = object
48 | data: array[1, byte]
49 | GodotPoolVector2ArrayWriteAccess* {.byref.} = object
50 | data: array[1, byte]
51 |
52 | GodotPoolVector3Array* {.byref.} = object
53 | data: array[sizeof(int), byte]
54 | GodotPoolVector3ArrayReadAccess* {.byref.} = object
55 | data: array[1, byte]
56 | GodotPoolVector3ArrayWriteAccess* {.byref.} = object
57 | data: array[1, byte]
58 |
59 | GodotPoolColorArray* {.byref.} = object
60 | data: array[sizeof(int), byte]
61 | GodotPoolColorArrayReadAccess* {.byref.} = object
62 | data: array[1, byte]
63 | GodotPoolColorArrayWriteAccess* {.byref.} = object
64 | data: array[1, byte]
65 |
66 | GodotString* {.byref.} = object
67 | data: array[sizeof(int), byte]
68 |
69 | cwchar_t* {.importc: "wchar_t", nodecl.} = object
70 |
71 | GodotCharString* {.byref.} = object
72 | data: array[sizeof(int), byte]
73 |
74 | VariantType* {.size: sizeof(cint), pure.} = enum
75 | Nil, ## atomic types
76 | Bool,
77 | Int,
78 | Real,
79 | String,
80 | # math types
81 | Vector2, ## 5
82 | Rect2,
83 | Vector3,
84 | Transform2D,
85 | Plane,
86 | Quat, ## 10
87 | AABB,
88 | Basis,
89 | Transform, ## misc types
90 | Color,
91 | NodePath, ## 15
92 | RID,
93 | Object,
94 | Dictionary,
95 | Array, ## 20
96 | # arrays
97 | PoolByteArray,
98 | PoolIntArray,
99 | PoolRealArray,
100 | PoolStringArray,
101 | PoolVector2Array, ## 25
102 | PoolVector3Array,
103 | PoolColorArray
104 |
105 | VariantCallErrorType* {.size: sizeof(cint), pure.} = enum
106 | OK,
107 | InvalidMethod,
108 | InvalidArgument,
109 | TooManyArguments,
110 | TooFewArguments,
111 | InstanceIsNull
112 |
113 | VariantCallError* = object
114 | error*: VariantCallErrorType
115 | argument*: cint
116 | expected*: VariantType
117 |
118 | GodotVariant* {.byref.} = object
119 | data: array[2, int64]
120 | data2: int
121 |
122 | type GodotMethodBind* = object
123 |
124 | type
125 | GDNativeAPIVersion* = object
126 | major*: cuint
127 | minor*: cuint
128 |
129 | GDNativeInitOptions* = object
130 | inEditor*: bool
131 | coreApiHash*: uint64
132 | editorApiHash*: uint64
133 | noApiHash*: uint64
134 | reportVersionMismatch*: proc (library: ptr GodotObject, extension: cstring,
135 | want: GDNativeAPIVersion, have: GDNativeAPIVersion) {.noconv.}
136 | reportLoadingError*: proc (library: ptr GodotObject, what: cstring) {.noconv.}
137 | gdNativeLibrary*: ptr GodotObject
138 | gdNativeAPIStruct*: pointer
139 | activeLibraryPath*: ptr GodotString
140 |
141 | GDNativeTerminateOptions* = object
142 | inEditor*: bool
143 |
144 | GodotMethodRPCMode* {.size: sizeof(cint), pure.} = enum
145 | Disabled,
146 | Remote,
147 | Sync,
148 | Master,
149 | Slave
150 |
151 | GodotMethodAttributes* = object
152 | rpcMode*: GodotMethodRPCMode
153 |
154 | GodotPropertyHint* {.size: sizeof(cint), pure.} = enum
155 | None, ## no hint provided.
156 | Range, ## hint_text = "min,max,step,slider; // slider is optional"
157 | ExpRange, ## hint_text = "min,max,step", exponential edit
158 | Enum, ## hint_text= "val1,val2,val3,etc"
159 | ExpEasing, ## exponential easing funciton (Math::ease)
160 | Length, ## hint_text= "length" (as integer)
161 | SpriteFrame,
162 | KeyAccel, ## hint_text= "length" (as integer)
163 | Flags, ## hint_text= "flag1,flag2,etc" (as bit flags)
164 | Layers2DRender,
165 | Layers2DPhysics,
166 | Layers3DRender,
167 | Layers3DPhysics,
168 | File, ## a file path must be passed, hint_text (optionally)
169 | ## is a filter "*.png,*.wav,*.doc,"
170 | Dir, ## a directort path must be passed
171 | GlobalFile, ## a file path must be passed, hint_text (optionally) is a
172 | ## filter "*.png,*.wav,*.doc,"
173 | GlobalDir, ## a directort path must be passed
174 | ResourceType, ## a resource object type
175 | MultilineText, ## used for string properties that can contain multiple lines
176 | ColorNoAlpha, ## used for ignoring alpha component when editing a color
177 | ImageCompressLossy,
178 | ImageCompressLossless,
179 | ObjectId,
180 | TypeString, ## a type string, the hint is the base type to choose
181 | NodePathToEditedNode, ## so something else can provide this
182 | ## (used in scripts)
183 | MethodOfVariantType, ## a method of a type
184 | MethodOfBaseType, ## a method of a base type
185 | MethodOfInstance, ## a method of an instance
186 | MethodOfScript, ## a method of a script & base
187 | PropertyOfVariantType, ## a property of a type
188 | PropertyOfBaseType, ## a property of a base type
189 | PropertyOfInstance, ## a property of an instance
190 | PropertyOfScript, ## a property of a script & base
191 | PropertyHintMax
192 |
193 | const
194 | GODOT_PROPERTY_USAGE_STORAGE_VALUE = 1.cint
195 | GODOT_PROPERTY_USAGE_EDITOR_VALUE = 2.cint
196 | GODOT_PROPERTY_USAGE_NETWORK_VALUE = 4.cint
197 | GODOT_PROPERTY_USAGE_EDITOR_HELPER_VALUE = 8.cint
198 | GODOT_PROPERTY_USAGE_CHECKABLE_VALUE = 16.cint
199 | GODOT_PROPERTY_USAGE_CHECKED_VALUE = 32.cint
200 | GODOT_PROPERTY_USAGE_INTERNATIONALIZED_VALUE = 64.cint
201 | GODOT_PROPERTY_USAGE_GROUP_VALUE = 128.cint
202 | GODOT_PROPERTY_USAGE_CATEGORY_VALUE = 256.cint
203 | GODOT_PROPERTY_USAGE_STORE_IF_NONZERO_VALUE = 512.cint
204 | GODOT_PROPERTY_USAGE_STORE_IF_NONONE_VALUE = 1024.cint
205 | GODOT_PROPERTY_USAGE_NO_INSTANCE_STATE_VALUE = 2048.cint
206 | GODOT_PROPERTY_USAGE_RESTART_IF_CHANGED_VALUE = 4096.cint
207 | GODOT_PROPERTY_USAGE_SCRIPT_VARIABLE_VALUE = 8192.cint
208 | GODOT_PROPERTY_USAGE_STORE_IF_NULL_VALUE = 16384.cint
209 | GODOT_PROPERTY_USAGE_ANIMATE_AS_TRIGGER_VALUE = 32768.cint
210 | GODOT_PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED_VALUE = 65536.cint
211 |
212 | GODOT_PROPERTY_USAGE_DEFAULT_VALUE: cint =
213 | GODOT_PROPERTY_USAGE_STORAGE_VALUE or GODOT_PROPERTY_USAGE_EDITOR_VALUE or
214 | GODOT_PROPERTY_USAGE_NETWORK_VALUE
215 | GODOT_PROPERTY_USAGE_DEFAULT_INTL_VALUE: cint =
216 | GODOT_PROPERTY_USAGE_STORAGE_VALUE or
217 | GODOT_PROPERTY_USAGE_EDITOR_VALUE or GODOT_PROPERTY_USAGE_NETWORK_VALUE or
218 | GODOT_PROPERTY_USAGE_INTERNATIONALIZED_VALUE
219 | GODOT_PROPERTY_USAGE_NOEDITOR_VALUE: cint =
220 | GODOT_PROPERTY_USAGE_STORAGE_VALUE or GODOT_PROPERTY_USAGE_NETWORK_VALUE
221 |
222 | type
223 | GodotPropertyUsage* {.size: sizeof(cint), pure.} = enum
224 | Storage = GODOT_PROPERTY_USAGE_STORAGE_VALUE
225 | Editor = GODOT_PROPERTY_USAGE_EDITOR_VALUE
226 | Network = GODOT_PROPERTY_USAGE_NETWORK_VALUE
227 | NoEditor = GODOT_PROPERTY_USAGE_NOEDITOR_VALUE
228 | Default = GODOT_PROPERTY_USAGE_DEFAULT_VALUE
229 | EditorHelper = GODOT_PROPERTY_USAGE_EDITOR_HELPER_VALUE
230 | Checkable = GODOT_PROPERTY_USAGE_CHECKABLE_VALUE
231 | ## used for editing global variables
232 | Checked = GODOT_PROPERTY_USAGE_CHECKED_VALUE
233 | ## used for editing global variables
234 | Internationalized = GODOT_PROPERTY_USAGE_INTERNATIONALIZED_VALUE
235 | ## hint for internationalized strings
236 | DefaultIntl = GODOT_PROPERTY_USAGE_DEFAULT_INTL_VALUE
237 | Group = GODOT_PROPERTY_USAGE_GROUP_VALUE
238 | ## used for grouping props in the editor
239 | Category = GODOT_PROPERTY_USAGE_CATEGORY_VALUE
240 | NonZero = GODOT_PROPERTY_USAGE_STORE_IF_NONZERO_VALUE
241 | ## only store if nonzero
242 | NonOne = GODOT_PROPERTY_USAGE_STORE_IF_NONONE_VALUE
243 | ## only store if false
244 | NoInstanceState = GODOT_PROPERTY_USAGE_NO_INSTANCE_STATE_VALUE
245 | RestartIfChanged = GODOT_PROPERTY_USAGE_RESTART_IF_CHANGED_VALUE
246 | ScriptVariable = GODOT_PROPERTY_USAGE_SCRIPT_VARIABLE_VALUE
247 | StoreIfNull = GODOT_PROPERTY_USAGE_STORE_IF_NULL_VALUE
248 | AnimateAsTrigger = GODOT_PROPERTY_USAGE_ANIMATE_AS_TRIGGER_VALUE
249 | UpdateAllIfModified = GODOT_PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED_VALUE
250 |
251 | GodotPropertyAttributes* {.bycopy.} = object
252 | rsetType*: GodotMethodRPCMode
253 | typ*: cint
254 | hint*: GodotPropertyHint
255 | hintString*: GodotString
256 | usage*: cint
257 | defaultValue*: GodotVariant
258 |
259 | GodotInstanceCreateFunc* {.bycopy.} = object
260 | createFunc*:
261 | proc (obj: ptr GodotObject; methodData: pointer): pointer {.noconv.}
262 | ## returns user data
263 | methodData*: pointer
264 | freeFunc*: proc (a2: pointer) {.noconv.}
265 |
266 | GodotInstanceDestroyFunc* {.bycopy.} = object
267 | destroyFunc*:
268 | proc (obj: ptr GodotObject; methodData: pointer;
269 | userData: pointer) {.noconv.}
270 | methodData*: pointer
271 | freeFunc*: proc (a2: pointer) {.noconv.}
272 |
273 | GodotInstanceMethod* {.bycopy.} = object
274 | meth*:
275 | proc (obj: ptr GodotObject; methodData: pointer;
276 | userData: pointer; numArgs: cint;
277 | args: var array[MAX_ARG_COUNT, ptr GodotVariant]):
278 | GodotVariant {.noconv.}
279 | methodData*: pointer
280 | freeFunc*: proc (a2: pointer) {.noconv.}
281 |
282 | GodotPropertySetFunc* {.bycopy.} = object
283 | setFunc*: proc (obj: ptr GodotObject; methodData: pointer;
284 | userData: pointer; value: GodotVariant) {.noconv.}
285 | methodData*: pointer
286 | freeFunc*: proc (a2: pointer) {.noconv.}
287 |
288 | GodotPropertyGetFunc* {.bycopy.} = object
289 | getFunc*: proc (obj: ptr GodotObject; methodData: pointer;
290 | userData: pointer): GodotVariant {.noconv.}
291 | methodData*: pointer
292 | freeFunc*: proc (a2: pointer) {.noconv.}
293 |
294 | GodotSignalArgument* {.bycopy.} = object
295 | name*: GodotString
296 | typ*: cint
297 | hint*: GodotPropertyHint
298 | hintString*: GodotString
299 | usage*: cint
300 | defaultValue*: GodotVariant
301 |
302 | GodotSignal* = object
303 | name*: GodotString
304 | numArgs*: cint
305 | args*: ptr GodotSignalArgument
306 | numDefaultArgs*: cint
307 | defaultArgs*: ptr GodotVariant
308 |
309 | GodotClassConstructor* = proc (): ptr GodotObject {.
310 | noconv, gcsafe, locks: 0, raises: [], tags: [].}
311 |
312 | template offset*[T](p: ptr T, offset: int): ptr T =
313 | cast[ptr T](cast[ByteAddress](p) +% (offset * sizeof(T)))
--------------------------------------------------------------------------------
/godot/core/basis.nim:
--------------------------------------------------------------------------------
1 | # Copyright (c) 2018 Xored Software, Inc.
2 |
3 | import math, hashes
4 |
5 | import godotbase, vector3, quats
6 | import godotcoretypes
7 |
8 | {.push stackTrace: off.}
9 |
10 | proc setCells*(basis: var Basis, xx, xy, xz, yx, yy, yz, zx, zy, zz: float32) =
11 | basis.elements[0].x = xx
12 | basis.elements[0].y = xy
13 | basis.elements[0].z = xz
14 | basis.elements[1].x = yx
15 | basis.elements[1].y = yy
16 | basis.elements[1].z = yz
17 | basis.elements[2].x = zx
18 | basis.elements[2].y = zy
19 | basis.elements[2].z = zz
20 |
21 | proc `[]`*(self: Basis; row: range[0..2]): Vector3 {.inline.} =
22 | self.elements[row]
23 |
24 | proc `[]`*(self: var Basis; row: range[0..2]): var Vector3 {.inline.} =
25 | self.elements[row]
26 |
27 | proc `[]=`*(self: var Basis; row: range[0..2];
28 | value: Vector3) {.inline.} =
29 | self.elements[row] = value
30 |
31 | proc `==`*(self, other: Basis): bool =
32 | for i in 0..2:
33 | for j in 0..2:
34 | if self[i][j] != other[i][j]:
35 | return false
36 | result = true
37 |
38 | proc isEqualApprox*(self, other: Basis): bool =
39 | for i in 0..2:
40 | for j in 0..2:
41 | if not self[i][j].isEqualApprox(other[i][j]):
42 | return false
43 | result = true
44 |
45 | # column accessors
46 | proc x*(self: Basis): Vector3 {.inline.} =
47 | vec3(self.elements[0].x, self.elements[1].x, self.elements[2].x)
48 |
49 | proc y*(self: Basis): Vector3 {.inline.} =
50 | vec3(self.elements[0].y, self.elements[1].y, self.elements[2].y)
51 |
52 | proc z*(self: Basis): Vector3 {.inline.} =
53 | vec3(self.elements[0].z, self.elements[1].z, self.elements[2].z)
54 |
55 | proc tdotx*(self: Basis; v: Vector3): float32 {.inline.} =
56 | self.elements[0].x * v.x + self.elements[1].x * v.y + self.elements[2].x * v.z
57 |
58 | proc tdoty*(self: Basis; v: Vector3): float32 {.inline.} =
59 | self.elements[0].y * v.x + self.elements[1].y * v.y + self.elements[2].y * v.z
60 |
61 | proc tdotz*(self: Basis; v: Vector3): float32 {.inline.} =
62 | self.elements[0].z * v.x + self.elements[1].z * v.y + self.elements[2].z * v.z
63 |
64 | proc `+`*(self, other: Basis): Basis {.inline.} =
65 | result[0] = self[0] + other[0]
66 | result[1] = self[1] + other[1]
67 | result[2] = self[2] + other[2]
68 |
69 | proc `+=`*(self: var Basis, other: Basis) {.inline.} =
70 | self[0] += other[0]
71 | self[1] += other[1]
72 | self[2] += other[2]
73 |
74 | proc `-`*(self, other: Basis): Basis {.inline.} =
75 | result[0] = self[0] - other[0]
76 | result[1] = self[1] - other[1]
77 | result[2] = self[2] - other[2]
78 |
79 | proc `-=`*(self: var Basis, other: Basis) {.inline.} =
80 | self[0] -= other[0]
81 | self[1] -= other[1]
82 | self[2] -= other[2]
83 |
84 | proc `*`*(self, other: Basis): Basis {.inline.} =
85 | result.setCells(
86 | other.tdotx(self[0]), other.tdoty(self[0]), other.tdotz(self[0]),
87 | other.tdotx(self[1]), other.tdoty(self[1]), other.tdotz(self[1]),
88 | other.tdotx(self[2]), other.tdoty(self[2]), other.tdotz(self[2])
89 | )
90 |
91 | proc `*=`*(self: var Basis, other: Basis) {.inline.} =
92 | self.setCells(
93 | other.tdotx(self[0]), other.tdoty(self[0]), other.tdotz(self[0]),
94 | other.tdotx(self[1]), other.tdoty(self[1]), other.tdotz(self[1]),
95 | other.tdotx(self[2]), other.tdoty(self[2]), other.tdotz(self[2])
96 | )
97 |
98 | proc `*=`*(self: var Basis; b: float32) {.inline.} =
99 | self[0] *= b
100 | self[1] *= b
101 | self[2] *= b
102 |
103 | proc `*`*(self: Basis; b: float32): Basis {.inline.} =
104 | result = self
105 | result *= b
106 |
107 | proc initBasis*(): Basis {.inline.} =
108 | result.setCells(
109 | 1, 0, 0,
110 | 0, 1, 0,
111 | 0, 0, 1
112 | )
113 |
114 | proc initBasis*(row0, row1, row2: Vector3): Basis {.inline.} =
115 | Basis(elements: [row0, row1, row2])
116 |
117 | proc initBasis*(xx, xy, xz, yx, yy, yz, zx, zy, zz: float32): Basis =
118 | result.setCells(xx, xy, xz, yx, yy, yz, zx, zy, zz)
119 |
120 | proc initBasis*(euler: Quat): Basis {.inline.} =
121 | let d = euler.lengthSquared()
122 | let s = 2.0 / d
123 | let xs = euler.x * s
124 | let ys = euler.y * s
125 | let zs = euler.z * s
126 | let wx = euler.w * xs
127 | let wy = euler.w * ys
128 | let wz = euler.w * zs
129 | let xx = euler.x * xs
130 | let xy = euler.x * ys
131 | let xz = euler.x * zs
132 | let yy = euler.y * ys
133 | let yz = euler.y * zs
134 | let zz = euler.z * zs
135 | result.setCells(
136 | 1.0 - (yy + zz), xy - wz, xz + wy,
137 | xy + wz, 1.0 - (xx + zz), yz - wx,
138 | xz - wy, yz + wx, 1.0 - (xx + yy))
139 |
140 | proc setAxisAngle(self: var Basis, axis: Vector3, phi: float32) =
141 | assert(axis.isNormalized())
142 | let axisSq = vec3(axis.x * axis.x, axis.y * axis.y, axis.z * axis.z)
143 |
144 | let cosine = cos(phi);
145 | let sine = sin(phi);
146 |
147 | self.elements[0].x = axisSq.x + cosine * (1.0 - axisSq.x)
148 | self.elements[0].y = axis.x * axis.y * (1.0 - cosine) - axis.z * sine
149 | self.elements[0].z = axis.z * axis.x * (1.0 - cosine) + axis.y * sine
150 |
151 | self.elements[1].x = axis.x * axis.y * (1.0 - cosine) + axis.z * sine
152 | self.elements[1].y = axisSq.y + cosine * (1.0 - axisSq.y)
153 | self.elements[1].z = axis.y * axis.z * (1.0 - cosine) - axis.x * sine
154 |
155 | self.elements[2].x = axis.z * axis.x * (1.0 - cosine) - axis.y * sine
156 | self.elements[2].y = axis.y * axis.z * (1.0 - cosine) + axis.x * sine
157 | self.elements[2].z = axisSq.z + cosine * (1.0 - axisSq.z)
158 |
159 | proc initBasis*(axis: Vector3, phi: float32): Basis {.inline.} =
160 | result.setAxisAngle(axis, phi)
161 |
162 | proc setEuler*(self: var Basis, euler: Vector3) =
163 | var c = cos(euler.x)
164 | var s = sin(euler.x)
165 |
166 | let xmat = initBasis(1.0, 0.0, 0.0, 0.0, c, -s, 0.0, s, c)
167 |
168 | c = cos(euler.y)
169 | s = sin(euler.y)
170 | let ymat = initBasis(c, 0.0, s, 0.0, 1.0, 0.0, -s, 0.0, c)
171 |
172 | c = cos(euler.z)
173 | s = sin(euler.z)
174 | let zmat = initBasis(c, -s, 0.0, s, c, 0.0, 0.0, 0.0, 1.0)
175 |
176 | self = xmat * (ymat * zmat)
177 |
178 | proc getEuler*(self: Basis): Vector3 =
179 | result.y = arcsin(self.elements[0].z)
180 | if result.y < PI * 0.5:
181 | if result.y > -PI * 0.5:
182 | result.x = arctan2(-self.elements[1].z, self.elements[2].z)
183 | result.z = arctan2(-self.elements[0].y, self.elements[0].x)
184 | else:
185 | let r = arctan2(self.elements[1].x, self.elements[1].y)
186 | result.x = -r
187 | else:
188 | let r = arctan2(self.elements[0].y, self.elements[1].y)
189 | result.x = r
190 |
191 | proc initBasis*(euler: Vector3): Basis {.inline.} =
192 | result.setEuler(euler)
193 |
194 | proc outer*(self, other: Vector3): Basis {.inline.} =
195 | let row0 = vec3(self.x * other.x, self.x * other.y, self.x * other.z)
196 | let row1 = vec3(self.y * other.x, self.y * other.y, self.y * other.z)
197 | let row2 = vec3(self.z * other.x, self.z * other.y, self.z * other.z)
198 | initBasis(row0, row1, row2)
199 |
200 | proc toDiagonalMatrix*(self: Vector3): Basis {.inline.} =
201 | initBasis(
202 | self.x, 0, 0,
203 | 0, self.y, 0,
204 | 0, 0, self.z
205 | )
206 |
207 | proc `$`*(self: Basis): string {.inline.} =
208 | result = newStringOfCap(128)
209 | for i in 0..2:
210 | for j in 0..2:
211 | if i != 0 or j != 0:
212 | result.add(", ")
213 | result.add($self[i][j])
214 |
215 | proc hash*(self: Basis): Hash {.inline.} =
216 | !$(self.elements[0].hash() !& self.elements[1].hash() !& self.elements[2].hash())
217 |
218 | template cofac(row1, col1, row2, col2: int): float32 =
219 | self.elements[row1][col1] * self.elements[row2][col2] -
220 | self.elements[row1][col2] * self.elements[row2][col1]
221 |
222 | proc determinant(self: Basis): float32 {.inline.} =
223 | self[0][0] * cofac(1, 1, 2, 2) -
224 | self[1][0] * cofac(0, 1, 2, 2) +
225 | self[2][0] * cofac(0, 1, 1, 2)
226 |
227 | proc invert*(self: var Basis) =
228 | let co = [cofac(1, 1, 2, 2), cofac(1, 2, 2, 0), cofac(1, 0, 2, 1)]
229 | let det = self.elements[0][0] * co[0] +
230 | self.elements[0][1] * co[1] +
231 | self.elements[0][2] * co[2]
232 | assert(det != 0)
233 | let s = 1.0'f32 / det
234 | self.setCells(
235 | co[0] * s, cofac(0, 2, 2, 1) * s, cofac(0, 1, 1, 2) * s,
236 | co[1] * s, cofac(0, 0, 2, 2) * s, cofac(0, 2, 1, 0) * s,
237 | co[2] * s, cofac(0, 1, 2, 0) * s, cofac(0, 0, 1, 1) * s
238 | )
239 |
240 | proc inverse*(self: Basis): Basis {.inline.} =
241 | result = self
242 | result.invert()
243 |
244 | proc axis*(self: Basis; idx: range[0..2]): Vector3 {.inline.} =
245 | vec3(self[0][idx], self[1][idx], self[2][idx])
246 |
247 | proc setAxis*(self: var Basis; idx: range[0..2]; value: Vector3) {.inline.} =
248 | self.elements[0][idx] = value.x
249 | self.elements[1][idx] = value.y
250 | self.elements[2][idx] = value.z
251 |
252 | proc row*(self: Basis; row: range[0..2]): Vector3 {.inline.} =
253 | self.elements[row]
254 |
255 | proc setRow*(self: var Basis; row: range[0..2]; value: Vector3) {.inline.} =
256 | self.elements[row] = value
257 |
258 | proc getMainDiagonal*(self: Basis): Vector3 {.inline.} =
259 | vec3(self.elements[0][0], self.elements[1][1], self.elements[2][2])
260 |
261 | proc zero*(self: var Basis) {.inline.} =
262 | self.elements[0].zero()
263 | self.elements[1].zero()
264 | self.elements[2].zero()
265 |
266 | proc orthonormalize(self: var Basis) =
267 | var x = self.axis(0)
268 | var y = self.axis(1)
269 | var z = self.axis(2)
270 |
271 | x.normalize()
272 | y = y - x * x.dot(y)
273 | y.normalize()
274 | z = z - x * x.dot(z) - y * y.dot(z)
275 | z.normalize()
276 |
277 | self.setAxis(0, x)
278 | self.setAxis(1, y)
279 | self.setAxis(2, z)
280 |
281 | proc orthonormalized*(self: Basis): Basis {.inline.} =
282 | result = self
283 | result.orthonormalize()
284 |
285 | proc transpose*(self: var Basis) {.inline.} =
286 | swap(self.elements[0].y, self.elements[1].x)
287 | swap(self.elements[0].z, self.elements[2].x)
288 | swap(self.elements[1].z, self.elements[2].y)
289 |
290 | proc transposed*(self: Basis): Basis {.inline.} =
291 | result = self
292 | result.transpose()
293 |
294 | proc isOrthogonal*(self: Basis): bool {.inline.} =
295 | let id = initBasis()
296 | let m = self * self.transposed()
297 | result = id.isEqualApprox(m)
298 |
299 | proc isRotation*(self: Basis): bool {.inline.} =
300 | self.determinant().isEqualApprox(1.0) and self.isOrthogonal()
301 |
302 | proc isSymmetric*(self: Basis): bool {.inline.} =
303 | if not self.elements[0][1].isEqualApprox(self.elements[1][0]):
304 | return false
305 | if not self.elements[0][2].isEqualApprox(self.elements[2][0]):
306 | return false
307 | if not self.elements[1][2].isEqualApprox(self.elements[2][1]):
308 | return false
309 | result = true
310 |
311 | proc scale*(self: var Basis, scale: Vector3) =
312 | self[0].x *= scale.x
313 | self[0].y *= scale.x
314 | self[0].z *= scale.x
315 | self[1].x *= scale.y
316 | self[1].y *= scale.y
317 | self[1].z *= scale.y
318 | self[2].x *= scale.z
319 | self[2].y *= scale.z
320 | self[2].z *= scale.z
321 |
322 | proc scaled*(self: Basis, scale: Vector3): Basis =
323 | result = self
324 | result.scale(scale)
325 |
326 | proc rotated*(self: Basis; axis: Vector3; phi: float32): Basis {.inline.} =
327 | initBasis(axis, phi) * self
328 |
329 | proc rotate*(self: var Basis; axis: Vector3; phi: float32) {.inline.} =
330 | self = self.rotated(axis, phi)
331 |
332 | proc rotated*(self: Basis; euler: Vector3): Basis {.inline.} =
333 | initBasis(euler) * self
334 |
335 | proc rotate*(self: var Basis; euler: Vector3) {.inline.} =
336 | self = self.rotated(euler)
337 |
338 | proc getScale*(self: Basis): Vector3 =
339 | let detSign = if self.determinant() > 0: 1'f32 else: -1'f32
340 | result = detSign * vec3(
341 | vec3(self.elements[0].x, self.elements[1].x, self.elements[2].x).length(),
342 | vec3(self.elements[0].y, self.elements[1].y, self.elements[2].y).length(),
343 | vec3(self.elements[0].z, self.elements[1].z, self.elements[2].z).length(),
344 | )
345 |
346 | proc getRotation*(self: Basis): Vector3 {.inline.} =
347 | var m = self.orthonormalized()
348 | let det = m.determinant()
349 | if det < 0:
350 | m.scale(vec3(-1, -1, -1))
351 | result = m.getEuler()
352 |
353 | proc setScale*(self: var Basis; scale: Vector3) =
354 | let e = self.getEuler()
355 | self = initBasis() # reset to identity
356 | self.scale(scale)
357 | self.rotate(e)
358 |
359 | proc setRotationEuler*(self: var Basis; euler: Vector3) =
360 | let s = self.getScale()
361 | self = initBasis()
362 | self.scale(s)
363 | self.rotate(euler)
364 |
365 | proc setRotationAxisAngle*(self: var Basis; axis: Vector3; angle: float32) =
366 | let s = self.getScale()
367 | self = initBasis()
368 | self.scale(s)
369 | self.rotate(axis, angle)
370 |
371 | proc asQuat*(self: Basis): Quat =
372 | let trace = self.elements[0].x + self.elements[1].y + self.elements[2].z
373 | var temp: array[4, float32]
374 | if trace > 0'f32:
375 | var s = sqrt(trace + 1.0)
376 | temp[3] = s * 0.5
377 | s = 0.5 / s
378 |
379 | temp[0] = (self.elements[2].y - self.elements[1].z) * s
380 | temp[1] = (self.elements[0].z - self.elements[2].x) * s
381 | temp[2] = (self.elements[1].x - self.elements[0].y) * s
382 | else:
383 | let i = if self.elements[0].x < self.elements[1].y:
384 | if self.elements[1].y < self.elements[2].z: 2 else: 1
385 | else:
386 | if self.elements[0].x < self.elements[2].z: 2 else: 0
387 | let j = (i + 1) mod 3
388 | let k = (i + 2) mod 3
389 |
390 | var s = sqrt(self.elements[i][i] - self.elements[j][j] -
391 | self.elements[k][k] + 1.0)
392 | temp[i] = s * 0.5
393 | s = 0.5 / s
394 |
395 | temp[3] = (self.elements[k][j] - self.elements[j][k]) * s
396 | temp[j] = (self.elements[j][i] + self.elements[i][j]) * s
397 | temp[k] = (self.elements[k][i] + self.elements[i][k]) * s
398 |
399 | result = initQuat(temp[0], temp[1], temp[2], temp[3])
400 |
401 | proc xform*(self: Basis; v: Vector3): Vector3 {.inline.} =
402 | vec3(
403 | self.elements[0].dot(v),
404 | self.elements[1].dot(v),
405 | self.elements[2].dot(v)
406 | )
407 |
408 | proc xformInv*(self: Basis; v: Vector3): Vector3 {.inline.} =
409 | vec3(
410 | self.elements[0].x * v.x + self.elements[1].x * v.y + self.elements[2].x * v.z,
411 | self.elements[0].y * v.x + self.elements[1].y * v.y + self.elements[2].y * v.z,
412 | self.elements[0].z * v.x + self.elements[1].z * v.y + self.elements[2].z * v.z,
413 | )
414 |
415 | const orthoBases = [
416 | initBasis(1, 0, 0, 0, 1, 0, 0, 0, 1),
417 | initBasis(0, -1, 0, 1, 0, 0, 0, 0, 1),
418 | initBasis(-1, 0, 0, 0, -1, 0, 0, 0, 1),
419 | initBasis(0, 1, 0, -1, 0, 0, 0, 0, 1),
420 | initBasis(1, 0, 0, 0, 0, -1, 0, 1, 0),
421 | initBasis(0, 0, 1, 1, 0, 0, 0, 1, 0),
422 | initBasis(-1, 0, 0, 0, 0, 1, 0, 1, 0),
423 | initBasis(0, 0, -1, -1, 0, 0, 0, 1, 0),
424 | initBasis(1, 0, 0, 0, -1, 0, 0, 0, -1),
425 | initBasis(0, 1, 0, 1, 0, 0, 0, 0, -1),
426 | initBasis(-1, 0, 0, 0, 1, 0, 0, 0, -1),
427 | initBasis(0, -1, 0, -1, 0, 0, 0, 0, -1),
428 | initBasis(1, 0, 0, 0, 0, 1, 0, -1, 0),
429 | initBasis(0, 0, -1, 1, 0, 0, 0, -1, 0),
430 | initBasis(-1, 0, 0, 0, 0, -1, 0, -1, 0),
431 | initBasis(0, 0, 1, -1, 0, 0, 0, -1, 0),
432 | initBasis(0, 0, 1, 0, 1, 0, -1, 0, 0),
433 | initBasis(0, -1, 0, 0, 0, 1, -1, 0, 0),
434 | initBasis(0, 0, -1, 0, -1, 0, -1, 0, 0),
435 | initBasis(0, 1, 0, 0, 0, -1, -1, 0, 0),
436 | initBasis(0, 0, 1, 0, -1, 0, 1, 0, 0),
437 | initBasis(0, 1, 0, 0, 0, 1, 1, 0, 0),
438 | initBasis(0, 0, -1, 0, 1, 0, 1, 0, 0),
439 | initBasis(0, -1, 0, 0, 0, -1, 1, 0, 0)
440 | ]
441 |
442 | proc orthogonalIndex*(self: Basis): int =
443 | var orth = self
444 | for i in 0..2:
445 | for j in 0..2:
446 | var v = orth[i][j]
447 | if v > 0.5:
448 | v = 1.0'f32
449 | elif v < -0.5:
450 | v = -1.0'f32
451 | else:
452 | v = 0'f32
453 | orth[i][j] = v
454 |
455 | for idx, base in orthoBases:
456 | if base == orth:
457 | return idx
458 |
459 | proc setOrthogonalIndex*(self: var Basis, idx: range[0..23]) =
460 | self = orthoBases[idx]
461 |
462 | proc rotate*(self: var Vector3; axis: Vector3; phi: float32) =
463 | self = initBasis(axis, phi).xform(self)
464 |
465 | proc rotated*(self: Vector3; axis: Vector3; phi: float32): Vector3 =
466 | result = self
467 | result.rotate(axis, phi)
468 |
469 | {.pop.} # stackTrace: off
470 |
--------------------------------------------------------------------------------
/godot/nim/godotmacros.nim:
--------------------------------------------------------------------------------
1 | # Copyright 2018 Xored Software, Inc.
2 |
3 | import macros, tables, typetraits, strutils, sets, sequtils, options, algorithm
4 | import godotinternal, internal/godotvariants
5 | import godotnim, core/variants
6 |
7 | type
8 | VarDecl = ref object
9 | name: NimNode
10 | typ: NimNode
11 | defaultValue: NimNode
12 | isNoGodot: bool
13 | hint: Option[string]
14 | hintStr: Option[string]
15 | usage: NimNode
16 | isExported: bool
17 |
18 | MethodDecl = ref object
19 | name: string
20 | args: seq[VarDecl]
21 | isVirtual: bool
22 | returnType: NimNode
23 | nimNode: NimNode
24 | isNoGodot: bool
25 |
26 | ObjectDecl = ref object
27 | name: string
28 | parentName: string
29 | fields: seq[VarDecl]
30 | methods: seq[MethodDecl]
31 | isTool: bool
32 |
33 | include "internal/backwardcompat.inc.nim"
34 |
35 | proc godotToNim[T](val: Variant): (T, ConversionResult) =
36 | mixin fromVariant
37 | result[1] = fromVariant(result[0], val)
38 |
39 | proc nimToGodot[T](val: T): Variant =
40 | mixin toVariant
41 | when compiles(toVariant(val)):
42 | result = toVariant(val)
43 | else:
44 | const err = "Cannot convert Nim value of type " & T.name &
45 | " into Variant"
46 | {.error: err.}
47 |
48 | proc extractNames(definition: NimNode):
49 | tuple[name, parentName: string] =
50 | if definition.kind == nnkIdent:
51 | result.name = definition.strVal
52 | else:
53 | if not (definition.kind == nnkInfix and
54 | definition[0].strVal == "of"):
55 | error("invalid type definition", definition)
56 | result.name = definition[1].strVal
57 | case definition[2].kind:
58 | of nnkIdent:
59 | result.parentName = definition[2].strVal
60 | else:
61 | error("parent type expected", definition[2])
62 |
63 | when not declared(newRStrLit):
64 | proc newRStrLit(s: string): NimNode {.compileTime.} =
65 | result = newNimNode(nnkRStrLit)
66 | result.strVal = s
67 |
68 | proc newCStringLit(s: string): NimNode {.compileTime.} =
69 | newNimNode(nnkCallStrLit).add(ident("cstring"), newRStrLit(s))
70 |
71 | iterator pragmas(node: NimNode):
72 | tuple[key: string, value: NimNode, index: int] =
73 | assert node.kind in {nnkPragma, nnkEmpty}
74 | for index in countdown(node.len - 1, 0):
75 | if node[index].kind == nnkExprColonExpr:
76 | yield (node[index][0].strVal, node[index][1], index)
77 | elif node[index].kind == nnkIdent:
78 | yield (node[index].strVal, nil, index)
79 |
80 | proc removePragmaNode(statement: NimNode,
81 | pname: string): NimNode {.compileTime.} =
82 | ## Removes the pragma from the node and returns value of the pragma
83 | ## Works for routine nodes or nnkPragmaExpr
84 | if not (RoutineNodes.contains(statement.kind) or
85 | statement.kind == nnkPragmaExpr):
86 | return nil
87 |
88 | result = nil
89 | var pragmas = if RoutineNodes.contains(statement.kind): statement.pragma()
90 | else: statement[1]
91 | for ident, val, i in pragmas(pragmas):
92 | if ident.eqIdent(pname):
93 | pragmas.del(i)
94 | return val
95 |
96 | proc removePragma(statement: NimNode, pname: string): bool =
97 | ## Removes the pragma from the node and returns whether pragma was removed
98 | if not (RoutineNodes.contains(statement.kind) or
99 | statement.kind == nnkPragmaExpr):
100 | return false
101 | var pragmas = if RoutineNodes.contains(statement.kind): statement.pragma()
102 | else: statement[1]
103 | for ident, val, i in pragmas(pragmas):
104 | if ident.eqIdent(pname):
105 | pragmas.del(i)
106 | return true
107 |
108 | proc removeStrPragma(statement: NimNode,
109 | pname: string): Option[string] {.compileTime.} =
110 | ## Removes the pragma from the node and returns value of the pragma
111 | ## Works for routine nodes or nnkPragmaExpr
112 | let node = removePragmaNode(statement, pname)
113 | result = if node.isNil: none(string)
114 | else: some($node)
115 |
116 | proc isExported(node: NimNode): bool {.compileTime.} =
117 | if node.kind == nnkPragmaExpr:
118 | result = isExported(node[0])
119 | elif node.kind == nnkPostfix:
120 | result = ($node[0] == "*")
121 |
122 | proc identDefsToVarDecls(identDefs: NimNode): seq[VarDecl] =
123 | assert(identDefs.kind == nnkIdentDefs)
124 | result = newSeqOfCap[VarDecl](identDefs.len - 2)
125 |
126 | var typ = identDefs[identDefs.len - 2]
127 | if typ.kind == nnkEmpty:
128 | let defaultValue = identDefs[identDefs.len - 1]
129 | if defaultValue.kind != nnkEmpty:
130 | typ = newCall("type", defaultValue)
131 |
132 | for i in 0..<(identDefs.len - 2):
133 | let nameNode = identDefs[i].copyNimTree()
134 | let hint = removeStrPragma(nameNode, "hint")
135 | let hintStr = removeStrPragma(nameNode, "hintStr")
136 | let usage = removePragmaNode(nameNode, "usage")
137 | let isGdExport = removePragma(nameNode, "gdExport")
138 |
139 | result.add(VarDecl(
140 | name: if nameNode.kind == nnkPragmaExpr: nameNode[0].basename()
141 | else: nameNode.basename(),
142 | typ: typ,
143 | defaultValue: identDefs[identDefs.len - 1],
144 | hint: hint,
145 | hintStr: hintStr,
146 | isNoGodot: not isGdExport,
147 | usage: usage,
148 | isExported: nameNode.isExported()
149 | ))
150 |
151 | proc parseMethod(meth: NimNode): MethodDecl =
152 | assert(meth.kind in {nnkProcDef, nnkMethodDef})
153 | let isGdExport = removePragma(meth, "gdExport")
154 | let isNoGodot = (meth.kind != nnkMethodDef and not isGdExport) or
155 | removePragma(meth, "noGdExport")
156 | result = MethodDecl(
157 | name: $meth[0].basename,
158 | args: newSeq[VarDecl](),
159 | returnType: meth[3][0],
160 | isVirtual: meth.kind == nnkMethodDef,
161 | isNoGodot: isNoGodot,
162 | nimNode: meth
163 | )
164 | for i in 1..`_:
675 | ##
676 | ## .. code-block:: nim
677 | ## import godot, editor_plugin
678 | ##
679 | ## gdobj(MyTool of EditorPlugin, tool):
680 | ## method enterTree*() =
681 | ## print("MyTool initialized!")
682 | ##
683 | ## Objects can be instantiated by invoking
684 | ## `gdnew `_ or by using
685 | ## `load `_ or any other way
686 | ## that you can find in `Godot API `_.
687 | let typeDef = parseType(ast)
688 | result = genType(typeDef)
689 |
--------------------------------------------------------------------------------
/godot/nim/godotnim.nim:
--------------------------------------------------------------------------------
1 | # Copyright 2018 Xored Software, Inc.
2 |
3 | import tables, typetraits, macros, unicode, strutils, sets, options
4 | import gdnativeapi
5 | import core/godotcoretypes, core/godotbase
6 | import core/vector2, core/rect2,
7 | core/vector3, core/transform2d,
8 | core/planes, core/quats, core/aabb,
9 | core/basis, core/transforms, core/colors,
10 | core/nodepaths, core/rids, core/dictionaries,
11 | core/arrays, core/poolarrays, core/variants
12 | import godotinternal
13 |
14 | ## This module defines ``NimGodotObject`` and ``toVariant``/``fromVariant``
15 | ## converters for Nim types. The converters are used by
16 | ## `gdobj `_ macro to import/export
17 | ## values from/to Godot (editor, GDScript).
18 | ##
19 | ## You can also allow conversion of any custom type ``MyType`` by implementing:
20 | ##
21 | ## .. code-block:: nim
22 | ## proc godotTypeInfo*(T: typedesc[MyType]): GodotTypeInfo
23 | ## proc toVariant*(self: MyType): Variant
24 | ## proc fromVariant*(self: var MyType, val: Variant): ConversionResult
25 | ##
26 | ## Implementing ``godotTypeInfo`` is optional and is necessary only if you want
27 | ## the type to be editable from the editor.
28 |
29 | type
30 | NimGodotObject* = ref object of RootObj
31 | ## The base type all Godot types inherit from.
32 | ## Manages lifecycle of the wrapped ``GodotObject``.
33 | godotObject: ptr GodotObject
34 | linkedObjectPtr: pointer
35 | ## Wrapper around native object that is the container of the Nim "script"
36 | ## This is needed for `of` checks and `as` conversions to work as
37 | ## expected. For example, Nim type may inherit from ``Spatial``, but the
38 | ## script is attached to ``Particles``. In this case conversion to
39 | ## ``Particles`` is valid, but Nim type system is not aware of that.
40 | ## This works in both directions - for linked native object this
41 | ## reference points to Nim object.
42 | ## This is stored as a raw pointer to avoid reference cycles and therefore
43 | ## improve GC performance.
44 | isRef*: bool
45 | isFinalized: bool
46 | isNative: bool
47 |
48 | ConversionResult* {.pure.} = enum
49 | ## Conversion result to return from ``fromVariant`` procedure.
50 | OK,
51 | TypeError,
52 | ## Type mismatch
53 | RangeError
54 | ## Types match, but the value is out of range.
55 | ## Mainly used for numeric (ordinal) types.
56 |
57 | SomeUnsignedInt = uint8 or uint16 or uint32 or uint64 or uint or cuint
58 | SomeSignedInt = int8 or int16 or int32 or int64 or int or cint
59 | SomeFloat = float32 or float64 or cfloat
60 |
61 | SomeGodot = bool or Vector2 or Rect2 or Vector3 or
62 | Transform2D or Plane or Quat or AABB or
63 | Basis or Transform or Color or NodePath or
64 | RID or GodotObject or Dictionary or Array or
65 | PoolByteArray or PoolIntArray or PoolRealArray or
66 | PoolStringArray or PoolVector2Array or PoolVector3Array or
67 | PoolColorArray or GodotString
68 |
69 | SomeGodotOrNum = SomeGodot or SomeSignedInt or SomeUnsignedInt or SomeFloat
70 |
71 | CallError* = object of Exception
72 | ## Raised by wrappers in case of an incorrect dynamic invocation.
73 | ## For example, if incorrect number of arguments were passed or they had
74 | ## unexpected types.
75 | err*: VariantCallError
76 | ## The error as returned by Godot
77 |
78 | ObjectInfo = object
79 | constructor: proc(): NimGodotObject {.gcsafe, nimcall.}
80 | baseNativeClass: cstring
81 | isNative: bool
82 | isRef: bool
83 |
84 | GodotTypeInfo* = object
85 | ## Type information provided to Godot editor
86 | variantType*: VariantType
87 | hint*: GodotPropertyHint
88 | hintStr*: string
89 | ## Format depends on the type and the hint.
90 | ## For example, for Enum ``hint`` this is a comma separated list of
91 | ## values.
92 | ## See documentation of ``GodotPropertyHint`` for description of formats.
93 |
94 | FNV1Hash = uint32
95 |
96 | include "internal/backwardcompat.inc.nim"
97 |
98 | proc isFinalized*(obj: NimGodotObject): bool {.inline.} =
99 | obj.isFinalized
100 |
101 | var classRegistry {.threadvar.}: TableRef[FNV1Hash, ObjectInfo]
102 | var classRegistryStatic* {.compileTime.}: TableRef[FNV1Hash, ObjectInfo]
103 | ## Compile-time variable used for implementation of several procedures
104 | ## and macros
105 | static:
106 | classRegistryStatic = newTable[FNV1Hash, ObjectInfo]()
107 |
108 | var nativeClasses {.compileTime.} = newSeq[string]()
109 | var refClasses* {.compileTime.} = newSeq[string]()
110 |
111 | template initFNV1Hash(hash: var FNV1Hash) =
112 | hash = 0x811c9dc5'u32
113 |
114 | template appendFNV1Hash(hash: var FNV1Hash, val: uint8) =
115 | block:
116 | let u64hash = hash.uint64
117 | hash = ((
118 | u64hash +
119 | (u64hash shl 1'u64) +
120 | (u64hash shl 4'u64) +
121 | (u64hash shl 7'u64) +
122 | (u64hash shl 8'u64) +
123 | (u64hash shl 24'u64)) and 0xFFFFFFFF'u32).uint32 xor val
124 |
125 | {.push stackTrace:off.}
126 | proc lsb(c: ptr cwchar_t): char {.noinit, inline.} =
127 | {.emit: [result, " = (char)(", c[]," & 0xFF);"]}
128 | {.pop.}
129 |
130 | proc fnv1Hash(godotClassName: GodotString): FNV1Hash =
131 | var charsCount = godotClassName.len
132 | let charsPtr = godotClassName.dataPtr
133 | if charsCount > 2 and
134 | charsPtr.offset(charsCount - 2).lsb == 'S' and
135 | charsPtr.offset(charsCount - 1).lsb == 'W':
136 | charsCount -= 2
137 |
138 | initFNV1Hash(result)
139 | for i in 0..= charsCount:
152 | break
153 | let firstByte = uint8(rune.uint64 and 0xFF'u64)
154 | appendFNV1Hash(result, firstByte)
155 | # We don't really need to calculate hash of other bytes,
156 | # since we only use hashes of ASCII strings
157 | inc i
158 |
159 | proc getClassName*(o: NimGodotObject): string =
160 | o.godotObject.getClassName()
161 |
162 | var unreferenceMethodBind {.threadvar.}: ptr GodotMethodBind
163 | proc unreference(o: ptr GodotObject): bool =
164 | if isNil(unreferenceMethodBind):
165 | unreferenceMethodBind = getMethod(cstring"Reference",
166 | cstring"unreference")
167 | unreferenceMethodBind.ptrCall(o, nil, addr(result))
168 |
169 | var referenceMethodBind {.threadvar.}: ptr GodotMethodBind
170 | proc reference(o: ptr GodotObject): bool {.discardable.} =
171 | if isNil(referenceMethodBind):
172 | referenceMethodBind = getMethod(cstring"Reference",
173 | cstring"reference")
174 | referenceMethodBind.ptrCall(o, nil, addr result)
175 |
176 | var initRefMethodBind {.threadvar.}: ptr GodotMethodBind
177 | proc initRef(o: ptr GodotObject): bool {.discardable.} =
178 | if isNil(initRefMethodBind):
179 | initRefMethodBind = getMethod(cstring"Reference",
180 | cstring"init_ref")
181 | initRefMethodBind.ptrCall(o, nil, addr result)
182 |
183 | proc deinit*(obj: NimGodotObject) =
184 | ## Destroy the object. You only need to call this for objects not inherited
185 | ## from Reference, where manual lifecycle control is necessary.
186 | assert(not obj.godotObject.isNil)
187 | obj.godotObject.deinit()
188 | obj.godotObject = nil
189 |
190 | proc linkedObject(obj: NimGodotObject): NimGodotObject {.inline.} =
191 | cast[NimGodotObject](obj.linkedObjectPtr)
192 |
193 | proc nimGodotObjectFinalizer*[T: NimGodotObject](obj: T) =
194 | if obj.godotObject.isNil or obj.isNative: return
195 | # important to set it before so that ``unreference`` is aware
196 | obj.isFinalized = true
197 | if (obj.isRef or not obj.linkedObject.isNil and obj.linkedObject.isRef) and
198 | obj.godotObject.unreference():
199 | if not obj.linkedObject.isNil:
200 | GC_unref(obj.linkedObject)
201 | obj.deinit()
202 |
203 | macro baseNativeType(T: typedesc): cstring =
204 | var t = getType(getType(T)[1][1])
205 | var baseT: string
206 | while true:
207 | let typeName = ($t[1][1]).split(':')[0]
208 | if typeName in nativeClasses:
209 | baseT = typeName
210 | break
211 | if typeName == "NimGodotObject":
212 | break
213 | t = getType(t[1][1])
214 | if baseT.len == 0:
215 | result = newNilLit()
216 | else:
217 | let rStr = newNimNode(nnkRStrLit)
218 | rStr.strVal = baseT
219 | result = newNimNode(nnkCallStrLit).add(ident("cstring"), rStr)
220 |
221 | proc inherits(t: NimNode, parent: string): bool {.compileTime.} =
222 | var curT = t
223 | while true:
224 | let typeName = ($curT[1][1]).split(':')[0]
225 | if typeName == parent:
226 | return true
227 | if typeName == "NimGodotObject":
228 | break
229 | curT = getType(curT[1][1])
230 |
231 | macro isReference(T: typedesc): bool =
232 | result = if inherits(getType(T), "Reference"): ident("true")
233 | else: ident("false")
234 |
235 | macro isResource(T: typedesc): bool =
236 | result = if inherits(getType(T), "Resource"): ident("true")
237 | else: ident("false")
238 |
239 | template registerClass*(T: typedesc; godotClassName: string or cstring,
240 | native: bool) =
241 | ## Registers the specified Godot type.
242 | ## Used by ``gdobj`` macro and `godotapigen `_.
243 | if classRegistry.isNil:
244 | classRegistry = newTable[FNV1Hash, ObjectInfo]()
245 | let constructor = proc(): NimGodotObject =
246 | var t: T
247 | new(t, nimGodotObjectFinalizer[T])
248 | result = t
249 |
250 | const base = baseNativeType(T)
251 | const isRef: bool = isReference(T)
252 | let objInfo = ObjectInfo(
253 | constructor: constructor,
254 | baseNativeClass: base,
255 | isNative: native,
256 | isRef: isRef
257 | )
258 | classRegistry[fnv1Hash($godotClassName)] = objInfo
259 | static:
260 | let objInfoStatic = ObjectInfo(
261 | baseNativeClass: base,
262 | isNative: native,
263 | isRef: isRef,
264 | )
265 | let nameHash = fnv1Hash($godotClassName)
266 | if not classRegistryStatic.contains(nameHash):
267 | classRegistryStatic[nameHash] = objInfoStatic
268 | elif not endsWith($godotClassName, "SW"):
269 | # For simplicity we assume that all class names must have
270 | # different hashes
271 | # If this exception is ever raised, I guess, we should
272 | # implement a proper collision resolving
273 | raise newException(Exception, "Hash collision " & $godotClassName)
274 | when isRef:
275 | static:
276 | refClasses.add(T.name)
277 | when native:
278 | static:
279 | nativeClasses.add(T.name)
280 |
281 | proc newNimGodotObject[T: NimGodotObject](
282 | godotObject: ptr GodotObject, godotClassName: GodotString, noRef: bool): T =
283 | assert(not classRegistry.isNil)
284 | assert(not godotObject.isNil)
285 | let objInfo = classRegistry.getOrDefault(fnv1Hash(godotClassName))
286 | if objInfo.constructor.isNil:
287 | printError("Nim constructor not found for class " & $godotClassName)
288 | else:
289 | result = T(objInfo.constructor())
290 | result.godotObject = godotObject
291 | result.isRef = objInfo.isRef
292 | if not noRef and objInfo.isRef:
293 | result.godotObject.reference()
294 |
295 | proc asNimGodotObject*[T: NimGodotObject](
296 | godotObject: ptr GodotObject, forceNativeObject, noRef: bool = false): T =
297 | ## Wraps ``godotObject`` into Nim type ``T``.
298 | ## This is used by `godotapigen `_ and should rarely be
299 | ## used by anything else.
300 | if godotObject.isNil: return nil
301 | let userDataPtr = godotObject.getUserData()
302 | if not userDataPtr.isNil and not forceNativeObject:
303 | result = cast[T](userDataPtr)
304 | if result.godotObject != godotObject:
305 | # Could be data from other bindings
306 | result = nil
307 | if result.isNil:
308 | var classNameStr = godotObject.getClassNameRaw()
309 | result = newNimGodotObject[T](
310 | godotObject, classNameStr,
311 | forceNativeObject or noRef)
312 | deinit(classNameStr)
313 |
314 | proc newVariant*(obj: NimGodotObject): Variant {.inline.} =
315 | newVariant(obj.godotObject)
316 |
317 | proc asObject*[T: NimGodotObject](v: Variant): T {.inline.} =
318 | ## Converts ``v`` to object of type ``T``.
319 | ## Returns ``nil`` if the conversion cannot be performed
320 | ## (``v``'s type is not an Object or it's an object of an incompatible type)
321 | asNimGodotObject[T](v.asGodotObject())
322 |
323 | proc asObject*(v: Variant, T: typedesc[NimGodotObject]): T {.inline.} =
324 | ## Converts ``v`` to object of type ``T``.
325 | ## Returns ``nil`` if the conversion cannot be performed
326 | ## (``v``'s type is not an Object or it's an object of an incompatible type)
327 | asNimGodotObject[T](v.asGodotObject())
328 |
329 | proc `as`*[T: NimGodotObject](obj: NimGodotObject, t: typedesc[T]): T =
330 | ## Converts the ``obj`` into the specified type.
331 | ## Returns ``nil`` if the conversion cannot be performed
332 | ## (the ``obj`` is not of the type ``T``)
333 | ##
334 | ## This can be used either in dot notation (``node.as(Button)``) or
335 | ## infix notation (``node as Button``).
336 | if obj.isNil: return nil
337 | if system.`of`(obj, T):
338 | result = T(obj)
339 | elif not obj.linkedObject.isNil and system.`of`(obj.linkedObject, T):
340 | result = T(obj.linkedObject)
341 | else:
342 | result = nil
343 |
344 | proc `of`*[T1, T2: NimGodotObject](obj: T1, t: typedesc[T2]): bool {.inline.} =
345 | ## Godot-specific inheritance check.
346 | not obj.isNil and (system.`of`(obj, T2) or system.`of`(obj.linkedObject, T2))
347 |
348 | proc newRStrLit(s: string): NimNode {.compileTime.} =
349 | result = newNimNode(nnkRStrLit)
350 | result.strVal = s
351 |
352 | macro toGodotName(T: typedesc): untyped =
353 | if T is GodotString or T is string:
354 | newStrLitNode"String"
355 | elif T is SomeFloat:
356 | newStrLitNode"float"
357 | elif T is SomeUnsignedInt or T is SomeSignedInt:
358 | newStrLitNode"int"
359 | else:
360 | let nameStr = ((T.getType()[1][1].strVal).split(':')[0])
361 | case nameStr:
362 | of "File", "Directory", "Thread", "Mutex", "Semaphore":
363 | newStrLitNode("_" & nameStr)
364 | else:
365 | newStrLitNode(nameStr)
366 |
367 | macro asCString(s: static[string]): cstring =
368 | result = newNimNode(nnkCallStrLit).add(
369 | ident("cstring"), newRStrLit(s))
370 |
371 | proc getSingleton*[T: NimGodotObject](): T =
372 | ## Returns singleton of type ``T``. Normally, this should not be used,
373 | ## because `godotapigen `_ wraps singleton methods so that
374 | ## singleton objects don't have to be provided as parameters.
375 | const godotName = asCString(toGodotName(T))
376 | let singleton = getGodotSingleton(godotName)
377 | if singleton.isNil:
378 | printError("Tried to get non-existing singleton of type " & $godotName)
379 | else:
380 | result = asNimGodotObject[T](singleton)
381 |
382 | var gdNativeLibraryObj: ptr GodotObject
383 |
384 | var setClassNameMethod: ptr GodotMethodBind
385 | var setLibraryMethod: ptr GodotMethodBind
386 | var newMethod: ptr GodotMethodBind
387 | type
388 | PtrCallArgType = ptr array[MAX_ARG_COUNT, pointer]
389 | proc newOwnObj[T: NimGodotObject](name: cstring): T =
390 | let newNativeScript = getClassConstructor(cstring"NativeScript")()
391 | if setClassNameMethod.isNil:
392 | setClassNameMethod =
393 | getMethod(cstring"NativeScript", cstring"set_class_name")
394 | if setLibraryMethod.isNil:
395 | setLibraryMethod =
396 | getMethod(cstring"NativeScript", cstring"set_library")
397 | if newMethod.isNil:
398 | newMethod = getMethod(cstring"NativeScript", cstring"new")
399 | var godotStrName = name.toGodotString()
400 | var argPtr: pointer = addr godotStrName
401 | setClassNameMethod.ptrCall(
402 | newNativeScript, cast[PtrCallArgType](addr argPtr), nil)
403 | deinit(godotStrName)
404 | setLibraryMethod.ptrCall(
405 | newNativeScript, cast[PtrCallArgType](addr gdNativeLibraryObj), nil)
406 |
407 | var err: VariantCallError
408 | var ret = newMethod.call(newNativeScript, nil, 0, err)
409 | if err.error != VariantCallErrorType.OK:
410 | printError("Failed to invoke 'new' on NativeScript for " & $name)
411 | elif ret.getType() != VariantType.Object:
412 | printError("Expected that NativeScript::new returns Object, " &
413 | "but it returned: " & $ret.getType())
414 | else:
415 | result = asNimGodotObject[T](ret.asGodotObject())
416 | if result.isRef:
417 | result.isFinalized = true
418 | result.godotObject.reference()
419 | result.isFinalized = false
420 | ret.deinit()
421 |
422 | proc gdnew*[T: NimGodotObject](): T =
423 | ## Instantiates new object of type ``T``.
424 | const godotName = toGodotName(T)
425 | const cGodotName = asCString(godotName)
426 | const objInfo = classRegistryStatic[fnv1Hash(godotName)]
427 | when objInfo.isNative:
428 | let godotObject = getClassConstructor(cGodotName)()
429 | new(result, nimGodotObjectFinalizer[T])
430 | result.godotObject = godotObject
431 | when objInfo.isRef:
432 | godotObject.initRef()
433 | result.isRef = true
434 | else:
435 | result = newOwnObj[T](cGodotName)
436 |
437 | proc newCallError*(err: VariantCallError): ref CallError =
438 | ## Instantiates ``CallError`` from Godot ``err``.
439 | let msg = case err.error:
440 | of VariantCallErrorType.OK,
441 | VariantCallErrorType.InvalidMethod,
442 | VariantCallErrorType.TooManyArguments,
443 | VariantCallErrorType.TooFewArguments,
444 | VariantCallErrorType.InstanceIsNull:
445 | $err.error
446 | of VariantCallErrorType.InvalidArgument:
447 | "invalid argument at position " & $err.argument & ": expected " &
448 | $err.expected
449 |
450 | result = newException(CallError, msg)
451 | result.err = err
452 |
453 | proc newConversionError*(err: ConversionResult): ref ValueError =
454 | ## Instantiates error raised by `godotapigen `_
455 | ## generated code in case of a conversion error.
456 | let msg = case err:
457 | of ConversionResult.TypeError:
458 | "Failed to convert the return value into Nim type"
459 | of ConversionResult.RangeError:
460 | "The returned value was out of bounds"
461 | of ConversionResult.OK:
462 | "OK"
463 |
464 | result = newException(ValueError, msg)
465 |
466 | proc setGodotObject*(nimObj: NimGodotObject, obj: ptr GodotObject) {.inline.} =
467 | ## Used from Godot constructor produced by ``gdobj`` macro. Do not call.
468 | assert(not obj.isNil)
469 | assert(nimObj.godotObject.isNil) # reassignment is not allowed
470 | nimObj.godotObject = obj
471 |
472 | proc setNativeObject*(nimObj: NimGodotObject,
473 | nativeObj: NimGodotObject) {.inline.} =
474 | ## Used from Godot constructor produced by ``gdobj`` macro. Do not call.
475 | GC_ref(nativeObj)
476 | nimObj.linkedObjectPtr = cast[pointer](nativeObj)
477 | nativeObj.linkedObjectPtr = cast[pointer](nimObj)
478 | nativeObj.isNative = true
479 |
480 | proc removeGodotObject*(nimObj: NimGodotObject) {.inline.} =
481 | ## Used from Godot destructor produced by ``gdobj`` macro. Do not call.
482 | GC_unref(nimObj.linkedObject)
483 | nimObj.godotObject = nil
484 | nimObj.linkedObject.godotObject = nil
485 | nimObj.linkedObjectPtr = nil
486 |
487 | proc `==`*(self, other: NimGodotObject): bool {.inline.} =
488 | ## Compares objects by referential equality.
489 | if self.isNil and other.isNil: return true
490 | if self.isNil != other.isNil: return false
491 | result = (self.godotObject == other.godotObject)
492 |
493 | proc godotObject*(nimObj: NimGodotObject): ptr GodotObject {.inline.} =
494 | ## Returns raw poitner to ``GodotObject``. Use only if you know what
495 | ## you are doing.
496 | nimObj.godotObject
497 |
498 | proc godotTypeInfo*(T: typedesc[NimGodotObject]): GodotTypeInfo {.inline.} =
499 | GodotTypeInfo(
500 | variantType: VariantType.Object,
501 | hint: when isResource(T): GodotPropertyHint.ResourceType
502 | else: GodotPropertyHint.None,
503 | hintStr: toGodotName(T)
504 | )
505 |
506 | proc toVariant*(self: NimGodotObject): Variant {.inline.} =
507 | if self.isNil:
508 | newVariant()
509 | else:
510 | newVariant(self.godotObject)
511 |
512 | proc fromVariant*[T: NimGodotObject](self: var T,
513 | val: Variant): ConversionResult =
514 | if val.getType() == VariantType.Object:
515 | let objPtr = val.asGodotObject()
516 | self = asNimGodotObject[T](objPtr)
517 | if self.isNil:
518 | result = ConversionResult.TypeError
519 | elif val.getType() == VariantType.Nil:
520 | self = nil
521 | else:
522 | result = ConversionResult.TypeError
523 |
524 | proc toVariant*(self: Variant): Variant {.inline.} =
525 | if self.isNil:
526 | newVariant()
527 | else:
528 | newVariant(self)
529 |
530 | proc fromVariant*(self: var Variant,
531 | val: Variant): ConversionResult {.inline.} =
532 | self = newVariant(val)
533 |
534 | proc godotTypeInfo*(T: typedesc[SomeGodotOrNum]): GodotTypeInfo {.inline.} =
535 | result.variantType =
536 | when T is SomeSignedInt or T is SomeUnsignedInt:
537 | VariantType.Int
538 | elif T is bool:
539 | VariantType.Bool
540 | elif T is SomeFloat:
541 | VariantType.Real
542 | elif T is string or T is GodotString:
543 | VariantType.String
544 | elif T is Vector2:
545 | VariantType.Vector2
546 | elif T is Rect2:
547 | VariantType.Rect2
548 | elif T is Vector3:
549 | VariantType.Vector3
550 | elif T is Transform2D:
551 | VariantType.Transform2D
552 | elif T is Plane:
553 | VariantType.Plane
554 | elif T is Quat:
555 | VariantType.Quat
556 | elif T is AABB:
557 | VariantType.AABB
558 | elif T is Basis:
559 | VariantType.Basis
560 | elif T is Transform:
561 | VariantType.Transform
562 | elif T is Color:
563 | VariantType.Color
564 | elif T is RID:
565 | VariantType.RID
566 | elif T is ptr GodotObject:
567 | VariantType.Object
568 | elif T is NodePath:
569 | VariantType.NodePath
570 | elif T is Dictionary:
571 | VariantType.Dictionary
572 | elif T is Array:
573 | VariantType.Array
574 | elif T is PoolByteArray:
575 | VariantType.PoolByteArray
576 | elif T is PoolIntArray:
577 | VariantType.PoolIntArray
578 | elif T is PoolRealArray:
579 | VariantType.PoolRealArray
580 | elif T is PoolStringArray:
581 | VariantType.PoolStringArray
582 | elif T is PoolVector2Array:
583 | VariantType.PoolVector2Array
584 | elif T is PoolVector3Array:
585 | VariantType.PoolVector3Array
586 | elif T is PoolColorArray:
587 | VariantType.PoolColorArray
588 | else:
589 | VariantType.Nil
590 |
591 | proc godotTypeInfo*(T: typedesc[range]): VariantType {.inline.} =
592 | GodotTypeInfo(
593 | variantType: VariantType.Int,
594 | hint: GodotPropertyHint.Range,
595 | hintStr: $low(T) & "," & $high(T) & ",1"
596 | )
597 |
598 | proc toVariant*[T: SomeGodotOrNum](val: T): Variant {.inline.} =
599 | when val is ref:
600 | if val.isNil:
601 | newVariant()
602 | else:
603 | newVariant(val)
604 | else:
605 | newVariant(val)
606 |
607 | proc fromVariant*[T: SomeSignedInt or SomeUnsignedInt](
608 | self: var T, val: Variant): ConversionResult =
609 | if val.getType() == VariantType.Nil:
610 | self = 0
611 | elif val.getType() == VariantType.Int or val.getType() == VariantType.Real:
612 | # Real is allowed, because that's what the editor sets for Int values
613 | var intVal: (when T is SomeSignedInt: int64
614 | else: uint64)
615 | intVal = when T is SomeSignedInt: val.asInt()
616 | else: val.asUint()
617 | const highT = when T is SomeSignedInt: high(T).int64
618 | elif T is uint64: 0xFFFFFFFFFFFFFFFF'u64
619 | else: high(T).uint64
620 | const lowT = when T is SomeSignedInt: low(T).int64
621 | elif T is uint64: 0'u64
622 | else: low(T).uint64
623 | if intVal > highT or intVal < lowT:
624 | result = ConversionResult.RangeError
625 | else:
626 | self = T(intVal)
627 | else:
628 | result = ConversionResult.TypeError
629 |
630 | proc godotTypeInfo*(T: typedesc[enum]): GodotTypeInfo =
631 | result = GodotTypeInfo(
632 | variantType: VariantType.Int,
633 | hint: GodotPropertyHint.Enum,
634 | hintStr: ""
635 | )
636 | for val in T:
637 | if result.hintStr.len > 0:
638 | result.hintStr.add(',')
639 | result.hintStr.add($val)
640 |
641 | proc toVariant*[T: enum](self: T): Variant {.inline.} =
642 | newVariant(int64(ord(self)))
643 |
644 | proc fromVariant*[T: enum](self: var T,
645 | val: Variant): ConversionResult {.inline.} =
646 | var intConv: int64
647 | result = fromVariant(intConv, val)
648 | if result == ConversionResult.OK:
649 | self = T(intConv)
650 |
651 | proc fromVariant*[T: SomeFloat](self: var T, val: Variant): ConversionResult =
652 | if val.getType() == VariantType.Nil:
653 | self = 0
654 | elif val.getType() == VariantType.Real or val.getType() == VariantType.Int:
655 | self = T(val.asReal())
656 | else:
657 | result = ConversionResult.TypeError
658 |
659 | proc fromVariant*[T: SomeGodot](self: var T, val: Variant): ConversionResult =
660 | if val.getType() == VariantType.Nil:
661 | return
662 | const typeInfo = godotTypeInfo(T)
663 | if typeInfo.variantType != val.getType():
664 | return ConversionResult.TypeError
665 | when self is bool:
666 | self = val.asBool()
667 | elif self is Vector2:
668 | self = val.asVector2()
669 | elif self is Rect2:
670 | self = val.asRect2()
671 | elif self is Vector3:
672 | self = val.asVector3()
673 | elif self is Transform2D:
674 | self = val.asTransform2D()
675 | elif self is Plane:
676 | self = val.asPlane()
677 | elif self is Quat:
678 | self = val.asQuat()
679 | elif self is AABB:
680 | self = val.asAABB()
681 | elif self is Basis:
682 | self = val.asBasis()
683 | elif self is Transform:
684 | self = val.asTransform()
685 | elif self is Color:
686 | self = val.asColor()
687 | elif self is NodePath:
688 | self = val.asNodePath()
689 | elif self is RID:
690 | self = val.asRID()
691 | elif self is ptr GodotObject:
692 | self = val.asObject()
693 | elif self is Dictionary:
694 | self = val.asDictionary()
695 | elif self is Array:
696 | self = val.asArray()
697 | elif self is PoolByteArray:
698 | self = val.asPoolByteArray()
699 | elif self is PoolIntArray:
700 | self = val.asPoolIntArray()
701 | elif self is PoolRealArray:
702 | self = val.asPoolRealArray()
703 | elif self is PoolStringArray:
704 | self = val.asPoolStringArray()
705 | elif self is PoolVector2Array:
706 | self = val.asPoolVector2Array()
707 | elif self is PoolVector3Array:
708 | self = val.asPoolVector3Array()
709 | elif self is PoolColorArray:
710 | self = val.asPoolColorArray()
711 | elif self is GodotString:
712 | self = val.asGodotString()
713 | else:
714 | # mustn't reach this
715 | result = ConversionError.TypeError
716 |
717 | proc godotTypeInfo*(T: typedesc[string]): GodotTypeInfo {.inline.} =
718 | result.variantType = VariantType.String
719 |
720 | proc toVariant*(s: string): Variant {.inline.} =
721 | newVariant(s)
722 |
723 | proc fromVariant*(s: var string, val: Variant): ConversionResult =
724 | if val.getType() == VariantType.String:
725 | s = val.asString()
726 | elif val.getType() == VariantType.Nil:
727 | when (NimMajor, NimMinor, NimPatch) < (0, 19, 0):
728 | s = nil
729 | else:
730 | s = ""
731 | else:
732 | result = ConversionResult.TypeError
733 |
734 | template arrTypeInfo(T) =
735 | result.variantType = VariantType.Array
736 | mixin godotTypeInfo
737 | type ItemT = type((
738 | block:
739 | var s: T;
740 | when T is seq: s[0] else: s[low(s)]))
741 | when compiles(godotTypeInfo(ItemT)):
742 | let itemTypeInfo = godotTypeInfo(ItemT)
743 | result.hintStr = $ord(itemTypeInfo.variantType)
744 | result.hintStr.add('/')
745 | result.hintStr.add($ord(itemTypeInfo.hint))
746 | result.hintStr.add(':')
747 | if not itemTypeInfo.hintStr.isNil:
748 | result.hintStr.add(itemTypeInfo.hintStr)
749 |
750 | proc godotTypeInfo*(T: typedesc[seq]): GodotTypeInfo =
751 | arrTypeInfo(T)
752 |
753 | proc godotTypeInfo*(T: typedesc[array]): GodotTypeInfo =
754 | arrTypeInfo(T)
755 |
756 | template arrayToVariant(s: untyped): Variant =
757 | var arr = newArray()
758 | mixin toVariant
759 | for item in s:
760 | arr.add(toVariant(item))
761 | newVariant(arr)
762 |
763 | proc toVariant*[T](s: seq[T]): Variant =
764 | when (NimMajor, NimMinor, NimPatch) < (0, 20, 0):
765 | if s.isNil:
766 | return newVariant()
767 | result = arrayToVariant(s)
768 |
769 | proc toVariant*[I, T](s: array[I, T]): Variant =
770 | result = arrayToVariant(s)
771 |
772 | proc fromVariant*[T](s: var seq[T], val: Variant): ConversionResult =
773 | if val.getType() == VariantType.Nil:
774 | when (NimMajor, NimMinor, NimPatch) < (0, 20, 0):
775 | s = nil
776 | else:
777 | result = ConversionResult.TypeError
778 | elif val.getType() == VariantType.Array:
779 | let arr = val.asArray()
780 | var newS = newSeq[T](arr.len)
781 | for idx, item in arr:
782 | mixin fromVariant
783 | let convResult = fromVariant(newS[idx], item)
784 | if convResult != ConversionResult.OK:
785 | return convResult
786 | shallowCopy(s, newS)
787 | else:
788 | result = ConversionResult.TypeError
789 |
790 | proc fromVariant*[T: array](s: var T, val: Variant): ConversionResult =
791 | if val.getType() == VariantType.Nil:
792 | discard
793 | elif val.getType() == VariantType.Array:
794 | let arr = val.asArray()
795 | if s.len != arr.len:
796 | return ConversionResult.TypeError
797 | var nimIdx = low(s) # may not start from 0 and may even be an enum
798 | for item in arr:
799 | mixin fromVariant
800 | let convResult = fromVariant(s[nimIdx], item)
801 | if convResult != ConversionResult.OK:
802 | return convResult
803 | if nimIdx != high(s):
804 | inc nimIdx
805 | else:
806 | result = ConversionResult.TypeError
807 |
808 | proc godotTypeInfo*[T](OptT: typedesc[Option[T]]): GodotTypeInfo =
809 | when compiles(godotTypeInfo(T)):
810 | result.variantType = godotTypeInfo(T)
811 | else:
812 | result.variantType = VariantType.Nil
813 |
814 | proc toVariant*[T](option: Option[T]): Variant =
815 | if option.isSome():
816 | result = toVariant(option.unsafeGet())
817 | else:
818 | result = newVariant()
819 |
820 | proc fromVariant*[T](option: var Option[T], val: Variant): ConversionResult =
821 | if val.getType() == VariantType.Nil:
822 | option = none(T)
823 | else:
824 | var v: T
825 | result = fromVariant(v, val)
826 | if result == ConversionResult.OK:
827 | option = some(v)
828 |
829 | proc godotTypeInfo*(T: typedesc[Table|TableRef|OrderedTable|OrderedTableRef]): GodotTypeInfo {.inline.} =
830 | result.variantType = VariantType.Dictionary
831 |
832 | proc toVariant*[T: Table or TableRef or OrderedTable or OrderedTableRef](t: T): Variant =
833 | when t is ref:
834 | if t.isNil:
835 | return newVariant()
836 | var dict = newDictionary()
837 | mixin toVariant
838 | for k, v in t.pairs():
839 | dict[toVariant(k)] = toVariant(v)
840 | result = newVariant(dict)
841 |
842 | proc fromVariant*[T: Table or TableRef or OrderedTable or OrderedTableRef](t: var T,
843 | val: Variant): ConversionResult =
844 | if val.getType() == VariantType.Nil:
845 | when t is ref:
846 | t = nil
847 | elif val.getType() == VariantType.Dictionary:
848 | let dict = val.asDictionary()
849 | mixin fromVariant
850 | when t is Table:
851 | t = initTable[type(t.keys()), type(t.values())]()
852 | elif t is TableRef:
853 | t = newTable[type(t.keys()), type(t.values())]()
854 | elif t is OrderedTable:
855 | t = initOrderedTable[type(t.keys()), type(t.values())]()
856 | else:
857 | t = newOrderedTable[type(t.keys()), type(t.values())]()
858 | for k, v in dict:
859 | var nimKey: type(t.keys())
860 | var nimVal: type(t.values())
861 | let keyResult = fromVariant(nimKey, k)
862 | if keyResult != ConversionResult.OK:
863 | when t is ref:
864 | t = nil
865 | return keyResult
866 | let valResult = fromVariant(nimVal, v)
867 | if valResult != ConversionResult.OK:
868 | when t is ref:
869 | t = nil
870 | return valResult
871 | t[nimKey] = nimVal
872 | else:
873 | result = ConversionResult.TypeError
874 |
875 | when (NimMajor, NimMinor, NimPatch) < (0, 19, 0):
876 | {.emit: """/*TYPESECTION*/
877 | N_LIB_EXPORT N_CDECL(void, NimMain)(void);
878 | N_NOINLINE(void, setStackBottom)(void* thestackbottom);
879 | """.}
880 |
881 | var nativeLibHandle: pointer
882 | proc getNativeLibHandle*(): pointer =
883 | ## Returns NativeScript library handle used to register type information
884 | ## in Godot.
885 | return nativeLibHandle
886 |
887 | proc godot_nativescript_init(handle: pointer) {.
888 | cdecl, exportc, dynlib.} =
889 | nativeLibHandle = handle
890 |
891 | var stackBottom {.volatile.}: pointer
892 | stackBottom = addr(stackBottom)
893 | {.emit: """
894 | NimMain();
895 | """.}
896 | when (NimMajor, NimMinor, NimPatch) < (0, 19, 0):
897 | {.emit: """
898 | setStackBottom((void*)(&`stackBottom`));
899 | """.}
900 | else:
901 | nimGC_setStackBottom(stackBottom)
902 | GC_fullCollect()
903 | GC_disable()
904 |
905 | proc godot_gdnative_init(options: ptr GDNativeInitOptions) {.
906 | cdecl, exportc, dynlib.} =
907 | gdNativeLibraryObj = options.gdNativeLibrary
908 | setGDNativeAPI(options.gdNativeAPIStruct, options)
909 |
910 | proc godot_gdnative_terminate(options: ptr GDNativeTerminateOptions) {.
911 | cdecl, exportc, dynlib.} =
912 | if not options[].inEditor or not compileOption("threads"):
913 | deallocHeap(runFinalizers = not options[].inEditor, allowGcAfterwards = false)
914 |
915 | const nimGcStepLengthUs {.intdefine.} = 2000
916 |
917 | var idleCallbacks {.threadvar.}: seq[proc () {.closure.}]
918 | idleCallbacks = newSeq[proc () {.closure.}]()
919 |
920 | var isMainThread {.threadvar.}: bool
921 | isMainThread = true
922 |
923 | proc registerFrameCallback*(cb: proc () {.closure.}) =
924 | # Registers a callback to be called on the main thread at the end
925 | # of each frame.
926 | if not isMainThread:
927 | const err = cstring"registerFrameIdleCallback is called from non-main thread. Ignoring."
928 | godotPrintError(err, cstring"registerFrameCallback",
929 | cstring"godotnim.nim", 0)
930 | else:
931 | idleCallbacks.add(cb)
932 |
933 | {.push stackTrace: off.}
934 |
935 | proc godot_nativescript_frame() {.cdecl, exportc, dynlib.} =
936 | var stackBottom {.volatile.}: pointer
937 | stackBottom = addr(stackBottom)
938 | when (NimMajor, NimMinor, NimPatch) < (0, 19, 0):
939 | {.emit: """
940 | setStackBottom((void*)(&`stackBottom`));
941 | """.}
942 | else:
943 | nimGC_setStackBottom(stackBottom)
944 | for cb in idleCallbacks:
945 | cb()
946 | GC_step(nimGcStepLengthUs, true, 0)
947 |
948 | when not defined(release):
949 | onUnhandledException = proc(errorMsg: string) =
950 | printError("Unhandled Nim exception: " & errorMsg)
951 |
952 | proc godot_nativescript_thread_enter() {.cdecl, exportc, dynlib.} =
953 | when compileOption("threads"):
954 | setupForeignThreadGc()
955 | else:
956 | 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."
957 | var s = err.toGodotString()
958 | godotPrint(s)
959 | s.deinit()
960 |
961 | proc godot_nativescript_thread_exit() {.cdecl, exportc, dynlib.} =
962 | when compileOption("threads"):
963 | teardownForeignThreadGc()
964 |
965 | {.pop.} # stackTrace: off
966 |
--------------------------------------------------------------------------------