Compare commits
41 commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4175dbb3e5 | ||
| 7eadb07820 | |||
|
|
00d8ac2691 | ||
|
|
388bea9205 | ||
|
|
f25c3c7a5d | ||
|
|
d3e5f91b40 | ||
|
|
3f46e3c648 | ||
|
|
87707a86b4 | ||
|
|
031774f54f | ||
|
|
ed9ede5cb3 | ||
|
|
a49fcbdac7 | ||
|
|
157a90e4a0 |
||
|
|
d1b82d351c | ||
|
|
78d3626fa3 | ||
|
|
1b8e7ccd98 | ||
|
|
c2db807da4 | ||
|
|
7dd1b1ed5f | ||
|
|
2f3f4034cf | ||
|
|
19b0c23d62 | ||
|
|
0fecfdb3b8 | ||
|
|
34fda99def | ||
|
|
3a935b9308 | ||
|
|
f45281f5a0 | ||
|
|
db4bb91765 | ||
|
|
e9d73d8ec4 | ||
|
|
859f9f04fb | ||
|
|
ceaf66a34c | ||
|
|
fd5f77e7c2 | ||
|
|
8d68051f23 | ||
|
|
13f5aba3fe | ||
|
|
b3ad6134d9 | ||
|
|
1e8ccfea2b | ||
|
|
9e61030817 | ||
|
|
66c939b9e6 | ||
|
|
76de026b4f | ||
|
|
4eb771e9be | ||
|
|
2dd0130c78 | ||
|
|
651c2d823c | ||
|
|
8b1ac6d835 | ||
|
|
21ca9a088b | ||
|
|
96dfc7de90 |
33 changed files with 1203 additions and 738 deletions
|
|
@ -1,6 +1,6 @@
|
||||||
# Nim bindings for Godot Engine [](https://travis-ci.org/pragmagic/godot-nim)
|
# Nim bindings for Godot Engine
|
||||||
|
|
||||||
Nim bindings for Godot 3.0 based on [GDNative](https://godotengine.org/article/dlscript-here).
|
Nim bindings for Godot 3 based on [GDNative](https://godotengine.org/article/dlscript-here).
|
||||||
|
|
||||||
Documentation: https://pragmagic.github.io/godot-nim/
|
Documentation: https://pragmagic.github.io/godot-nim/
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -71,7 +71,7 @@ proc fixupHrefs(file: string) =
|
||||||
|
|
||||||
proc getGitHash(): string =
|
proc getGitHash(): string =
|
||||||
result = execProcess("git rev-parse HEAD")
|
result = execProcess("git rev-parse HEAD")
|
||||||
if not result.isNil and result.len > 0:
|
if result.len > 0:
|
||||||
result = result.replace("\L", "").replace("\r", "")
|
result = result.replace("\L", "").replace("\r", "")
|
||||||
|
|
||||||
proc buildDocs*(outDir, godotNimDir, godotBin: string) =
|
proc buildDocs*(outDir, godotNimDir, godotBin: string) =
|
||||||
|
|
@ -104,14 +104,15 @@ proc buildDocs*(outDir, godotNimDir, godotBin: string) =
|
||||||
createDir(godotApiFolder)
|
createDir(godotApiFolder)
|
||||||
genApiFiles(godotApiFolder, godotBinAbs)
|
genApiFiles(godotApiFolder, godotBinAbs)
|
||||||
for file in walkDirRec(godotApiFolder, {pcFile, pcDir}, [".nim"]):
|
for file in walkDirRec(godotApiFolder, {pcFile, pcDir}, [".nim"]):
|
||||||
spawn execOrFail("nim doc -d:useRealtimeGc --path:godot " & quoted(file))
|
spawn execOrFail("nim doc -d:useRealtimeGc --path:godot -o:" &
|
||||||
|
quoted(outName(godotApiFolder, file)) & ' ' & quoted(file))
|
||||||
|
|
||||||
sync()
|
sync()
|
||||||
|
|
||||||
var gitHash: string
|
var gitHash: string
|
||||||
withDir(godotBinAbs.parentDir()):
|
withDir(godotBinAbs.parentDir()):
|
||||||
gitHash = getGitHash()
|
gitHash = getGitHash()
|
||||||
if gitHash.isNil or gitHash.len == 0:
|
if gitHash.len == 0:
|
||||||
raise newException(Exception,
|
raise newException(Exception,
|
||||||
"Godot executable is not under Git repository")
|
"Godot executable is not under Git repository")
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
version = "0.7.10"
|
version = "0.8.2"
|
||||||
author = "Xored Software, Inc."
|
author = "Xored Software, Inc."
|
||||||
description = "Godot Engine bindings"
|
description = "Godot Engine bindings"
|
||||||
license = "MIT"
|
license = "MIT"
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,9 @@
|
||||||
# Copyright (c) 2018 Xored Software, Inc.
|
# Copyright (c) 2018 Xored Software, Inc.
|
||||||
|
|
||||||
import internal.godotinternaltypes, internal.godotstrings
|
import hashes
|
||||||
|
|
||||||
|
import vector3
|
||||||
|
import internal/godotinternaltypes, internal/godotstrings
|
||||||
import godotcoretypes, gdnativeapi
|
import godotcoretypes, gdnativeapi
|
||||||
|
|
||||||
proc initAABB*(pos, size: Vector3): AABB {.inline.} =
|
proc initAABB*(pos, size: Vector3): AABB {.inline.} =
|
||||||
|
|
@ -9,6 +12,9 @@ proc initAABB*(pos, size: Vector3): AABB {.inline.} =
|
||||||
proc `$`*(self: AABB): string {.inline.} =
|
proc `$`*(self: AABB): string {.inline.} =
|
||||||
$getGDNativeAPI().aabbAsString(self)
|
$getGDNativeAPI().aabbAsString(self)
|
||||||
|
|
||||||
|
proc hash*(self: AABB): Hash {.inline.} =
|
||||||
|
!$(self.position.hash() !& self.size.hash())
|
||||||
|
|
||||||
proc area*(self: AABB): float32 {.inline.} =
|
proc area*(self: AABB): float32 {.inline.} =
|
||||||
getGDNativeAPI().aabbGetArea(self)
|
getGDNativeAPI().aabbGetArea(self)
|
||||||
|
|
||||||
|
|
@ -25,10 +31,10 @@ proc encloses*(self, other: AABB): bool {.inline.} =
|
||||||
getGDNativeAPI().aabbEncloses(self, other)
|
getGDNativeAPI().aabbEncloses(self, other)
|
||||||
|
|
||||||
proc merge*(self, other: AABB): AABB {.inline.} =
|
proc merge*(self, other: AABB): AABB {.inline.} =
|
||||||
getGDNativeAPI().aabbMerge(self, other)
|
getGDNativeAPI().aabbMerge(self, other).toAABB()
|
||||||
|
|
||||||
proc intersection*(self, other: AABB): AABB {.inline.} =
|
proc intersection*(self, other: AABB): AABB {.inline.} =
|
||||||
getGDNativeAPI().aabbIntersection(self, other)
|
getGDNativeAPI().aabbIntersection(self, other).toAABB()
|
||||||
|
|
||||||
proc intersectsPlane*(self: AABB; plane: Plane): bool {.inline.} =
|
proc intersectsPlane*(self: AABB; plane: Plane): bool {.inline.} =
|
||||||
getGDNativeAPI().aabbIntersectsPlane(self, plane)
|
getGDNativeAPI().aabbIntersectsPlane(self, plane)
|
||||||
|
|
@ -40,10 +46,10 @@ proc contains*(self: AABB; point: Vector3): bool {.inline.} =
|
||||||
getGDNativeAPI().aabbHasPoint(self, point)
|
getGDNativeAPI().aabbHasPoint(self, point)
|
||||||
|
|
||||||
proc getSupport*(self: AABB; dir: Vector3): Vector3 {.inline.} =
|
proc getSupport*(self: AABB; dir: Vector3): Vector3 {.inline.} =
|
||||||
getGDNativeAPI().aabbGetSupport(self, dir)
|
getGDNativeAPI().aabbGetSupport(self, dir).toVector3()
|
||||||
|
|
||||||
proc getLongestAxis*(self: AABB): Vector3 {.inline.} =
|
proc getLongestAxis*(self: AABB): Vector3 {.inline.} =
|
||||||
getGDNativeAPI().aabbGetLongestAxis(self)
|
getGDNativeAPI().aabbGetLongestAxis(self).toVector3()
|
||||||
|
|
||||||
proc getLongestAxisIndex*(self: AABB): cint {.inline.} =
|
proc getLongestAxisIndex*(self: AABB): cint {.inline.} =
|
||||||
getGDNativeAPI().aabbGetLongestAxisIndex(self)
|
getGDNativeAPI().aabbGetLongestAxisIndex(self)
|
||||||
|
|
@ -52,7 +58,7 @@ proc getLongestAxisSize*(self: AABB): float32 {.inline.} =
|
||||||
getGDNativeAPI().aabbGetLongestAxisSize(self)
|
getGDNativeAPI().aabbGetLongestAxisSize(self)
|
||||||
|
|
||||||
proc getShortestAxis*(self: AABB): Vector3 {.inline.} =
|
proc getShortestAxis*(self: AABB): Vector3 {.inline.} =
|
||||||
getGDNativeAPI().aabbGetShortestAxis(self)
|
getGDNativeAPI().aabbGetShortestAxis(self).toVector3()
|
||||||
|
|
||||||
proc getShortestAxisIndex*(self: AABB): cint {.inline.} =
|
proc getShortestAxisIndex*(self: AABB): cint {.inline.} =
|
||||||
getGDNativeAPI().aabbGetShortestAxisIndex(self)
|
getGDNativeAPI().aabbGetShortestAxisIndex(self)
|
||||||
|
|
@ -61,13 +67,13 @@ proc getShortestAxisSize*(self: AABB): float32 {.inline.} =
|
||||||
getGDNativeAPI().aabbGetShortestAxisSize(self)
|
getGDNativeAPI().aabbGetShortestAxisSize(self)
|
||||||
|
|
||||||
proc expand*(self: AABB; toPoint: Vector3): AABB {.inline.} =
|
proc expand*(self: AABB; toPoint: Vector3): AABB {.inline.} =
|
||||||
getGDNativeAPI().aabbExpand(self, toPoint)
|
getGDNativeAPI().aabbExpand(self, toPoint).toAABB()
|
||||||
|
|
||||||
proc grow*(self: AABB; by: float32): AABB {.inline.} =
|
proc grow*(self: AABB; by: float32): AABB {.inline.} =
|
||||||
getGDNativeAPI().aabbGrow(self, by)
|
getGDNativeAPI().aabbGrow(self, by).toAABB()
|
||||||
|
|
||||||
proc getEndpoint*(self: AABB; idx: cint): Vector3 {.inline.} =
|
proc getEndpoint*(self: AABB; idx: cint): Vector3 {.inline.} =
|
||||||
getGDNativeAPI().aabbGetEndpoint(self, idx)
|
getGDNativeAPI().aabbGetEndpoint(self, idx).toVector3()
|
||||||
|
|
||||||
proc `==`*(a, b: AABB): bool {.inline.} =
|
proc `==`*(a, b: AABB): bool {.inline.} =
|
||||||
getGDNativeAPI().aabbOperatorEqual(a, b)
|
getGDNativeAPI().aabbOperatorEqual(a, b)
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
# Copyright 2018 Xored Software, Inc.
|
# Copyright 2018 Xored Software, Inc.
|
||||||
|
|
||||||
import hashes
|
import hashes
|
||||||
import internal.godotinternaltypes, internal.godotarrays
|
import internal/godotinternaltypes, internal/godotarrays
|
||||||
|
|
||||||
type
|
type
|
||||||
Array* = ref object
|
Array* = ref object
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
# Copyright (c) 2018 Xored Software, Inc.
|
# Copyright (c) 2018 Xored Software, Inc.
|
||||||
|
|
||||||
import math
|
import math, hashes
|
||||||
|
|
||||||
import godotbase, vector3, quats
|
import godotbase, vector3, quats
|
||||||
import godotcoretypes
|
import godotcoretypes
|
||||||
|
|
||||||
|
|
@ -201,6 +202,9 @@ proc `$`*(self: Basis): string {.inline.} =
|
||||||
result.add(", ")
|
result.add(", ")
|
||||||
result.add($self[i][j])
|
result.add($self[i][j])
|
||||||
|
|
||||||
|
proc hash*(self: Basis): Hash {.inline.} =
|
||||||
|
!$(self.elements[0].hash() !& self.elements[1].hash() !& self.elements[2].hash())
|
||||||
|
|
||||||
template cofac(row1, col1, row2, col2: int): float32 =
|
template cofac(row1, col1, row2, col2: int): float32 =
|
||||||
self.elements[row1][col1] * self.elements[row2][col2] -
|
self.elements[row1][col1] * self.elements[row2][col2] -
|
||||||
self.elements[row1][col2] * self.elements[row2][col1]
|
self.elements[row1][col2] * self.elements[row2][col1]
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,7 @@
|
||||||
# Copyright (c) 2018 Xored Software, Inc.
|
# Copyright (c) 2018 Xored Software, Inc.
|
||||||
|
|
||||||
|
import hashes
|
||||||
|
|
||||||
import godotcoretypes, gdnativeapi
|
import godotcoretypes, gdnativeapi
|
||||||
|
|
||||||
proc initColor*(r, g, b: float32; a: float32 = 1.0'f32): Color {.inline.} =
|
proc initColor*(r, g, b: float32; a: float32 = 1.0'f32): Color {.inline.} =
|
||||||
|
|
@ -33,6 +35,9 @@ proc `$`*(self: Color): string {.inline.} =
|
||||||
result.add(", ")
|
result.add(", ")
|
||||||
result.add($self.a)
|
result.add($self.a)
|
||||||
|
|
||||||
|
proc hash*(self: Color): Hash {.inline.} =
|
||||||
|
!$(self.r.hash() !& self.g.hash() !& self.b.hash() !& self.a.hash())
|
||||||
|
|
||||||
proc toHex(val: float32, target: var string, targetIdx: int) =
|
proc toHex(val: float32, target: var string, targetIdx: int) =
|
||||||
let val = clamp(int(val * 255), 0, 255)
|
let val = clamp(int(val * 255), 0, 255)
|
||||||
let nums = [(val and 0xF0) shr 4, val and 0xF]
|
let nums = [(val and 0xF0) shr 4, val and 0xF]
|
||||||
|
|
@ -59,16 +64,16 @@ proc gray*(self: Color): float32 {.inline.} =
|
||||||
getGDNativeAPI().colorGray(self)
|
getGDNativeAPI().colorGray(self)
|
||||||
|
|
||||||
proc inverted*(self: Color): Color {.inline.} =
|
proc inverted*(self: Color): Color {.inline.} =
|
||||||
getGDNativeAPI().colorInverted(self)
|
getGDNativeAPI().colorInverted(self).toColor()
|
||||||
|
|
||||||
proc contrasted*(self: Color): Color {.inline.} =
|
proc contrasted*(self: Color): Color {.inline.} =
|
||||||
getGDNativeAPI().colorContrasted(self)
|
getGDNativeAPI().colorContrasted(self).toColor()
|
||||||
|
|
||||||
proc lerp*(self: Color; b: Color; t: float32): Color {.inline.} =
|
proc lerp*(self: Color; b: Color; t: float32): Color {.inline.} =
|
||||||
getGDNativeAPI().colorLinearInterpolate(self, b, t)
|
getGDNativeAPI().colorLinearInterpolate(self, b, t).toColor()
|
||||||
|
|
||||||
proc blend*(self: Color; over: Color): Color {.inline.} =
|
proc blend*(self: Color; over: Color): Color {.inline.} =
|
||||||
getGDNativeAPI().colorBlend(self, over)
|
getGDNativeAPI().colorBlend(self, over).toColor()
|
||||||
|
|
||||||
proc `==`*(a, b: Color): bool {.inline.} =
|
proc `==`*(a, b: Color): bool {.inline.} =
|
||||||
a.r == b.r and a.g == b.g and a.b == b.b and a.a == b.a
|
a.r == b.r and a.g == b.g and a.b == b.b and a.a == b.a
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,8 @@
|
||||||
# Copyright 2018 Xored Software, Inc.
|
# Copyright 2018 Xored Software, Inc.
|
||||||
|
|
||||||
import hashes
|
import hashes
|
||||||
import internal.godotinternaltypes, internal.godotdictionaries,
|
import internal/godotinternaltypes, internal/godotdictionaries,
|
||||||
internal.godotvariants, internal.godotstrings
|
internal/godotvariants, internal/godotstrings
|
||||||
|
|
||||||
type
|
type
|
||||||
Dictionary* = ref object
|
Dictionary* = ref object
|
||||||
|
|
@ -33,6 +33,9 @@ proc isEmpty*(self: Dictionary): bool {.inline.} =
|
||||||
proc clear*(self: Dictionary) {.inline.} =
|
proc clear*(self: Dictionary) {.inline.} =
|
||||||
self.godotDictionary.clear()
|
self.godotDictionary.clear()
|
||||||
|
|
||||||
|
proc hash*(self: Dictionary): Hash {.inline.} =
|
||||||
|
hash(self.godotDictionary.godotHash())
|
||||||
|
|
||||||
import variants, arrays
|
import variants, arrays
|
||||||
|
|
||||||
proc newVariant*(dict: Dictionary): Variant {.inline.} =
|
proc newVariant*(dict: Dictionary): Variant {.inline.} =
|
||||||
|
|
@ -40,7 +43,7 @@ proc newVariant*(dict: Dictionary): Variant {.inline.} =
|
||||||
initGodotVariant(result.godotVariant[], dict.godotDictionary)
|
initGodotVariant(result.godotVariant[], dict.godotDictionary)
|
||||||
|
|
||||||
proc asDictionary*(self: Variant): Dictionary {.inline.} =
|
proc asDictionary*(self: Variant): Dictionary {.inline.} =
|
||||||
newDictionary(self.godotVariant[].asGodotDictionary)
|
newDictionary(self.godotVariant[].asGodotDictionary())
|
||||||
|
|
||||||
proc contains*(self: Dictionary; key: Variant): bool {.inline.}=
|
proc contains*(self: Dictionary; key: Variant): bool {.inline.}=
|
||||||
self.godotDictionary.contains(key.godotVariant[])
|
self.godotDictionary.contains(key.godotVariant[])
|
||||||
|
|
@ -51,9 +54,6 @@ proc contains*(self: Dictionary; keys: Array): bool {.inline.} =
|
||||||
proc del*(self: Dictionary; key: Variant) {.inline.} =
|
proc del*(self: Dictionary; key: Variant) {.inline.} =
|
||||||
self.godotDictionary.del(key.godotVariant[])
|
self.godotDictionary.del(key.godotVariant[])
|
||||||
|
|
||||||
proc hash*(self: Dictionary): Hash {.inline.} =
|
|
||||||
hash(self.godotDictionary.godotHash())
|
|
||||||
|
|
||||||
proc keys*(self: Dictionary): Array {.inline.} =
|
proc keys*(self: Dictionary): Array {.inline.} =
|
||||||
newArray(self.godotDictionary.keys())
|
newArray(self.godotDictionary.keys())
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -30,26 +30,29 @@ proc stepify*(value, step: float32): float32 {.inline, noinit.} =
|
||||||
else:
|
else:
|
||||||
value
|
value
|
||||||
|
|
||||||
proc min*(x, y: float32): float32 {.inline, noinit.} =
|
when (NimMajor, NimMinor, NimPatch) < (0, 20, 4):
|
||||||
if x <= y: x else: y
|
# Newer Nim has these procs in system module
|
||||||
|
|
||||||
proc abs*(x: float32): float32 {.inline, noinit.} =
|
proc min*(x, y: float32): float32 {.inline, noinit.} =
|
||||||
if x < 0.0: -x else: x
|
if x <= y: x else: y
|
||||||
|
|
||||||
proc max*(x, y: float32): float32 {.inline, noinit.} =
|
proc abs*(x: float32): float32 {.inline, noinit.} =
|
||||||
if y <= x: x else: y
|
if x < 0.0: -x else: x
|
||||||
|
|
||||||
|
proc max*(x, y: float32): float32 {.inline, noinit.} =
|
||||||
|
if y <= x: x else: y
|
||||||
|
|
||||||
{.pop.} # stackTrace: off
|
{.pop.} # stackTrace: off
|
||||||
|
|
||||||
template printWarning*(warning: typed) =
|
template printWarning*(warning: typed) =
|
||||||
## Prints ``warning`` to Godot log, adding filename and line information.
|
## Prints ``warning`` to Godot log, adding filename and line information.
|
||||||
let (filename, line) = instantiationInfo()
|
let instInfo = instantiationInfo()
|
||||||
godotPrintWarning(cstring($warning), cstring"", cstring(filename), line.cint)
|
godotPrintWarning(cstring($warning), cstring"", cstring(instInfo.filename), instInfo.line.cint)
|
||||||
|
|
||||||
template printError*(error: typed) =
|
template printError*(error: typed) =
|
||||||
## Prints ``error`` to Godot log, adding filename and line information.
|
## Prints ``error`` to Godot log, adding filename and line information.
|
||||||
let (filename, line) = instantiationInfo()
|
let instInfo = instantiationInfo()
|
||||||
godotPrintError(cstring($error), cstring"", cstring(filename), line.cint)
|
godotPrintError(cstring($error), cstring"", cstring(instInfo.filename), instInfo.line.cint)
|
||||||
|
|
||||||
proc print*(parts: varargs[string, `$`]) =
|
proc print*(parts: varargs[string, `$`]) =
|
||||||
## Prints concatenated ``parts`` to Godot log.
|
## Prints concatenated ``parts`` to Godot log.
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,9 @@
|
||||||
# Copyright 2018 Xored Software, Inc.
|
# Copyright 2018 Xored Software, Inc.
|
||||||
|
|
||||||
import internal.godotinternaltypes, internal.godotnodepaths,
|
import hashes
|
||||||
internal.godotstrings
|
|
||||||
|
import internal/godotinternaltypes, internal/godotnodepaths,
|
||||||
|
internal/godotstrings
|
||||||
|
|
||||||
type
|
type
|
||||||
NodePath* = ref object
|
NodePath* = ref object
|
||||||
|
|
@ -32,6 +34,9 @@ proc `$`*(self: NodePath): string {.inline.} =
|
||||||
result = $s
|
result = $s
|
||||||
s.deinit()
|
s.deinit()
|
||||||
|
|
||||||
|
proc hash*(self: NodePath): Hash {.inline.} =
|
||||||
|
($self).hash()
|
||||||
|
|
||||||
proc isAbsolute*(self: NodePath): bool {.inline.} =
|
proc isAbsolute*(self: NodePath): bool {.inline.} =
|
||||||
self.path.isAbsolute()
|
self.path.isAbsolute()
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,10 @@
|
||||||
# Copyright (c) 2018 Xored Software, Inc.
|
# Copyright (c) 2018 Xored Software, Inc.
|
||||||
|
|
||||||
|
import hashes
|
||||||
|
|
||||||
import vector3
|
import vector3
|
||||||
|
|
||||||
import internal.godotinternaltypes, internal.godotstrings
|
import internal/godotinternaltypes, internal/godotstrings
|
||||||
import godotcoretypes, gdnativeapi
|
import godotcoretypes, gdnativeapi
|
||||||
|
|
||||||
proc initPlane*(a, b, c, d: float32): Plane {.inline.} =
|
proc initPlane*(a, b, c, d: float32): Plane {.inline.} =
|
||||||
|
|
@ -20,14 +22,17 @@ proc initPlane*(normal: Vector3; d: float32): Plane {.inline.} =
|
||||||
proc `$`*(self: Plane): string {.inline.} =
|
proc `$`*(self: Plane): string {.inline.} =
|
||||||
$getGDNativeAPI().planeAsString(self)
|
$getGDNativeAPI().planeAsString(self)
|
||||||
|
|
||||||
|
proc hash*(self: Plane): Hash {.inline, noinit.} =
|
||||||
|
!$(self.normal.hash() !& self.d.hash())
|
||||||
|
|
||||||
proc normalized*(self: Plane): Plane {.inline.} =
|
proc normalized*(self: Plane): Plane {.inline.} =
|
||||||
getGDNativeAPI().planeNormalized(self)
|
getGDNativeAPI().planeNormalized(self).toPlane()
|
||||||
|
|
||||||
proc center*(self: Plane): Vector3 {.inline.} =
|
proc center*(self: Plane): Vector3 {.inline.} =
|
||||||
getGDNativeAPI().planeCenter(self)
|
getGDNativeAPI().planeCenter(self).toVector3()
|
||||||
|
|
||||||
proc getAnyPoint*(self: Plane): Vector3 {.inline.} =
|
proc getAnyPoint*(self: Plane): Vector3 {.inline.} =
|
||||||
getGDNativeAPI().planeGetAnyPoint(self)
|
getGDNativeAPI().planeGetAnyPoint(self).toVector3()
|
||||||
|
|
||||||
proc isPointOver*(self: Plane; point: Vector3): bool {.inline.} =
|
proc isPointOver*(self: Plane; point: Vector3): bool {.inline.} =
|
||||||
getGDNativeAPI().planeIsPointOver(self, point)
|
getGDNativeAPI().planeIsPointOver(self, point)
|
||||||
|
|
@ -40,7 +45,7 @@ proc contains*(self: Plane; point: Vector3;
|
||||||
getGDNativeAPI().planeHasPoint(self, point, epsilon)
|
getGDNativeAPI().planeHasPoint(self, point, epsilon)
|
||||||
|
|
||||||
proc project*(self: Plane; point: Vector3): Vector3 {.inline.} =
|
proc project*(self: Plane; point: Vector3): Vector3 {.inline.} =
|
||||||
getGDNativeAPI().planeProject(self, point)
|
getGDNativeAPI().planeProject(self, point).toVector3()
|
||||||
|
|
||||||
proc intersect3*(self: Plane; dest: var Vector3;
|
proc intersect3*(self: Plane; dest: var Vector3;
|
||||||
b, c: Plane): bool {.inline.} =
|
b, c: Plane): bool {.inline.} =
|
||||||
|
|
@ -55,7 +60,7 @@ proc intersectsSegment*(self: Plane; dest: var Vector3;
|
||||||
getGDNativeAPI().planeIntersectsSegment(self, dest, segmentBegin, segmentEnd)
|
getGDNativeAPI().planeIntersectsSegment(self, dest, segmentBegin, segmentEnd)
|
||||||
|
|
||||||
proc `-`*(self: Plane): Plane {.inline.} =
|
proc `-`*(self: Plane): Plane {.inline.} =
|
||||||
getGDNativeAPI().planeOperatorNeg(self)
|
getGDNativeAPI().planeOperatorNeg(self).toPlane()
|
||||||
|
|
||||||
proc `==`*(a, b: Plane): bool {.inline.} =
|
proc `==`*(a, b: Plane): bool {.inline.} =
|
||||||
getGDNativeAPI().planeOperatorEqual(a, b)
|
getGDNativeAPI().planeOperatorEqual(a, b)
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,11 @@
|
||||||
# Copyright 2018 Xored Software, Inc.
|
# Copyright 2018 Xored Software, Inc.
|
||||||
|
|
||||||
|
import hashes
|
||||||
|
|
||||||
import godotcoretypes
|
import godotcoretypes
|
||||||
import internal.godotinternaltypes, internal.godotpoolarrays,
|
import internal/godotinternaltypes, internal/godotpoolarrays,
|
||||||
internal.godotstrings
|
internal/godotstrings
|
||||||
|
import vector2, vector3, colors
|
||||||
|
|
||||||
template definePoolArrayBase(T, GodotT, DataT, fieldName, newProcName,
|
template definePoolArrayBase(T, GodotT, DataT, fieldName, newProcName,
|
||||||
initProcName) =
|
initProcName) =
|
||||||
|
|
@ -26,6 +29,36 @@ template definePoolArrayBase(T, GodotT, DataT, fieldName, newProcName,
|
||||||
new(result, poolArrayFinalizer)
|
new(result, poolArrayFinalizer)
|
||||||
result.fieldName = arr
|
result.fieldName = arr
|
||||||
|
|
||||||
|
proc hash*(arr: T): Hash =
|
||||||
|
for item in arr.fieldName.items():
|
||||||
|
result = result !&
|
||||||
|
(when type(item) is GodotString: ($item).hash() else: item.hash())
|
||||||
|
result = !$result
|
||||||
|
|
||||||
|
definePoolArrayBase(PoolByteArray, GodotPoolByteArray, uint8,
|
||||||
|
godotPoolByteArray, newPoolByteArray,
|
||||||
|
initGodotPoolByteArray)
|
||||||
|
definePoolArrayBase(PoolIntArray, GodotPoolIntArray, cint,
|
||||||
|
godotPoolIntArray, newPoolIntArray,
|
||||||
|
initGodotPoolIntArray)
|
||||||
|
definePoolArrayBase(PoolRealArray, GodotPoolRealArray, float32,
|
||||||
|
godotPoolRealArray, newPoolRealArray,
|
||||||
|
initGodotPoolRealArray)
|
||||||
|
definePoolArrayBase(PoolVector2Array, GodotPoolVector2Array, Vector2,
|
||||||
|
godotPoolVector2Array, newPoolVector2Array,
|
||||||
|
initGodotPoolVector2Array)
|
||||||
|
definePoolArrayBase(PoolVector3Array, GodotPoolVector3Array, Vector3,
|
||||||
|
godotPoolVector3Array, newPoolVector3Array,
|
||||||
|
initGodotPoolVector3Array)
|
||||||
|
definePoolArrayBase(PoolColorArray, GodotPoolColorArray, Color,
|
||||||
|
godotPoolColorArray, newPoolColorArray,
|
||||||
|
initGodotPoolColorArray)
|
||||||
|
definePoolArrayBase(PoolStringArray, GodotPoolStringArray, string,
|
||||||
|
godotPoolStringArray, newPoolStringArray,
|
||||||
|
initGodotPoolStringArray)
|
||||||
|
|
||||||
|
import arrays
|
||||||
|
|
||||||
template definePoolArray(T, GodotT, DataT, fieldName, newProcName, initProcName;
|
template definePoolArray(T, GodotT, DataT, fieldName, newProcName, initProcName;
|
||||||
noData = false) =
|
noData = false) =
|
||||||
|
|
||||||
|
|
@ -83,30 +116,6 @@ template definePoolArray(T, GodotT, DataT, fieldName, newProcName, initProcName;
|
||||||
for pair in arr.fieldName.mpairs:
|
for pair in arr.fieldName.mpairs:
|
||||||
yield (pair[0].int, pair[1])
|
yield (pair[0].int, pair[1])
|
||||||
|
|
||||||
definePoolArrayBase(PoolByteArray, GodotPoolByteArray, uint8,
|
|
||||||
godotPoolByteArray, newPoolByteArray,
|
|
||||||
initGodotPoolByteArray)
|
|
||||||
definePoolArrayBase(PoolIntArray, GodotPoolIntArray, cint,
|
|
||||||
godotPoolIntArray, newPoolIntArray,
|
|
||||||
initGodotPoolIntArray)
|
|
||||||
definePoolArrayBase(PoolRealArray, GodotPoolRealArray, float32,
|
|
||||||
godotPoolRealArray, newPoolRealArray,
|
|
||||||
initGodotPoolRealArray)
|
|
||||||
definePoolArrayBase(PoolVector2Array, GodotPoolVector2Array, Vector2,
|
|
||||||
godotPoolVector2Array, newPoolVector2Array,
|
|
||||||
initGodotPoolVector2Array)
|
|
||||||
definePoolArrayBase(PoolVector3Array, GodotPoolVector3Array, Vector3,
|
|
||||||
godotPoolVector3Array, newPoolVector3Array,
|
|
||||||
initGodotPoolVector3Array)
|
|
||||||
definePoolArrayBase(PoolColorArray, GodotPoolColorArray, Color,
|
|
||||||
godotPoolColorArray, newPoolColorArray,
|
|
||||||
initGodotPoolColorArray)
|
|
||||||
definePoolArrayBase(PoolStringArray, GodotPoolStringArray, string,
|
|
||||||
godotPoolStringArray, newPoolStringArray,
|
|
||||||
initGodotPoolStringArray)
|
|
||||||
|
|
||||||
import arrays
|
|
||||||
|
|
||||||
definePoolArray(PoolByteArray, GodotPoolByteArray, uint8,
|
definePoolArray(PoolByteArray, GodotPoolByteArray, uint8,
|
||||||
godotPoolByteArray, newPoolByteArray,
|
godotPoolByteArray, newPoolByteArray,
|
||||||
initGodotPoolByteArray)
|
initGodotPoolByteArray)
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,8 @@
|
||||||
# Copyright (c) 2018 Xored Software, Inc.
|
# Copyright (c) 2018 Xored Software, Inc.
|
||||||
|
|
||||||
import internal.godotinternaltypes, internal.godotstrings
|
import hashes
|
||||||
|
|
||||||
|
import internal/godotinternaltypes, internal/godotstrings
|
||||||
import godotcoretypes, gdnativeapi
|
import godotcoretypes, gdnativeapi
|
||||||
|
|
||||||
proc initQuat*(x, y, z, w: float32): Quat {.inline.} =
|
proc initQuat*(x, y, z, w: float32): Quat {.inline.} =
|
||||||
|
|
@ -17,6 +19,9 @@ proc initQuat*(axis: Vector3; angle: float32): Quat {.inline.} =
|
||||||
proc `$`*(self: Quat): string {.inline.} =
|
proc `$`*(self: Quat): string {.inline.} =
|
||||||
$getGDNativeAPI().quatAsString(self)
|
$getGDNativeAPI().quatAsString(self)
|
||||||
|
|
||||||
|
proc hash*(self: Quat): Hash {.inline.} =
|
||||||
|
!$(self.x.hash() !& self.y.hash() !& self.z.hash() !& self.w.hash())
|
||||||
|
|
||||||
proc length*(self: Quat): float32 {.inline.} =
|
proc length*(self: Quat): float32 {.inline.} =
|
||||||
getGDNativeAPI().quatLength(self)
|
getGDNativeAPI().quatLength(self)
|
||||||
|
|
||||||
|
|
@ -24,50 +29,50 @@ proc lengthSquared*(self: Quat): float32 {.inline.} =
|
||||||
getGDNativeAPI().quatLengthSquared(self)
|
getGDNativeAPI().quatLengthSquared(self)
|
||||||
|
|
||||||
proc normalized*(self: Quat): Quat {.inline.} =
|
proc normalized*(self: Quat): Quat {.inline.} =
|
||||||
getGDNativeAPI().quatNormalized(self)
|
getGDNativeAPI().quatNormalized(self).toQuat()
|
||||||
|
|
||||||
proc isNormalized*(self: Quat): bool {.inline.} =
|
proc isNormalized*(self: Quat): bool {.inline.} =
|
||||||
getGDNativeAPI().quatIsNormalized(self)
|
getGDNativeAPI().quatIsNormalized(self)
|
||||||
|
|
||||||
proc inverse*(self: Quat): Quat {.inline.} =
|
proc inverse*(self: Quat): Quat {.inline.} =
|
||||||
getGDNativeAPI().quatInverse(self)
|
getGDNativeAPI().quatInverse(self).toQuat()
|
||||||
|
|
||||||
proc dot*(a, b: Quat): float32 {.inline.} =
|
proc dot*(a, b: Quat): float32 {.inline.} =
|
||||||
getGDNativeAPI().quatDot(a, b)
|
getGDNativeAPI().quatDot(a, b)
|
||||||
|
|
||||||
proc xform*(self: Quat; v: Vector3): Vector3 {.inline.} =
|
proc xform*(self: Quat; v: Vector3): Vector3 {.inline.} =
|
||||||
getGDNativeAPI().quatXform(self, v)
|
getGDNativeAPI().quatXform(self, v).toVector3()
|
||||||
|
|
||||||
proc slerp*(self: Quat; b: Quat; t: float32): Quat {.inline.} =
|
proc slerp*(self: Quat; b: Quat; t: float32): Quat {.inline.} =
|
||||||
getGDNativeAPI().quatSlerp(self, b, t)
|
getGDNativeAPI().quatSlerp(self, b, t).toQuat()
|
||||||
|
|
||||||
proc slerpni*(self: Quat; b: Quat; t: float32): Quat {.inline.} =
|
proc slerpni*(self: Quat; b: Quat; t: float32): Quat {.inline.} =
|
||||||
getGDNativeAPI().quatSlerpni(self, b, t)
|
getGDNativeAPI().quatSlerpni(self, b, t).toQuat()
|
||||||
|
|
||||||
proc cubicSlerp*(self, b, preA, postB: Quat;
|
proc cubicSlerp*(self, b, preA, postB: Quat;
|
||||||
t: float32): Quat {.inline.} =
|
t: float32): Quat {.inline.} =
|
||||||
getGDNativeAPI().quatCubicSlerp(self, b, preA, postB, t)
|
getGDNativeAPI().quatCubicSlerp(self, b, preA, postB, t).toQuat()
|
||||||
|
|
||||||
proc `*`*(a: Quat, b: float32): Quat {.inline.} =
|
proc `*`*(a: Quat, b: float32): Quat {.inline.} =
|
||||||
getGDNativeAPI().quatOperatorMultiply(a, b)
|
getGDNativeAPI().quatOperatorMultiply(a, b).toQuat()
|
||||||
|
|
||||||
proc `*=`*(a: var Quat, b: float32) {.inline.} =
|
proc `*=`*(a: var Quat, b: float32) {.inline.} =
|
||||||
a = a * b
|
a = a * b
|
||||||
|
|
||||||
proc `+`*(a, b: Quat): Quat {.inline.} =
|
proc `+`*(a, b: Quat): Quat {.inline.} =
|
||||||
getGDNativeAPI().quatOperatorAdd(a, b)
|
getGDNativeAPI().quatOperatorAdd(a, b).toQuat()
|
||||||
|
|
||||||
proc `+=`*(a: var Quat, b: Quat) {.inline.} =
|
proc `+=`*(a: var Quat, b: Quat) {.inline.} =
|
||||||
a = a + b
|
a = a + b
|
||||||
|
|
||||||
proc `-`*(a, b: Quat): Quat {.inline.} =
|
proc `-`*(a, b: Quat): Quat {.inline.} =
|
||||||
getGDNativeAPI().quatOperatorSubtract(a, b)
|
getGDNativeAPI().quatOperatorSubtract(a, b).toQuat()
|
||||||
|
|
||||||
proc `-=`* (a: var Quat, b: Quat) {.inline.} =
|
proc `-=`* (a: var Quat, b: Quat) {.inline.} =
|
||||||
a = a - b
|
a = a - b
|
||||||
|
|
||||||
proc `/`*(self: Quat; b: float32): Quat {.inline.} =
|
proc `/`*(self: Quat; b: float32): Quat {.inline.} =
|
||||||
getGDNativeAPI().quatOperatorDivide(self, b)
|
getGDNativeAPI().quatOperatorDivide(self, b).toQuat()
|
||||||
|
|
||||||
proc `/=`*(self: var Quat, b: float32) {.inline.} =
|
proc `/=`*(self: var Quat, b: float32) {.inline.} =
|
||||||
self = self / b
|
self = self / b
|
||||||
|
|
@ -76,4 +81,4 @@ proc `==`*(a, b: Quat): bool {.inline.} =
|
||||||
getGDNativeAPI().quatOperatorEqual(a, b)
|
getGDNativeAPI().quatOperatorEqual(a, b)
|
||||||
|
|
||||||
proc `-`*(self: Quat): Quat {.inline.} =
|
proc `-`*(self: Quat): Quat {.inline.} =
|
||||||
getGDNativeAPI().quatOperatorNeg(self)
|
getGDNativeAPI().quatOperatorNeg(self).toQuat()
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,9 @@
|
||||||
# Copyright (c) 2018 Xored Software, Inc.
|
# Copyright (c) 2018 Xored Software, Inc.
|
||||||
|
|
||||||
|
import hashes
|
||||||
|
|
||||||
import vector2
|
import vector2
|
||||||
import internal.godotinternaltypes, internal.godotstrings
|
import internal/godotinternaltypes, internal/godotstrings
|
||||||
import godotcoretypes, gdnativeapi
|
import godotcoretypes, gdnativeapi
|
||||||
|
|
||||||
{.push stackTrace: off.}
|
{.push stackTrace: off.}
|
||||||
|
|
@ -15,9 +17,12 @@ proc initRect2*(pos, size: Vector2): Rect2 {.inline, noinit.} =
|
||||||
proc initRect2*(x, y, sizeX, sizeY: float32): Rect2 {.inline, noinit.} =
|
proc initRect2*(x, y, sizeX, sizeY: float32): Rect2 {.inline, noinit.} =
|
||||||
Rect2(position: vec2(x, y), size: vec2(sizeX, sizeY))
|
Rect2(position: vec2(x, y), size: vec2(sizeX, sizeY))
|
||||||
|
|
||||||
proc `$`*(self: Rect2): string {.inline.} =
|
proc `$`*(self: Rect2): string {.inline, noinit.} =
|
||||||
$getGDNativeAPI().rect2AsString(self)
|
$getGDNativeAPI().rect2AsString(self)
|
||||||
|
|
||||||
|
proc hash*(self: Rect2): Hash {.inline, noinit.} =
|
||||||
|
!$(self.position.hash() !& self.size.hash())
|
||||||
|
|
||||||
proc area*(self: Rect2): float32 {.inline, noinit.} =
|
proc area*(self: Rect2): float32 {.inline, noinit.} =
|
||||||
self.size.x * self.size.y
|
self.size.x * self.size.y
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,8 @@
|
||||||
# Copyright (c) 2018 Xored Software, Inc.
|
# Copyright (c) 2018 Xored Software, Inc.
|
||||||
|
|
||||||
import godotcoretypes, internal.godotinternaltypes, gdnativeapi
|
import hashes
|
||||||
|
|
||||||
|
import godotcoretypes, internal/godotinternaltypes, gdnativeapi
|
||||||
|
|
||||||
proc initRID*(): RID {.inline.} =
|
proc initRID*(): RID {.inline.} =
|
||||||
getGDNativeAPI().ridNew(result)
|
getGDNativeAPI().ridNew(result)
|
||||||
|
|
@ -14,6 +16,9 @@ proc id*(self: RID): uint32 {.inline.} =
|
||||||
proc `$`*(self: RID): string {.inline.} =
|
proc `$`*(self: RID): string {.inline.} =
|
||||||
$self.id
|
$self.id
|
||||||
|
|
||||||
|
proc hash*(self: RID): Hash {.inline.} =
|
||||||
|
self.id.hash()
|
||||||
|
|
||||||
proc `==`*(a, b: RID): bool {.inline.} =
|
proc `==`*(a, b: RID): bool {.inline.} =
|
||||||
getGDNativeAPI().ridOperatorEqual(a, b)
|
getGDNativeAPI().ridOperatorEqual(a, b)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,8 @@
|
||||||
# Copyright (c) 2018 Xored Software, Inc.
|
# Copyright (c) 2018 Xored Software, Inc.
|
||||||
|
|
||||||
import internal.godotinternaltypes, internal.godotstrings
|
import hashes, vector2
|
||||||
|
|
||||||
|
import internal/godotinternaltypes, internal/godotstrings
|
||||||
import godotcoretypes, gdnativeapi
|
import godotcoretypes, gdnativeapi
|
||||||
|
|
||||||
proc initTransform2D*(): Transform2D {.inline.} =
|
proc initTransform2D*(): Transform2D {.inline.} =
|
||||||
|
|
@ -15,60 +17,63 @@ proc initTransform2D*(xAxis, yAxis, origin: Vector2): Transform2D {.inline.} =
|
||||||
proc `$`*(self: Transform2D): string {.inline.} =
|
proc `$`*(self: Transform2D): string {.inline.} =
|
||||||
$getGDNativeAPI().transform2DAsString(self)
|
$getGDNativeAPI().transform2DAsString(self)
|
||||||
|
|
||||||
|
proc hash*(self: Transform2D): Hash {.inline, noinit.} =
|
||||||
|
!$(self.elements[0].hash() !& self.elements[1].hash() !& self.elements[2].hash())
|
||||||
|
|
||||||
proc inverse*(self: Transform2D): Transform2D {.inline.} =
|
proc inverse*(self: Transform2D): Transform2D {.inline.} =
|
||||||
getGDNativeAPI().transform2DInverse(self)
|
getGDNativeAPI().transform2DInverse(self).toTransform2D()
|
||||||
|
|
||||||
proc affineInverse*(self: Transform2D): Transform2D {.inline.} =
|
proc affineInverse*(self: Transform2D): Transform2D {.inline.} =
|
||||||
getGDNativeAPI().transform2DAffineInverse(self)
|
getGDNativeAPI().transform2DAffineInverse(self).toTransform2D()
|
||||||
|
|
||||||
proc rotation*(self: Transform2D): float32 {.inline.} =
|
proc rotation*(self: Transform2D): float32 {.inline.} =
|
||||||
getGDNativeAPI().transform2DGetRotation(self)
|
getGDNativeAPI().transform2DGetRotation(self)
|
||||||
|
|
||||||
proc origin*(self: Transform2D): Vector2 {.inline.} =
|
proc origin*(self: Transform2D): Vector2 {.inline.} =
|
||||||
getGDNativeAPI().transform2DGetOrigin(self)
|
getGDNativeAPI().transform2DGetOrigin(self).toVector2()
|
||||||
|
|
||||||
proc scale*(self: Transform2D): Vector2 {.inline.} =
|
proc scale*(self: Transform2D): Vector2 {.inline.} =
|
||||||
getGDNativeAPI().transform2DGetScale(self)
|
getGDNativeAPI().transform2DGetScale(self).toVector2()
|
||||||
|
|
||||||
proc orthonormalized*(self: Transform2D): Transform2D {.inline.} =
|
proc orthonormalized*(self: Transform2D): Transform2D {.inline.} =
|
||||||
getGDNativeAPI().transform2DOrthonormalized(self)
|
getGDNativeAPI().transform2DOrthonormalized(self).toTransform2D()
|
||||||
|
|
||||||
proc rotated*(self: Transform2D; phi: float32): Transform2D {.inline.} =
|
proc rotated*(self: Transform2D; phi: float32): Transform2D {.inline.} =
|
||||||
getGDNativeAPI().transform2DRotated(self, phi)
|
getGDNativeAPI().transform2DRotated(self, phi).toTransform2D()
|
||||||
|
|
||||||
proc scaled*(self: Transform2D; scale: Vector2): Transform2D {.inline.} =
|
proc scaled*(self: Transform2D; scale: Vector2): Transform2D {.inline.} =
|
||||||
getGDNativeAPI().transform2DScaled(self, scale)
|
getGDNativeAPI().transform2DScaled(self, scale).toTransform2D()
|
||||||
|
|
||||||
proc translated*(self: Transform2D; offset: Vector2): Transform2D {.inline.} =
|
proc translated*(self: Transform2D; offset: Vector2): Transform2D {.inline.} =
|
||||||
getGDNativeAPI().transform2DTranslated(self, offset)
|
getGDNativeAPI().transform2DTranslated(self, offset).toTransform2D()
|
||||||
|
|
||||||
proc xformVector2*(self: Transform2D; v: Vector2): Vector2 {.inline.} =
|
proc xformVector2*(self: Transform2D; v: Vector2): Vector2 {.inline.} =
|
||||||
getGDNativeAPI().transform2DXformVector2(self, v)
|
getGDNativeAPI().transform2DXformVector2(self, v).toVector2()
|
||||||
|
|
||||||
proc xformInvVector2*(self: Transform2D; v: Vector2): Vector2 {.inline.} =
|
proc xformInvVector2*(self: Transform2D; v: Vector2): Vector2 {.inline.} =
|
||||||
getGDNativeAPI().transform2DXformInvVector2(self, v)
|
getGDNativeAPI().transform2DXformInvVector2(self, v).toVector2()
|
||||||
|
|
||||||
proc basisXformVector2*(self: Transform2D; v: Vector2): Vector2 {.inline.} =
|
proc basisXformVector2*(self: Transform2D; v: Vector2): Vector2 {.inline.} =
|
||||||
getGDNativeAPI().transform2DBasisXformVector2(self, v)
|
getGDNativeAPI().transform2DBasisXformVector2(self, v).toVector2()
|
||||||
|
|
||||||
proc basisXformInvVector2*(self: Transform2D; v: Vector2): Vector2 {.inline.} =
|
proc basisXformInvVector2*(self: Transform2D; v: Vector2): Vector2 {.inline.} =
|
||||||
getGDNativeAPI().transform2DBasisXformInvVector2(self, v)
|
getGDNativeAPI().transform2DBasisXformInvVector2(self, v).toVector2()
|
||||||
|
|
||||||
proc xformRect2*(self: Transform2D; rect: Rect2): Rect2 {.inline.} =
|
proc xformRect2*(self: Transform2D; rect: Rect2): Rect2 {.inline.} =
|
||||||
getGDNativeAPI().transform2DXformRect2(self, rect)
|
getGDNativeAPI().transform2DXformRect2(self, rect).toRect2()
|
||||||
|
|
||||||
proc xformInvRect2*(self: Transform2D; rect: Rect2): Rect2 {.inline.} =
|
proc xformInvRect2*(self: Transform2D; rect: Rect2): Rect2 {.inline.} =
|
||||||
getGDNativeAPI().transform2DXformInvRect2(self, rect)
|
getGDNativeAPI().transform2DXformInvRect2(self, rect).toRect2()
|
||||||
|
|
||||||
proc interpolateWith*(self, m: Transform2D;
|
proc interpolateWith*(self, m: Transform2D;
|
||||||
c: float32): Transform2D {.inline.} =
|
c: float32): Transform2D {.inline.} =
|
||||||
getGDNativeAPI().transform2DInterpolateWith(self, m, c)
|
getGDNativeAPI().transform2DInterpolateWith(self, m, c).toTransform2D()
|
||||||
|
|
||||||
proc `==`*(a, b: Transform2D): bool {.inline.} =
|
proc `==`*(a, b: Transform2D): bool {.inline.} =
|
||||||
getGDNativeAPI().transform2DOperatorEqual(a, b)
|
getGDNativeAPI().transform2DOperatorEqual(a, b)
|
||||||
|
|
||||||
proc `*`*(a, b: Transform2D): Transform2D {.inline.} =
|
proc `*`*(a, b: Transform2D): Transform2D {.inline.} =
|
||||||
getGDNativeAPI().transform2DOperatorMultiply(a, b)
|
getGDNativeAPI().transform2DOperatorMultiply(a, b).toTransform2D()
|
||||||
|
|
||||||
proc `*=`*(a: var Transform2D, b: Transform2D) {.inline.} =
|
proc `*=`*(a: var Transform2D, b: Transform2D) {.inline.} =
|
||||||
a = a * b
|
a = a * b
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,10 @@
|
||||||
# Copyright (c) 2018 Xored Software, Inc.
|
# Copyright (c) 2018 Xored Software, Inc.
|
||||||
|
|
||||||
import internal.godotinternaltypes, internal.godotstrings
|
import hashes
|
||||||
|
|
||||||
|
import internal/godotinternaltypes, internal/godotstrings
|
||||||
import godotcoretypes, gdnativeapi
|
import godotcoretypes, gdnativeapi
|
||||||
import basis
|
import basis, vector3
|
||||||
|
|
||||||
proc initTransform*(): Transform {.inline.} =
|
proc initTransform*(): Transform {.inline.} =
|
||||||
result.basis = initBasis()
|
result.basis = initBasis()
|
||||||
|
|
@ -21,51 +23,54 @@ proc initTransform*(basis: Basis, origin: Vector3): Transform {.inline.} =
|
||||||
proc `$`*(self: Transform): string {.inline.} =
|
proc `$`*(self: Transform): string {.inline.} =
|
||||||
$getGDNativeAPI().transformAsString(self)
|
$getGDNativeAPI().transformAsString(self)
|
||||||
|
|
||||||
|
proc hash*(self: Transform): Hash {.inline.} =
|
||||||
|
!$(self.basis.hash() !& self.origin.hash())
|
||||||
|
|
||||||
proc inverse*(self: Transform): Transform {.inline.} =
|
proc inverse*(self: Transform): Transform {.inline.} =
|
||||||
getGDNativeAPI().transformInverse(self)
|
getGDNativeAPI().transformInverse(self).toTransform()
|
||||||
|
|
||||||
proc affineInverse*(self: Transform): Transform {.inline.} =
|
proc affineInverse*(self: Transform): Transform {.inline.} =
|
||||||
getGDNativeAPI().transformAffineInverse(self)
|
getGDNativeAPI().transformAffineInverse(self).toTransform()
|
||||||
|
|
||||||
proc orthonormalized*(self: Transform): Transform {.inline.} =
|
proc orthonormalized*(self: Transform): Transform {.inline.} =
|
||||||
getGDNativeAPI().transformOrthonormalized(self)
|
getGDNativeAPI().transformOrthonormalized(self).toTransform()
|
||||||
|
|
||||||
proc rotated*(self: Transform; axis: Vector3;
|
proc rotated*(self: Transform; axis: Vector3;
|
||||||
phi: float32): Transform {.inline.} =
|
phi: float32): Transform {.inline.} =
|
||||||
getGDNativeAPI().transformRotated(self, axis, phi)
|
getGDNativeAPI().transformRotated(self, axis, phi).toTransform()
|
||||||
|
|
||||||
proc scaled*(self: Transform; scale: Vector3): Transform {.inline.} =
|
proc scaled*(self: Transform; scale: Vector3): Transform {.inline.} =
|
||||||
getGDNativeAPI().transformScaled(self, scale)
|
getGDNativeAPI().transformScaled(self, scale).toTransform()
|
||||||
|
|
||||||
proc translated*(self: Transform; offset: Vector3): Transform {.inline.} =
|
proc translated*(self: Transform; offset: Vector3): Transform {.inline.} =
|
||||||
getGDNativeAPI().transformTranslated(self, offset)
|
getGDNativeAPI().transformTranslated(self, offset).toTransform()
|
||||||
|
|
||||||
proc lookingAt*(self: Transform; target, up: Vector3): Transform {.inline.} =
|
proc lookingAt*(self: Transform; target, up: Vector3): Transform {.inline.} =
|
||||||
getGDNativeAPI().transformLookingAt(self, target, up)
|
getGDNativeAPI().transformLookingAt(self, target, up).toTransform()
|
||||||
|
|
||||||
proc xformPlane*(self: Transform; plane: Plane): Plane {.inline.} =
|
proc xformPlane*(self: Transform; plane: Plane): Plane {.inline.} =
|
||||||
getGDNativeAPI().transformXformPlane(self, plane)
|
getGDNativeAPI().transformXformPlane(self, plane).toPlane()
|
||||||
|
|
||||||
proc xformInvPlane*(self: Transform; plane: Plane): Plane {.inline.} =
|
proc xformInvPlane*(self: Transform; plane: Plane): Plane {.inline.} =
|
||||||
getGDNativeAPI().transformXformInvPlane(self, plane)
|
getGDNativeAPI().transformXformInvPlane(self, plane).toPlane()
|
||||||
|
|
||||||
proc xformVector3*(self: Transform; v: Vector3): Vector3 {.inline.} =
|
proc xformVector3*(self: Transform; v: Vector3): Vector3 {.inline.} =
|
||||||
getGDNativeAPI().transformXformVector3(self, v)
|
getGDNativeAPI().transformXformVector3(self, v).toVector3()
|
||||||
|
|
||||||
proc xformInvVector3*(self: Transform; v: Vector3): Vector3 {.inline.} =
|
proc xformInvVector3*(self: Transform; v: Vector3): Vector3 {.inline.} =
|
||||||
getGDNativeAPI().transformXformInvVector3(self, v)
|
getGDNativeAPI().transformXformInvVector3(self, v).toVector3()
|
||||||
|
|
||||||
proc xformAABB*(self: Transform; rect: AABB): AABB {.inline.} =
|
proc xformAABB*(self: Transform; rect: AABB): AABB {.inline.} =
|
||||||
getGDNativeAPI().transformXformAABB(self, rect)
|
getGDNativeAPI().transformXformAABB(self, rect).toAABB()
|
||||||
|
|
||||||
proc xformInvAABB*(self: Transform; rect: AABB): AABB {.inline.} =
|
proc xformInvAABB*(self: Transform; rect: AABB): AABB {.inline.} =
|
||||||
getGDNativeAPI().transformXformInvAABB(self, rect)
|
getGDNativeAPI().transformXformInvAABB(self, rect).toAABB()
|
||||||
|
|
||||||
proc `==`*(self: Transform; b: Transform): bool {.inline.} =
|
proc `==`*(self: Transform; b: Transform): bool {.inline.} =
|
||||||
getGDNativeAPI().transformOperatorEqual(self, b)
|
getGDNativeAPI().transformOperatorEqual(self, b)
|
||||||
|
|
||||||
proc `*`*(self, other: Transform): Transform {.inline.} =
|
proc `*`*(self, other: Transform): Transform {.inline.} =
|
||||||
getGDNativeAPI().transformOperatorMultiply(self, other)
|
getGDNativeAPI().transformOperatorMultiply(self, other).toTransform()
|
||||||
|
|
||||||
proc `*=`*(self: var Transform, other: Transform) {.inline.} =
|
proc `*=`*(self: var Transform, other: Transform) {.inline.} =
|
||||||
self = self * other
|
self = self * other
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,9 @@
|
||||||
import tables
|
import tables, hashes
|
||||||
|
|
||||||
import godotcoretypes
|
import godotcoretypes
|
||||||
import internal.godotinternaltypes, internal.godotvariants,
|
import internal/godotinternaltypes, internal/godotvariants,
|
||||||
internal.godotstrings
|
internal/godotstrings, internal/godotdictionaries,
|
||||||
|
internal/godotarrays
|
||||||
|
|
||||||
type
|
type
|
||||||
Variant* = ref object
|
Variant* = ref object
|
||||||
|
|
@ -72,12 +73,13 @@ proc newVariant*(r: cdouble): Variant {.inline.} =
|
||||||
|
|
||||||
proc newVariant*(s: string): Variant {.inline.} =
|
proc newVariant*(s: string): Variant {.inline.} =
|
||||||
new(result, variantFinalizer)
|
new(result, variantFinalizer)
|
||||||
if s.isNil:
|
when (NimMajor, NimMinor, NimPatch) < (0, 19, 0):
|
||||||
initGodotVariant(result.godotVariant)
|
if s.isNil:
|
||||||
else:
|
initGodotVariant(result.godotVariant)
|
||||||
var godotStr = s.toGodotString()
|
return
|
||||||
initGodotVariant(result.godotVariant, godotStr)
|
var godotStr = s.toGodotString()
|
||||||
godotStr.deinit()
|
initGodotVariant(result.godotVariant, godotStr)
|
||||||
|
godotStr.deinit()
|
||||||
|
|
||||||
import basis, nodepaths
|
import basis, nodepaths
|
||||||
import planes, quats, rect2, aabb, rids
|
import planes, quats, rect2, aabb, rids
|
||||||
|
|
@ -140,11 +142,7 @@ proc newVariant*(obj: ptr GodotObject): Variant {.inline.} =
|
||||||
new(result, variantFinalizer)
|
new(result, variantFinalizer)
|
||||||
initGodotVariant(result.godotVariant, obj)
|
initGodotVariant(result.godotVariant, obj)
|
||||||
|
|
||||||
import arrays, poolarrays
|
import poolarrays
|
||||||
|
|
||||||
proc newVariant*(arr: Array): Variant {.inline.} =
|
|
||||||
new(result, variantFinalizer)
|
|
||||||
initGodotVariant(result.godotVariant, arr.godotArray[])
|
|
||||||
|
|
||||||
proc newVariant*(pba: PoolByteArray): Variant {.inline.} =
|
proc newVariant*(pba: PoolByteArray): Variant {.inline.} =
|
||||||
new(result, variantFinalizer)
|
new(result, variantFinalizer)
|
||||||
|
|
@ -177,81 +175,119 @@ proc newVariant*(pca: PoolColorArray): Variant {.inline.} =
|
||||||
proc asBool*(self: Variant): bool {.inline.} =
|
proc asBool*(self: Variant): bool {.inline.} =
|
||||||
self.godotVariant.asBool()
|
self.godotVariant.asBool()
|
||||||
|
|
||||||
proc asUInt*(self: Variant): uint64 =
|
proc asUInt*(self: Variant): uint64 {.inline.} =
|
||||||
self.godotVariant.asUInt()
|
self.godotVariant.asUInt()
|
||||||
|
|
||||||
proc asInt*(self: Variant): int64 =
|
proc asInt*(self: Variant): int64 {.inline.} =
|
||||||
self.godotVariant.asInt()
|
self.godotVariant.asInt()
|
||||||
|
|
||||||
proc asReal*(self: Variant): cdouble =
|
proc asReal*(self: Variant): cdouble {.inline.} =
|
||||||
self.godotVariant.asReal()
|
self.godotVariant.asReal()
|
||||||
|
|
||||||
proc asString*(self: Variant): string =
|
proc asString*(self: Variant): string {.inline.} =
|
||||||
$self
|
$self
|
||||||
|
|
||||||
proc asVector2*(self: Variant): Vector2 =
|
proc asVector2*(self: Variant): Vector2 {.inline.} =
|
||||||
self.godotVariant.asVector2()
|
self.godotVariant.asVector2()
|
||||||
|
|
||||||
proc asRect2*(self: Variant): Rect2 =
|
proc asRect2*(self: Variant): Rect2 {.inline.} =
|
||||||
self.godotVariant.asRect2()
|
self.godotVariant.asRect2()
|
||||||
|
|
||||||
proc asVector3*(self: Variant): Vector3 =
|
proc asVector3*(self: Variant): Vector3 {.inline.} =
|
||||||
self.godotVariant.asVector3()
|
self.godotVariant.asVector3()
|
||||||
|
|
||||||
proc asTransform2D*(self: Variant): Transform2D =
|
proc asTransform2D*(self: Variant): Transform2D {.inline.} =
|
||||||
self.godotVariant.asTransform2D()
|
self.godotVariant.asTransform2D()
|
||||||
|
|
||||||
proc asPlane*(self: Variant): Plane =
|
proc asPlane*(self: Variant): Plane {.inline.} =
|
||||||
self.godotVariant.asPlane()
|
self.godotVariant.asPlane()
|
||||||
|
|
||||||
proc asQuat*(self: Variant): Quat =
|
proc asQuat*(self: Variant): Quat {.inline.} =
|
||||||
self.godotVariant.asQuat()
|
self.godotVariant.asQuat()
|
||||||
|
|
||||||
proc asAABB*(self: Variant): AABB =
|
proc asAABB*(self: Variant): AABB {.inline.} =
|
||||||
self.godotVariant.asAABB()
|
self.godotVariant.asAABB()
|
||||||
|
|
||||||
proc asBasis*(self: Variant): Basis =
|
proc asBasis*(self: Variant): Basis {.inline.} =
|
||||||
self.godotVariant.asBasis()
|
self.godotVariant.asBasis()
|
||||||
|
|
||||||
proc asTransform*(self: Variant): Transform =
|
proc asTransform*(self: Variant): Transform {.inline.} =
|
||||||
self.godotVariant.asTransform()
|
self.godotVariant.asTransform()
|
||||||
|
|
||||||
proc asColor*(self: Variant): Color =
|
proc asColor*(self: Variant): Color {.inline.} =
|
||||||
self.godotVariant.asColor()
|
self.godotVariant.asColor()
|
||||||
|
|
||||||
proc asNodePath*(self: Variant): NodePath =
|
proc asNodePath*(self: Variant): NodePath {.inline.} =
|
||||||
result = newNodePath(self.godotVariant.asNodePath())
|
result = newNodePath(self.godotVariant.asNodePath())
|
||||||
|
|
||||||
proc asRID*(self: Variant): RID =
|
proc asRID*(self: Variant): RID {.inline.} =
|
||||||
self.godotVariant.asRID()
|
self.godotVariant.asRID()
|
||||||
|
|
||||||
proc asGodotObject*(self: Variant): ptr GodotObject =
|
proc asGodotObject*(self: Variant): ptr GodotObject {.inline.} =
|
||||||
self.godotVariant.asGodotObject()
|
self.godotVariant.asGodotObject()
|
||||||
|
|
||||||
proc asArray*(self: Variant): Array =
|
proc asPoolByteArray*(self: Variant): PoolByteArray {.inline.} =
|
||||||
newArray(self.godotVariant.asGodotArray())
|
|
||||||
|
|
||||||
proc asPoolByteArray*(self: Variant): PoolByteArray =
|
|
||||||
newPoolByteArray(self.godotVariant.asGodotPoolByteArray())
|
newPoolByteArray(self.godotVariant.asGodotPoolByteArray())
|
||||||
|
|
||||||
proc asPoolIntArray*(self: Variant): PoolIntArray =
|
proc asPoolIntArray*(self: Variant): PoolIntArray {.inline.} =
|
||||||
newPoolIntArray(self.godotVariant.asGodotPoolIntArray())
|
newPoolIntArray(self.godotVariant.asGodotPoolIntArray())
|
||||||
|
|
||||||
proc asPoolRealArray*(self: Variant): PoolRealArray =
|
proc asPoolRealArray*(self: Variant): PoolRealArray {.inline.} =
|
||||||
newPoolRealArray(self.godotVariant.asGodotPoolRealArray())
|
newPoolRealArray(self.godotVariant.asGodotPoolRealArray())
|
||||||
|
|
||||||
proc asPoolStringArray*(self: Variant): PoolStringArray =
|
proc asPoolStringArray*(self: Variant): PoolStringArray {.inline.} =
|
||||||
newPoolStringArray(self.godotVariant.asGodotPoolStringArray())
|
newPoolStringArray(self.godotVariant.asGodotPoolStringArray())
|
||||||
|
|
||||||
proc asPoolVector2Array*(self: Variant): PoolVector2Array =
|
proc asPoolVector2Array*(self: Variant): PoolVector2Array {.inline.} =
|
||||||
newPoolVector2Array(self.godotVariant.asGodotPoolVector2Array())
|
newPoolVector2Array(self.godotVariant.asGodotPoolVector2Array())
|
||||||
|
|
||||||
proc asPoolVector3Array*(self: Variant): PoolVector3Array =
|
proc asPoolVector3Array*(self: Variant): PoolVector3Array {.inline.} =
|
||||||
newPoolVector3Array(self.godotVariant.asGodotPoolVector3Array())
|
newPoolVector3Array(self.godotVariant.asGodotPoolVector3Array())
|
||||||
|
|
||||||
proc asPoolColorArray*(self: Variant): PoolColorArray =
|
proc asPoolColorArray*(self: Variant): PoolColorArray {.inline.} =
|
||||||
newPoolColorArray(self.godotVariant.asGodotPoolColorArray())
|
newPoolColorArray(self.godotVariant.asGodotPoolColorArray())
|
||||||
|
|
||||||
|
proc hash*(self: Variant): Hash =
|
||||||
|
proc objectHash(obj: ptr GodotObject): Hash =
|
||||||
|
if not obj.isNil: cast[int](obj).hash() else: 0.hash()
|
||||||
|
result = case self.getType():
|
||||||
|
of VariantType.Nil: Hash(0)
|
||||||
|
of VariantType.Bool: self.asBool().hash()
|
||||||
|
of VariantType.Int: self.asInt().hash()
|
||||||
|
of VariantType.Real: self.asReal().hash()
|
||||||
|
of VariantType.String: self.asString().hash()
|
||||||
|
of VariantType.Vector2: self.asVector2().hash()
|
||||||
|
of VariantType.Rect2: self.asRect2().hash()
|
||||||
|
of VariantType.Vector3: self.asVector3().hash()
|
||||||
|
of VariantType.Transform2D: self.asTransform2D().hash()
|
||||||
|
of VariantType.Plane: self.asPlane().hash()
|
||||||
|
of VariantType.Quat: self.asQuat().hash()
|
||||||
|
of VariantType.AABB: self.asAABB().hash()
|
||||||
|
of VariantType.Basis: self.asBasis().hash()
|
||||||
|
of VariantType.Transform: self.asTransform().hash()
|
||||||
|
of VariantType.Color: self.asColor().hash()
|
||||||
|
of VariantType.NodePath: self.asNodePath().hash()
|
||||||
|
of VariantType.RID: self.asRID().hash()
|
||||||
|
of VariantType.Object: self.asGodotObject().objectHash()
|
||||||
|
of VariantType.Dictionary: hash(self.godotVariant.asGodotDictionary().godotHash())
|
||||||
|
of VariantType.Array: hash(self.godotVariant.asGodotArray().godotHash())
|
||||||
|
of VariantType.PoolByteArray: self.asPoolByteArray().hash()
|
||||||
|
of VariantType.PoolIntArray: self.asPoolIntArray().hash()
|
||||||
|
of VariantType.PoolRealArray: self.asPoolRealArray().hash()
|
||||||
|
of VariantType.PoolStringArray: self.asPoolStringArray().hash()
|
||||||
|
of VariantType.PoolVector2Array: self.asPoolVector2Array().hash()
|
||||||
|
of VariantType.PoolVector3Array: self.asPoolVector3Array().hash()
|
||||||
|
of VariantType.PoolColorArray: self.asPoolColorArray().hash()
|
||||||
|
|
||||||
|
import arrays
|
||||||
|
|
||||||
|
proc newVariant*(arr: Array): Variant {.inline.} =
|
||||||
|
new(result, variantFinalizer)
|
||||||
|
initGodotVariant(result.godotVariant, arr.godotArray[])
|
||||||
|
|
||||||
|
proc asArray*(self: Variant): Array {.inline.} =
|
||||||
|
newArray(self.godotVariant.asGodotArray())
|
||||||
|
|
||||||
proc hasMethod*(self: Variant; meth: string): bool =
|
proc hasMethod*(self: Variant; meth: string): bool =
|
||||||
var s = meth.toGodotString()
|
var s = meth.toGodotString()
|
||||||
result = self.godotVariant.hasMethod(s)
|
result = self.godotVariant.hasMethod(s)
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,12 @@
|
||||||
# Copyright (c) 2018 Xored Software, Inc.
|
# Copyright (c) 2018 Xored Software, Inc.
|
||||||
|
|
||||||
import math, godotbase
|
import math, godotbase, hashes
|
||||||
|
|
||||||
import internal.godotinternaltypes, internal.godotstrings
|
import internal/godotinternaltypes, internal/godotstrings
|
||||||
import godotcoretypes, gdnativeapi
|
import godotcoretypes, gdnativeapi
|
||||||
|
|
||||||
|
const EPSILON = 0.00001'f32
|
||||||
|
|
||||||
{.push stackTrace: off.}
|
{.push stackTrace: off.}
|
||||||
|
|
||||||
proc vec2*(): Vector2 {.inline, noinit.} =
|
proc vec2*(): Vector2 {.inline, noinit.} =
|
||||||
|
|
@ -16,6 +18,9 @@ proc vec2*(x, y: float32): Vector2 {.inline, noinit.} =
|
||||||
proc `$`*(self: Vector2): string {.inline, noinit.} =
|
proc `$`*(self: Vector2): string {.inline, noinit.} =
|
||||||
$getGDNativeAPI().vector2AsString(self)
|
$getGDNativeAPI().vector2AsString(self)
|
||||||
|
|
||||||
|
proc hash*(self: Vector2): Hash {.inline, noinit.} =
|
||||||
|
!$(self.x.hash() !& self.y.hash())
|
||||||
|
|
||||||
proc `+`*(self, other: Vector2): Vector2 {.inline, noinit.} =
|
proc `+`*(self, other: Vector2): Vector2 {.inline, noinit.} =
|
||||||
Vector2(x: self.x + other.x, y: self.y + other.y)
|
Vector2(x: self.x + other.x, y: self.y + other.y)
|
||||||
|
|
||||||
|
|
@ -84,7 +89,7 @@ proc length*(self: Vector2): float32 {.inline, noinit.} =
|
||||||
proc lengthSquared*(self: Vector2): float32 {.inline, noinit.} =
|
proc lengthSquared*(self: Vector2): float32 {.inline, noinit.} =
|
||||||
self.x * self.x + self.y * self.y
|
self.x * self.x + self.y * self.y
|
||||||
|
|
||||||
proc normalize(self: var Vector2) {.inline.} =
|
proc normalize*(self: var Vector2) {.inline.} =
|
||||||
var len = self.x * self.x + self.y * self.y
|
var len = self.x * self.x + self.y * self.y
|
||||||
if len != 0:
|
if len != 0:
|
||||||
len = sqrt(len)
|
len = sqrt(len)
|
||||||
|
|
@ -196,4 +201,14 @@ proc clamped*(self: Vector2; length: float32): Vector2 {.noinit.} =
|
||||||
result /= len
|
result /= len
|
||||||
result *= length
|
result *= length
|
||||||
|
|
||||||
|
proc moveToward*(vFrom, to: Vector2, delta: float32): Vector2 =
|
||||||
|
let
|
||||||
|
vd = to - vFrom
|
||||||
|
vLen = vd.length
|
||||||
|
|
||||||
|
if vLen <= delta or vLen < EPSILON:
|
||||||
|
result = to
|
||||||
|
else:
|
||||||
|
result = vFrom + (vd / vLen) * delta
|
||||||
|
|
||||||
{.pop.} # stackTrace: off
|
{.pop.} # stackTrace: off
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,10 @@
|
||||||
# Copyright (c) 2018 Xored Software, Inc.
|
# Copyright (c) 2018 Xored Software, Inc.
|
||||||
|
|
||||||
import math
|
import math, hashes
|
||||||
import godotbase, godotcoretypes
|
import godotbase, godotcoretypes
|
||||||
|
|
||||||
|
const EPSILON = 0.00001'f32
|
||||||
|
|
||||||
{.push stackTrace: off.}
|
{.push stackTrace: off.}
|
||||||
|
|
||||||
proc vec3*(): Vector3 {.inline.} =
|
proc vec3*(): Vector3 {.inline.} =
|
||||||
|
|
@ -21,6 +23,9 @@ proc `$`*(self: Vector3): string {.inline.} =
|
||||||
result.add($self.z)
|
result.add($self.z)
|
||||||
result.add(')')
|
result.add(')')
|
||||||
|
|
||||||
|
proc hash*(self: Vector3): Hash {.inline, noinit.} =
|
||||||
|
!$(self.x.hash() !& self.y.hash() !& self.z.hash())
|
||||||
|
|
||||||
proc `+`*(a, b: Vector3): Vector3 {.inline.} =
|
proc `+`*(a, b: Vector3): Vector3 {.inline.} =
|
||||||
result.x = a.x + b.x
|
result.x = a.x + b.x
|
||||||
result.y = a.y + b.y
|
result.y = a.y + b.y
|
||||||
|
|
@ -236,4 +241,14 @@ proc cubicInterpolate*(self, b, preA, postB: Vector3;
|
||||||
(2.0 * p0 - 5.0 * p1 + 4 * p2 - p3) * t2 +
|
(2.0 * p0 - 5.0 * p1 + 4 * p2 - p3) * t2 +
|
||||||
(-p0 + 3.0 * p1 - 3.0 * p2 + p3) * t3)
|
(-p0 + 3.0 * p1 - 3.0 * p2 + p3) * t3)
|
||||||
|
|
||||||
|
proc moveToward*(vFrom, to: Vector3, delta: float32): Vector3 =
|
||||||
|
let
|
||||||
|
vd = to - vFrom
|
||||||
|
vLen = vd.length
|
||||||
|
|
||||||
|
if vLen <= delta or vLen < EPSILON:
|
||||||
|
result = to
|
||||||
|
else:
|
||||||
|
result = vFrom + (vd / vLen) * delta
|
||||||
|
|
||||||
{.pop.} # stackTrace: off
|
{.pop.} # stackTrace: off
|
||||||
File diff suppressed because it is too large
Load diff
|
|
@ -1,14 +1,14 @@
|
||||||
# Copyright 2018 Xored Software, Inc.
|
# Copyright 2018 Xored Software, Inc.
|
||||||
|
|
||||||
import core.godotbase, godotinternal
|
import core/godotbase, godotinternal
|
||||||
import core.godotcoretypes
|
import core/godotcoretypes
|
||||||
import core.vector2, core.rect2, core.vector3, core.transform2d, core.planes,
|
import core/vector2, core/rect2, core/vector3, core/transform2d, core/planes,
|
||||||
core.quats
|
core/quats
|
||||||
import core.aabb, core.basis, core.transforms, core.colors, core.nodepaths,
|
import core/aabb, core/basis, core/transforms, core/colors, core/nodepaths,
|
||||||
core.rids
|
core/rids
|
||||||
import core.dictionaries, core.arrays, core.poolarrays, core.variants
|
import core/dictionaries, core/arrays, core/poolarrays, core/variants
|
||||||
|
|
||||||
import nim.godotmacros, nim.godotnim
|
import nim/godotmacros, nim/godotnim
|
||||||
|
|
||||||
export godotbase, godotcoretypes, vector2, rect2, vector3, transform2d, planes,
|
export godotbase, godotcoretypes, vector2, rect2, vector3, transform2d, planes,
|
||||||
quats, aabb, basis, transforms, colors, nodepaths, rids, dictionaries,
|
quats, aabb, basis, transforms, colors, nodepaths, rids, dictionaries,
|
||||||
|
|
|
||||||
|
|
@ -1,12 +1,31 @@
|
||||||
# Copyright 2018 Xored Software, Inc.
|
# Copyright 2018 Xored Software, Inc.
|
||||||
|
|
||||||
import streams, json, os, strutils, times, sets, tables
|
import streams, json, os, strutils, times, sets, tables, options
|
||||||
import sequtils, algorithm
|
import sequtils, algorithm
|
||||||
import compiler.ast, compiler.renderer, compiler.idents, compiler.astalgo
|
import compiler/ast, compiler/renderer, compiler/idents, compiler/astalgo
|
||||||
|
|
||||||
|
include "internal/backwardcompat.inc.nim"
|
||||||
|
|
||||||
|
when (NimMajor, NimMinor, NimPatch) >= (0, 19, 0):
|
||||||
|
import compiler/lineinfos
|
||||||
|
|
||||||
|
when (NimMajor, NimMinor, NimPatch) >= (0, 19, 0):
|
||||||
|
var gic = newIdentCache()
|
||||||
|
|
||||||
|
proc getIdent(ident: string): PIdent =
|
||||||
|
getIdent(gic, ident)
|
||||||
|
|
||||||
proc ident(ident: string): PNode =
|
proc ident(ident: string): PNode =
|
||||||
result = newNode(nkIdent)
|
result = PNode(kind: nkIdent, ident: getIdent(ident))
|
||||||
result.ident = getIdent(ident)
|
|
||||||
|
proc newPNode(kind: TNodeKind): PNode =
|
||||||
|
when (NimMajor, NimMinor, NimPatch) < (0, 19, 0):
|
||||||
|
result = newNode(kind)
|
||||||
|
else:
|
||||||
|
result = PNode(kind: kind)
|
||||||
|
result.info.fileIndex = InvalidFileIdx
|
||||||
|
result.info.col = int16(-1)
|
||||||
|
result.info.line = uint16(0)
|
||||||
|
|
||||||
proc addChain(node: PNode, others: varargs[PNode]): PNode {.discardable.} =
|
proc addChain(node: PNode, others: varargs[PNode]): PNode {.discardable.} =
|
||||||
for other in others:
|
for other in others:
|
||||||
|
|
@ -15,37 +34,37 @@ proc addChain(node: PNode, others: varargs[PNode]): PNode {.discardable.} =
|
||||||
|
|
||||||
proc newIdentDefs(name, typ: PNode,
|
proc newIdentDefs(name, typ: PNode,
|
||||||
defaultVal: PNode = nil): PNode =
|
defaultVal: PNode = nil): PNode =
|
||||||
result = newNode(nkIdentDefs)
|
result = newPNode(nkIdentDefs)
|
||||||
result.add(name)
|
result.add(name)
|
||||||
result.add(typ)
|
result.add(typ)
|
||||||
if defaultVal.isNil:
|
if defaultVal.isNil:
|
||||||
result.add(newNode(nkEmpty))
|
result.add(newPNode(nkEmpty))
|
||||||
else:
|
else:
|
||||||
result.add(defaultVal)
|
result.add(defaultVal)
|
||||||
|
|
||||||
proc newProc(name: PNode, params: openArray[PNode], body = newNode(nkEmpty),
|
proc newProc(name: PNode, params: openArray[PNode], body = newPNode(nkEmpty),
|
||||||
procType = nkProcDef): PNode =
|
procType = nkProcDef): PNode =
|
||||||
result = newNode(procType)
|
result = newPNode(procType)
|
||||||
result.add(name)
|
result.add(name)
|
||||||
result.add(newNode(nkEmpty))
|
result.add(newPNode(nkEmpty))
|
||||||
result.add(newNode(nkEmpty))
|
result.add(newPNode(nkEmpty))
|
||||||
let formalParams = newNode(nkFormalParams)
|
let formalParams = newPNode(nkFormalParams)
|
||||||
for param in params:
|
for param in params:
|
||||||
formalParams.add(param)
|
formalParams.add(param)
|
||||||
result.add(formalParams)
|
result.add(formalParams)
|
||||||
result.add(newNode(nkEmpty))
|
result.add(newPNode(nkEmpty))
|
||||||
result.add(newNode(nkEmpty))
|
result.add(newPNode(nkEmpty))
|
||||||
result.add(body)
|
result.add(body)
|
||||||
|
|
||||||
proc newIfStmt(condition, body: PNode): PNode =
|
proc newIfStmt(condition, body: PNode): PNode =
|
||||||
result = newNode(nkIfStmt)
|
result = newPNode(nkIfStmt)
|
||||||
let branch = newNode(nkElifBranch)
|
let branch = newPNode(nkElifBranch)
|
||||||
result.add(branch)
|
result.add(branch)
|
||||||
branch.add(condition)
|
branch.add(condition)
|
||||||
branch.add(body)
|
branch.add(body)
|
||||||
|
|
||||||
proc newCall(theProc: PNode, args: varargs[PNode]): PNode =
|
proc newCall(theProc: PNode, args: varargs[PNode]): PNode =
|
||||||
result = newNode(nkCall)
|
result = newPNode(nkCall)
|
||||||
result.add(theProc)
|
result.add(theProc)
|
||||||
for arg in args:
|
for arg in args:
|
||||||
result.add(arg)
|
result.add(arg)
|
||||||
|
|
@ -54,66 +73,66 @@ proc newCall(theProc: string, args: varargs[PNode]): PNode =
|
||||||
newCall(ident(theProc), args)
|
newCall(ident(theProc), args)
|
||||||
|
|
||||||
proc newStrLit(s: string): PNode =
|
proc newStrLit(s: string): PNode =
|
||||||
result = newNode(nkStrLit)
|
result = newPNode(nkStrLit)
|
||||||
result.strVal = s
|
result.strVal = s
|
||||||
|
|
||||||
proc newRStrLit(s: string): PNode =
|
proc newRStrLit(s: string): PNode =
|
||||||
result = newNode(nkRStrLit)
|
result = newPNode(nkRStrLit)
|
||||||
result.strVal = s
|
result.strVal = s
|
||||||
|
|
||||||
proc newCStringLit(s: string): PNode =
|
proc newCStringLit(s: string): PNode =
|
||||||
newNode(nkCallStrLit).addChain(ident("cstring"), newRStrLit(s))
|
newPNode(nkCallStrLit).addChain(ident("cstring"), newRStrLit(s))
|
||||||
|
|
||||||
proc newIntLit(val: BiggestInt): PNode =
|
proc newIntLit(val: BiggestInt): PNode =
|
||||||
result = newNode(nkIntLit)
|
result = newPNode(nkIntLit)
|
||||||
result.intVal = val
|
result.intVal = val
|
||||||
|
|
||||||
proc newInt64Lit(val: BiggestInt): PNode =
|
proc newInt64Lit(val: BiggestInt): PNode =
|
||||||
result = newNode(nkInt64Lit)
|
result = newPNode(nkInt64Lit)
|
||||||
result.intVal = val
|
result.intVal = val
|
||||||
|
|
||||||
proc newFloatLit(val: BiggestFloat): PNode =
|
proc newFloatLit(val: BiggestFloat): PNode =
|
||||||
result = newNode(nkFloatLit)
|
result = newPNode(nkFloatLit)
|
||||||
result.floatVal = val
|
result.floatVal = val
|
||||||
|
|
||||||
proc newFloat64Lit(val: BiggestFloat): PNode =
|
proc newFloat64Lit(val: BiggestFloat): PNode =
|
||||||
result = newNode(nkFloat64Lit)
|
result = newPNode(nkFloat64Lit)
|
||||||
result.floatVal = val
|
result.floatVal = val
|
||||||
|
|
||||||
proc newNilLit(): PNode =
|
proc newNilLit(): PNode =
|
||||||
result = newNode(nkNilLit)
|
result = newPNode(nkNilLit)
|
||||||
|
|
||||||
proc newDotExpr(left, right: PNode): PNode =
|
proc newDotExpr(left, right: PNode): PNode =
|
||||||
result = newNode(nkDotExpr)
|
result = newPNode(nkDotExpr)
|
||||||
result.add(left)
|
result.add(left)
|
||||||
result.add(right)
|
result.add(right)
|
||||||
|
|
||||||
proc newCommand(left, right: PNode): PNode =
|
proc newCommand(left, right: PNode): PNode =
|
||||||
result = newNode(nkCommand)
|
result = newPNode(nkCommand)
|
||||||
result.add(left)
|
result.add(left)
|
||||||
result.add(right)
|
result.add(right)
|
||||||
|
|
||||||
proc infix(left, op, right: PNode): PNode =
|
proc infix(left, op, right: PNode): PNode =
|
||||||
result = newNode(nkInfix)
|
result = newPNode(nkInfix)
|
||||||
result.add(op)
|
result.add(op)
|
||||||
result.add(left)
|
result.add(left)
|
||||||
result.add(right)
|
result.add(right)
|
||||||
|
|
||||||
proc postfix(left: PNode, op: string): PNode =
|
proc postfix(left: PNode, op: string): PNode =
|
||||||
result = newNode(nkPostfix)
|
result = newPNode(nkPostfix)
|
||||||
result.add(ident(op))
|
result.add(ident(op))
|
||||||
result.add(left)
|
result.add(left)
|
||||||
|
|
||||||
proc prefix(op: string, right: PNode): PNode =
|
proc prefix(op: string, right: PNode): PNode =
|
||||||
result = newNode(nkPrefix)
|
result = newPNode(nkPrefix)
|
||||||
result.add(ident(op))
|
result.add(ident(op))
|
||||||
result.add(right)
|
result.add(right)
|
||||||
|
|
||||||
proc newBracketExpr(first, bracket: PNode): PNode =
|
proc newBracketExpr(first, bracket: PNode): PNode =
|
||||||
newNode(nkBracketExpr).addChain(first, bracket)
|
newPNode(nkBracketExpr).addChain(first, bracket)
|
||||||
|
|
||||||
proc newEmptyNode(): PNode =
|
proc newEmptyNode(): PNode =
|
||||||
newNode(nkEmpty)
|
newPNode(nkEmpty)
|
||||||
|
|
||||||
type GodotType = ref object
|
type GodotType = ref object
|
||||||
name: string
|
name: string
|
||||||
|
|
@ -139,19 +158,19 @@ proc findCommonRoot(typeRegistry: Table[string, GodotType],
|
||||||
|
|
||||||
var idx = 0
|
var idx = 0
|
||||||
while true:
|
while true:
|
||||||
var curType: string
|
var curType = none(string)
|
||||||
var allEqual = true
|
var allEqual = true
|
||||||
for chain in chains:
|
for chain in chains:
|
||||||
if idx >= chain.len:
|
if idx >= chain.len:
|
||||||
allEqual = false
|
allEqual = false
|
||||||
break
|
break
|
||||||
if curType.isNil:
|
if curType.isNone:
|
||||||
curType = chain[idx]
|
curType = some(chain[idx])
|
||||||
elif curType != chain[idx]:
|
elif curType.get != chain[idx]:
|
||||||
allEqual = false
|
allEqual = false
|
||||||
break
|
break
|
||||||
if allEqual:
|
if allEqual:
|
||||||
result = curType
|
result = curType.get
|
||||||
else:
|
else:
|
||||||
break
|
break
|
||||||
inc idx
|
inc idx
|
||||||
|
|
@ -206,42 +225,42 @@ proc toNimStyle(name: string): string =
|
||||||
|
|
||||||
proc newRefTypeNode(typeSection: PNode, typ, base, doc: string,
|
proc newRefTypeNode(typeSection: PNode, typ, base, doc: string,
|
||||||
isExported = true) =
|
isExported = true) =
|
||||||
let typeDef = newNode(nkTypeDef)
|
let typeDef = newPNode(nkTypeDef)
|
||||||
typeSection.add(typeDef)
|
typeSection.add(typeDef)
|
||||||
if isExported:
|
if isExported:
|
||||||
typeDef.add(postfix(ident(typ), "*"))
|
typeDef.add(postfix(ident(typ), "*"))
|
||||||
else:
|
else:
|
||||||
typeDef.add(ident(typ))
|
typeDef.add(ident(typ))
|
||||||
|
|
||||||
typeDef.add(newNode(nkEmpty)) # generic
|
typeDef.add(newPNode(nkEmpty)) # generic
|
||||||
let objTy = newNode(nkObjectTy)
|
let objTy = newPNode(nkObjectTy)
|
||||||
let refTy = newNode(nkRefTy)
|
let refTy = newPNode(nkRefTy)
|
||||||
refTy.add(objTy)
|
refTy.add(objTy)
|
||||||
typeDef.add(refTy)
|
typeDef.add(refTy)
|
||||||
|
|
||||||
objTy.add(newNode(nkEmpty))
|
objTy.add(newPNode(nkEmpty))
|
||||||
let inherit = newNode(nkOfInherit)
|
let inherit = newPNode(nkOfInherit)
|
||||||
inherit.add(ident(base))
|
inherit.add(ident(base))
|
||||||
objTy.add(inherit)
|
objTy.add(inherit)
|
||||||
|
|
||||||
if not doc.isNil:
|
if doc.len > 0:
|
||||||
let recList = newNode(nkRecList)
|
let recList = newPNode(nkRecList)
|
||||||
let docNode = newNode(nkCommentStmt)
|
let docNode = newPNode(nkCommentStmt)
|
||||||
docNode.comment = doc
|
docNode.comment = doc
|
||||||
recList.add(docNode)
|
recList.add(docNode)
|
||||||
objTy.add(recList)
|
objTy.add(recList)
|
||||||
else:
|
else:
|
||||||
objTy.add(newNode(nkEmpty))
|
objTy.add(newPNode(nkEmpty))
|
||||||
|
|
||||||
proc makeConstSection(constObj: JsonNode): PNode =
|
proc makeConstSection(constObj: JsonNode): PNode =
|
||||||
if constObj.len == 0:
|
if constObj.len == 0:
|
||||||
return newNode(nkEmpty)
|
return newPNode(nkEmpty)
|
||||||
|
|
||||||
result = newNode(nkConstSection)
|
result = newPNode(nkConstSection)
|
||||||
for field, val in constObj:
|
for field, val in constObj:
|
||||||
let def = newNode(nkConstDef)
|
let def = newPNode(nkConstDef)
|
||||||
def.add(postfix(ident(field), "*"))
|
def.add(postfix(ident(field), "*"))
|
||||||
def.add(newNode(nkEmpty)) # infer type
|
def.add(newPNode(nkEmpty)) # infer type
|
||||||
var valNode: PNode
|
var valNode: PNode
|
||||||
if val.kind == JInt:
|
if val.kind == JInt:
|
||||||
valNode = newInt64Lit(val.num)
|
valNode = newInt64Lit(val.num)
|
||||||
|
|
@ -251,7 +270,7 @@ proc makeConstSection(constObj: JsonNode): PNode =
|
||||||
elif val.kind == JBool:
|
elif val.kind == JBool:
|
||||||
valNode = ident($val.bval)
|
valNode = ident($val.bval)
|
||||||
elif val.kind == JString:
|
elif val.kind == JString:
|
||||||
valNode = newNode(nkStrLit)
|
valNode = newPNode(nkStrLit)
|
||||||
valNode.strVal = val.str
|
valNode.strVal = val.str
|
||||||
else:
|
else:
|
||||||
raise newException(ValueError, "Unexpected constant kind: " & $val.kind)
|
raise newException(ValueError, "Unexpected constant kind: " & $val.kind)
|
||||||
|
|
@ -275,40 +294,47 @@ type
|
||||||
godotName: string
|
godotName: string
|
||||||
typ: GodotType
|
typ: GodotType
|
||||||
args: seq[MethodArg]
|
args: seq[MethodArg]
|
||||||
returnType: string
|
returnType: Option[string]
|
||||||
isVirtual: bool
|
isVirtual: bool
|
||||||
isBase: bool
|
isBase: bool
|
||||||
isDiscardable: bool
|
isDiscardable: bool
|
||||||
|
|
||||||
const standardTypes = toSet(
|
const standardTypes = toHashSet(
|
||||||
["bool", "cint", "int", "uint8", "int8", "uint16", "int16", "uint32", "int32",
|
["bool", "cint", "int", "uint8", "int8", "uint16", "int16", "uint32", "int32",
|
||||||
"uint64",
|
"uint64", "Error",
|
||||||
"int64", "float32", "cfloat", "float64", "GodotString", "Vector2", "Rect2",
|
"int64", "float32", "cfloat", "float64", "GodotString", "Vector2", "Rect2",
|
||||||
"Vector3", "Transform2D", "Plane", "Quat", "AABB", "Basis", "Transform",
|
"Vector3", "Transform2D", "Plane", "Quat", "AABB", "Basis", "Transform",
|
||||||
"Color", "RID", "NodePath", "Dictionary", "Variant", "Array",
|
"Color", "RID", "NodePath", "Dictionary", "Variant", "Array",
|
||||||
"PoolByteArray", "PoolIntArray", "PoolRealArray", "PoolStringArray",
|
"PoolByteArray", "PoolIntArray", "PoolRealArray", "PoolStringArray",
|
||||||
"PoolVector2Array", "PoolVector3Array", "PoolColorArray"])
|
"PoolVector2Array", "PoolVector3Array", "PoolColorArray"])
|
||||||
|
|
||||||
const smallIntTypes = toSet(["uint8", "int8", "uint16", "int16", "uint32",
|
const variantPrimitives = [
|
||||||
"int32", "cint", "int", "Error"])
|
"bool", "cint", "int", "uint8", "int8", "uint16", "int16", "uint32", "int32",
|
||||||
const int64Types = toSet(["uint64", "int64"])
|
"uint64", "Error",
|
||||||
|
"int64", "float32", "cfloat", "float64", "GodotString", "Vector2", "Rect2",
|
||||||
|
"Vector3", "Transform2D", "Plane", "Quat", "AABB", "Basis", "Transform",
|
||||||
|
"Color", "RID"]
|
||||||
|
|
||||||
|
const smallIntTypes = toHashSet(["uint8", "int8", "uint16", "int16", "uint32",
|
||||||
|
"int32", "cint", "int", "Error"])
|
||||||
|
const int64Types = toHashSet(["uint64", "int64"])
|
||||||
const intTypes = union(smallIntTypes, int64Types)
|
const intTypes = union(smallIntTypes, int64Types)
|
||||||
const float64Types = toSet(["float64", "cdouble"])
|
const float64Types = toHashSet(["float64", "cdouble"])
|
||||||
const float32Types = toSet(["float32", "cfloat"])
|
const float32Types = toHashSet(["float32", "cfloat"])
|
||||||
const floatTypes = union(float64Types, float32Types)
|
const floatTypes = union(float64Types, float32Types)
|
||||||
const arrayTypes = toSet(["Array", "PoolByteArray",
|
const arrayTypes = toHashSet(["Array", "PoolByteArray",
|
||||||
"PoolIntArray", "PoolRealArray", "PoolStringArray", "PoolVector2Array",
|
"PoolIntArray", "PoolRealArray", "PoolStringArray", "PoolVector2Array",
|
||||||
"PoolVector3Array", "PoolColorArray"])
|
"PoolVector3Array", "PoolColorArray"])
|
||||||
const wrapperTypes = union(arrayTypes,
|
const wrapperTypes = union(arrayTypes,
|
||||||
toSet(["NodePath", "Dictionary", "Variant"]))
|
toHashSet(["NodePath", "Dictionary", "Variant"]))
|
||||||
|
|
||||||
proc getInternalPtr(varName: PNode, typ: string): PNode =
|
proc getInternalPtr(varName: PNode, typ: string): PNode =
|
||||||
assert(typ in wrapperTypes)
|
assert(typ in wrapperTypes or typ == "Object")
|
||||||
result = newDotExpr(varName, ident("godot" & typ))
|
result = newDotExpr(varName, ident("godot" & typ))
|
||||||
|
|
||||||
proc newNilCheck(ident, toAssign: PNode): PNode =
|
proc newNilCheck(ident, toAssign: PNode): PNode =
|
||||||
newIfStmt(newCall("isNil", ident),
|
newIfStmt(newCall("isNil", ident),
|
||||||
newNode(nkAsgn).addChain(ident).addChain(
|
newPNode(nkAsgn).addChain(ident).addChain(
|
||||||
toAssign
|
toAssign
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
@ -319,6 +345,7 @@ proc singletonName(typ: string): PNode =
|
||||||
proc makeDefaultValue(arg: MethodArg): PNode =
|
proc makeDefaultValue(arg: MethodArg): PNode =
|
||||||
result = newEmptyNode()
|
result = newEmptyNode()
|
||||||
if not arg.defaultVal.isNil:
|
if not arg.defaultVal.isNil:
|
||||||
|
var failed = false
|
||||||
if arg.typ == "bool":
|
if arg.typ == "bool":
|
||||||
result = ident(arg.defaultVal.str.toLowerAscii())
|
result = ident(arg.defaultVal.str.toLowerAscii())
|
||||||
elif arg.typ in intTypes:
|
elif arg.typ in intTypes:
|
||||||
|
|
@ -335,15 +362,15 @@ proc makeDefaultValue(arg: MethodArg): PNode =
|
||||||
elif arg.typ == "Color":
|
elif arg.typ == "Color":
|
||||||
result = newCall("initColor",
|
result = newCall("initColor",
|
||||||
arg.defaultVal.str.split(',').mapIt(newFloatLit(parseFloat(it))))
|
arg.defaultVal.str.split(',').mapIt(newFloatLit(parseFloat(it))))
|
||||||
# elif arg.typ in arrayTypes and (arg.defaultVal.str == "[]" or
|
|
||||||
# arg.defaultVal.str == "[" & arg.typ & "]"):
|
|
||||||
# result = newCall("init" & arg.typ)
|
|
||||||
elif arg.typ == "RID" and arg.defaultVal.str == "[RID]":
|
elif arg.typ == "RID" and arg.defaultVal.str == "[RID]":
|
||||||
result = newCall("initRID")
|
result = newCall("initRID")
|
||||||
|
elif arg.typ in arrayTypes and (arg.defaultVal.str == "[]" or
|
||||||
|
arg.defaultVal.str == "[" & arg.typ & "]"):
|
||||||
|
result = newCall("new" & arg.typ)
|
||||||
elif arg.typ == "Vector2" or arg.typ == "Vector3" or arg.typ == "Rect2":
|
elif arg.typ == "Vector2" or arg.typ == "Vector3" or arg.typ == "Rect2":
|
||||||
let parts = arg.defaultVal.str.replace("(", "").replace(")", "").
|
let parts = arg.defaultVal.str.replace("(", "").replace(")", "").
|
||||||
replace(" ", "").
|
replace(" ", "").
|
||||||
split(",").mapIt(newFloatLit(parseFloat(it)))
|
split(',').mapIt(newFloatLit(parseFloat(it)))
|
||||||
if arg.typ.endsWith("r2"):
|
if arg.typ.endsWith("r2"):
|
||||||
result = newCall("vec2", parts)
|
result = newCall("vec2", parts)
|
||||||
elif arg.typ.endsWith('3'):
|
elif arg.typ.endsWith('3'):
|
||||||
|
|
@ -352,11 +379,43 @@ proc makeDefaultValue(arg: MethodArg): PNode =
|
||||||
result = newCall("initRect2", parts)
|
result = newCall("initRect2", parts)
|
||||||
elif arg.defaultVal.str == "[Object:null]":
|
elif arg.defaultVal.str == "[Object:null]":
|
||||||
result = newNilLit()
|
result = newNilLit()
|
||||||
elif arg.typ != "Transform" and arg.typ != "Transform2D" and
|
elif arg.typ == "Transform":
|
||||||
arg.typ != "Variant" and arg.typ notin arrayTypes: # TODO
|
let transformParts = arg.defaultVal.str.replace(" ", "").split('-')
|
||||||
|
doAssert(transformParts.len == 2)
|
||||||
|
let basisParts = transformParts[0].split(',').mapIt(
|
||||||
|
newFloatLit(parseFloat(it)))
|
||||||
|
let originParts = transformParts[1].split(',').mapIt(
|
||||||
|
newFloatLit(parseFloat(it)))
|
||||||
|
let basis = newCall("initBasis", basisParts)
|
||||||
|
let origin = newCall("vec3", originParts)
|
||||||
|
result = newCall("initTransform", basis, origin)
|
||||||
|
elif arg.typ == "Transform2D":
|
||||||
|
let parts = arg.defaultVal.str.
|
||||||
|
replace(" ", "").
|
||||||
|
replace(")", "").
|
||||||
|
replace("(", "").
|
||||||
|
split(',').mapIt(newFloatLit(parseFloat(it)))
|
||||||
|
doAssert(parts.len == 6)
|
||||||
|
let xAxis = newCall("vec2", parts[0..1])
|
||||||
|
let yAxis = newCall("vec2", parts[2..3])
|
||||||
|
let origin = newCall("vec2", parts[4..5])
|
||||||
|
result = newCall("initTransform2D", xAxis, yAxis, origin)
|
||||||
|
elif arg.typ == "Variant":
|
||||||
|
if arg.defaultVal.str == "0":
|
||||||
|
result = newCall("newVariant", newIntLit(0))
|
||||||
|
elif arg.defaultVal.str == "Null":
|
||||||
|
result = newCall("newVariant")
|
||||||
|
else:
|
||||||
|
failed = true
|
||||||
|
elif arg.typ == "Dictionary":
|
||||||
|
result = newCall("newDictionary")
|
||||||
|
else:
|
||||||
|
failed = true
|
||||||
|
|
||||||
|
if failed:
|
||||||
raise newException(
|
raise newException(
|
||||||
ValueError,
|
ValueError,
|
||||||
"Cannot build default value from $# ($#)" %
|
"Cannot build default value from \"$#\" ($#) - please report this at https://github.com/pragmagic/godot-nim/issues" %
|
||||||
[$arg.defaultVal, arg.typ])
|
[$arg.defaultVal, arg.typ])
|
||||||
|
|
||||||
proc boundArgName(idx: int): string =
|
proc boundArgName(idx: int): string =
|
||||||
|
|
@ -366,12 +425,12 @@ proc doGenerateMethod(tree: PNode, methodBindRegistry: var HashSet[string],
|
||||||
meth: MethodInfo, withImplementation: bool) =
|
meth: MethodInfo, withImplementation: bool) =
|
||||||
var body: PNode
|
var body: PNode
|
||||||
if not withImplementation:
|
if not withImplementation:
|
||||||
body = newNode(nkEmpty)
|
body = newPNode(nkEmpty)
|
||||||
elif meth.godotName == "_init" and meth.typ.godotName == "Object":
|
elif meth.godotName == "_init" and meth.typ.godotName == "Object":
|
||||||
# It's not real (calling it crashes) and will be removed later,
|
# It's not real (calling it crashes) and will be removed later,
|
||||||
# but we use init() convention in Nim, so it needs to work.
|
# but we use init() convention in Nim, so it needs to work.
|
||||||
body = newNode(nkStmtList).addChain(
|
body = newPNode(nkStmtList).addChain(
|
||||||
newNode(nkDiscardStmt).addChain(newNode(nkEmpty)))
|
newPNode(nkDiscardStmt).addChain(newPNode(nkEmpty)))
|
||||||
else:
|
else:
|
||||||
let methGodotName = if meth.godotName.startsWith('_'):
|
let methGodotName = if meth.godotName.startsWith('_'):
|
||||||
"underscore" & meth.godotName[1..^1]
|
"underscore" & meth.godotName[1..^1]
|
||||||
|
|
@ -382,12 +441,12 @@ proc doGenerateMethod(tree: PNode, methodBindRegistry: var HashSet[string],
|
||||||
if methodBindName[0].isUpperAscii():
|
if methodBindName[0].isUpperAscii():
|
||||||
methodBindName[0] = methodBindName[0].toLowerAscii()
|
methodBindName[0] = methodBindName[0].toLowerAscii()
|
||||||
if methodBindName notin methodBindRegistry:
|
if methodBindName notin methodBindRegistry:
|
||||||
let methodBindDecl = newNode(nkVarSection).addChain(
|
let methodBindDecl = newPNode(nkVarSection).addChain(
|
||||||
newIdentDefs(
|
newIdentDefs(
|
||||||
newNode(nkPragmaExpr).addChain(
|
newPNode(nkPragmaExpr).addChain(
|
||||||
ident(methodBindName)).addChain(
|
ident(methodBindName)).addChain(
|
||||||
newNode(nkPragma).addChain(ident("threadvar"))),
|
newPNode(nkPragma).addChain(ident("threadvar"))),
|
||||||
newNode(nkPtrTy).addChain(ident("GodotMethodBind"))
|
newPNode(nkPtrTy).addChain(ident("GodotMethodBind"))
|
||||||
))
|
))
|
||||||
tree.add(methodBindDecl)
|
tree.add(methodBindDecl)
|
||||||
methodBindRegistry.incl(methodBindName)
|
methodBindRegistry.incl(methodBindName)
|
||||||
|
|
@ -396,8 +455,8 @@ proc doGenerateMethod(tree: PNode, methodBindRegistry: var HashSet[string],
|
||||||
newCall("getMethod", newCStringLit(meth.typ.godotName),
|
newCall("getMethod", newCStringLit(meth.typ.godotName),
|
||||||
newCStringLit(meth.godotName))
|
newCStringLit(meth.godotName))
|
||||||
)
|
)
|
||||||
let vars = newNode(nkVarSection)
|
let vars = newPNode(nkVarSection)
|
||||||
var varargsName: string
|
var varargsName = none(string)
|
||||||
var isVarargs: bool
|
var isVarargs: bool
|
||||||
var staticArgsLen: int
|
var staticArgsLen: int
|
||||||
var argLenNode = newIntLit(0)
|
var argLenNode = newIntLit(0)
|
||||||
|
|
@ -405,75 +464,114 @@ proc doGenerateMethod(tree: PNode, methodBindRegistry: var HashSet[string],
|
||||||
if meth.args.len > 0:
|
if meth.args.len > 0:
|
||||||
for idx, arg in meth.args:
|
for idx, arg in meth.args:
|
||||||
if arg.kind == ArgKind.VarArgs:
|
if arg.kind == ArgKind.VarArgs:
|
||||||
varargsName = arg.name
|
varargsName = some(arg.name)
|
||||||
isVarargs = true
|
isVarargs = true
|
||||||
vars.add(newIdentDefs(ident("callError"), ident("VariantCallError")))
|
vars.add(newIdentDefs(ident("callError"), ident("VariantCallError")))
|
||||||
elif arg.kind == ArgKind.Bound:
|
elif arg.kind == ArgKind.Bound:
|
||||||
let argName = boundArgName(idx)
|
let argName = boundArgName(idx)
|
||||||
vars.add(newIdentDefs(
|
vars.add(newIdentDefs(
|
||||||
ident(argName), newNode(nkEmpty), arg.makeDefaultValue()))
|
ident(argName), newPNode(nkEmpty), arg.makeDefaultValue()))
|
||||||
|
|
||||||
let argsAlloc = newNode(nkCast).addChain(
|
let argsAlloc = newPNode(nkCast).addChain(
|
||||||
newNode(nkPtrTy).addChain(
|
newPNode(nkPtrTy).addChain(
|
||||||
newNode(nkBracketExpr).addChain(
|
newPNode(nkBracketExpr).addChain(
|
||||||
ident("array"), ident("MAX_ARG_COUNT"),
|
ident("array"), ident("MAX_ARG_COUNT"),
|
||||||
if isVarargs: newNode(nkPtrTy).addChain(ident("GodotVariant"))
|
if isVarargs: newPNode(nkPtrTy).addChain(ident("GodotVariant"))
|
||||||
else: ident("pointer"))))
|
else: ident("pointer"))))
|
||||||
staticArgsLen = if varargsName.isNil: meth.args.len
|
staticArgsLen = if varargsName.isNone: meth.args.len
|
||||||
else: meth.args.len - 1
|
else: meth.args.len - 1
|
||||||
if not varargsName.isNil:
|
if varargsName.isSome:
|
||||||
argLenNode = newCall("cint",
|
argLenNode = newCall("cint",
|
||||||
infix(newIntLit(staticArgsLen),
|
infix(newIntLit(staticArgsLen),
|
||||||
ident("+"),
|
ident("+"),
|
||||||
newDotExpr(ident(varargsName), ident("len"))))
|
newDotExpr(ident(varargsName.get), ident("len"))))
|
||||||
argsAlloc.add(newCall("godotAlloc", newCall("cint", infix(
|
argsAlloc.add(newCall("godotAlloc", newCall("cint", infix(
|
||||||
newCall("sizeof", ident("Variant")), ident("*"),
|
newCall("sizeof", newPNode(nkPtrTy).addChain(ident("GodotVariant"))), ident("*"),
|
||||||
newNode(nkPar).addChain(argLenNode))))
|
newPNode(nkPar).addChain(argLenNode))))
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
argLenNode = newCall("cint", newIntLit(staticArgsLen))
|
argLenNode = newCall("cint", newIntLit(staticArgsLen))
|
||||||
vars.add(newIdentDefs(
|
vars.add(newIdentDefs(
|
||||||
ident("argsStatic"),
|
ident("argsStatic"),
|
||||||
newNode(nkBracketExpr).addChain(
|
newPNode(nkBracketExpr).addChain(
|
||||||
ident("array"), newIntLit(staticArgsLen), ident("pointer")),
|
ident("array"), newIntLit(staticArgsLen), ident("pointer")),
|
||||||
newNode(nkEmpty)))
|
newPNode(nkEmpty)))
|
||||||
argsAlloc.add(newCommand(ident("addr"), ident("argsStatic")))
|
argsAlloc.add(newCommand(ident("addr"), ident("argsStatic")))
|
||||||
vars.add(newIdentDefs(argsName, newNode(nkEmpty), argsAlloc))
|
vars.add(newIdentDefs(argsName, newPNode(nkEmpty), argsAlloc))
|
||||||
|
|
||||||
let argConversions = newNode(nkStmtList)
|
let argConversions = newPNode(nkStmtList)
|
||||||
|
let destructors = newPNode(nkStmtList)
|
||||||
for idx, arg in meth.args:
|
for idx, arg in meth.args:
|
||||||
var argName = if arg.kind == ArgKind.Bound: ident(boundArgName(idx))
|
var argName = if arg.kind == ArgKind.Bound: ident(boundArgName(idx))
|
||||||
else: ident(arg.name)
|
else: ident(arg.name)
|
||||||
if arg.kind == ArgKind.VarArgs:
|
if arg.kind == ArgKind.VarArgs:
|
||||||
argName = newNode(nkBracketExpr).addChain(
|
argName = newPNode(nkBracketExpr).addChain(
|
||||||
ident(varargsName),
|
ident(varargsName.get),
|
||||||
infix(ident("idx"), ident("-"), newIntLit(staticArgsLen)))
|
infix(ident("idx"), ident("-"), newIntLit(staticArgsLen)))
|
||||||
let argIdx = if arg.kind == ArgKind.VarArgs: ident("idx") else: newIntLit(idx)
|
let argIdx = if arg.kind == ArgKind.VarArgs: ident("idx") else: newIntLit(idx)
|
||||||
let isStandardType = arg.typ in standardTypes
|
let isStandardType = arg.typ in standardTypes
|
||||||
let isWrappedType = arg.typ in wrapperTypes
|
let isWrappedType = arg.typ in wrapperTypes
|
||||||
let convArg = if not varargsName.isNil:
|
let convArg =
|
||||||
getInternalPtr(newCall("toVariant", argName), "Variant")
|
if varargsName.isSome:
|
||||||
elif isWrappedType: getInternalPtr(argName, arg.typ)
|
let isAlreadyVariant = arg.typ == "Variant"
|
||||||
elif isStandardType: newCall("unsafeAddr", argName)
|
let variantIdent = if isAlreadyVariant: getInternalPtr(argName, "Variant")
|
||||||
elif arg.typ == "string": newCall("unsafeAddr",
|
else: ident("variant" & $idx)
|
||||||
ident("argToPassToGodot" & $idx))
|
if not isAlreadyVariant:
|
||||||
else: ident("argToPassToGodot" & $idx) # object
|
argConversions.add(newPNode(nkVarSection).addChain(
|
||||||
|
newIdentDefs(variantIdent, ident("GodotVariant"), newEmptyNode())
|
||||||
|
))
|
||||||
|
destructors.add(
|
||||||
|
newCall("deinit", variantIdent)
|
||||||
|
)
|
||||||
|
if arg.typ in variantPrimitives:
|
||||||
|
argConversions.add(
|
||||||
|
newCall("initGodotVariant", variantIdent, argName)
|
||||||
|
)
|
||||||
|
elif arg.typ in wrapperTypes or arg.typ == "Object":
|
||||||
|
argConversions.add(
|
||||||
|
newCall("initGodotVariant", variantIdent, getInternalPtr(argName, arg.typ))
|
||||||
|
)
|
||||||
|
elif arg.typ == "string":
|
||||||
|
let stringIdent = ident("variantString" & $idx)
|
||||||
|
argConversions.addChain(
|
||||||
|
newPNode(nkVarSection).addChain(
|
||||||
|
newIdentDefs(stringIdent, ident("GodotString"), newCall("toGodotString", argName))
|
||||||
|
)
|
||||||
|
).addChain(
|
||||||
|
newCall("initGodotVariant", variantIdent, stringIdent)
|
||||||
|
)
|
||||||
|
destructors.add(newCall("deinit", stringIdent))
|
||||||
|
else:
|
||||||
|
raise newException(ValueError,
|
||||||
|
"Non-standard type $# for varargs params of method $# of type $#" %
|
||||||
|
[arg.typ, meth.godotName, meth.typ.godotName])
|
||||||
|
|
||||||
|
if isAlreadyVariant: variantIdent
|
||||||
|
else: newCall("addr", variantIdent)
|
||||||
|
elif isWrappedType: getInternalPtr(argName, arg.typ)
|
||||||
|
elif isStandardType: newCall("unsafeAddr", argName)
|
||||||
|
elif arg.typ == "string": newCall("unsafeAddr",
|
||||||
|
ident("argToPassToGodot" & $idx))
|
||||||
|
else: ident("argToPassToGodot" & $idx) # object
|
||||||
if not isStandardType and arg.kind == ArgKind.VarArgs:
|
if not isStandardType and arg.kind == ArgKind.VarArgs:
|
||||||
raise newException(ValueError,
|
raise newException(ValueError,
|
||||||
"Non-standard type $# for varargs params of method $# of type $#" %
|
"Non-standard type $# for varargs params of method $# of type $#" %
|
||||||
[arg.typ, meth.godotName, meth.typ.godotName])
|
[arg.typ, meth.godotName, meth.typ.godotName])
|
||||||
if not isStandardType and varargsName.isNil:
|
if not isStandardType and varargsName.isNone:
|
||||||
if arg.typ == "string":
|
if arg.typ == "string":
|
||||||
argConversions.add(newNode(nkVarSection).addChain(
|
argConversions.add(newPNode(nkVarSection).addChain(
|
||||||
newIdentDefs(ident("argToPassToGodot" & $idx), newEmptyNode(),
|
newIdentDefs(ident("argToPassToGodot" & $idx), newEmptyNode(),
|
||||||
newCall("toGodotString", argName))))
|
newCall("toGodotString", argName))))
|
||||||
else:
|
else:
|
||||||
argConversions.add(newNode(nkLetSection).addChain(
|
let objVal = newIfStmt(
|
||||||
newIdentDefs(ident("argToPassToGodot" & $idx), newEmptyNode(),
|
prefix("not", newDotExpr(argName, ident"isNil")),
|
||||||
newDotExpr(argName, ident("godotObject")))))
|
newDotExpr(argName, ident("godotObject"))
|
||||||
let argAsgn = newNode(nkAsgn).addChain(
|
).addChain(newPNode(nkElse).addChain(newNilLit()))
|
||||||
newNode(nkBracketExpr).addChain(
|
argConversions.add(newPNode(nkLetSection).addChain(
|
||||||
newNode(nkBracketExpr).addChain(argsName), argIdx),
|
newIdentDefs(ident("argToPassToGodot" & $idx), newEmptyNode(), objVal)))
|
||||||
|
let argAsgn = newPNode(nkAsgn).addChain(
|
||||||
|
newPNode(nkBracketExpr).addChain(
|
||||||
|
newPNode(nkBracketExpr).addChain(argsName), argIdx),
|
||||||
convArg
|
convArg
|
||||||
)
|
)
|
||||||
if arg.kind != ArgKind.VarArgs:
|
if arg.kind != ArgKind.VarArgs:
|
||||||
|
|
@ -481,14 +579,14 @@ proc doGenerateMethod(tree: PNode, methodBindRegistry: var HashSet[string],
|
||||||
argAsgn
|
argAsgn
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
argConversions.add(newNode(nkVarSection).addChain(
|
argConversions.add(newPNode(nkVarSection).addChain(
|
||||||
newIdentDefs(ident("idx"), newNode(nkEmpty),
|
newIdentDefs(ident("idx"), newPNode(nkEmpty),
|
||||||
newIntLit(staticArgsLen))))
|
newIntLit(staticArgsLen))))
|
||||||
let argLoop = newNode(nkWhileStmt)
|
let argLoop = newPNode(nkWhileStmt)
|
||||||
argConversions.add(argLoop)
|
argConversions.add(argLoop)
|
||||||
argLoop.add(infix(ident("idx"), ident("<"), argLenNode)
|
argLoop.add(infix(ident("idx"), ident("<"), argLenNode)
|
||||||
)
|
)
|
||||||
argLoop.add(newNode(nkStmtList).addChain(
|
argLoop.add(newPNode(nkStmtList).addChain(
|
||||||
argAsgn,
|
argAsgn,
|
||||||
newCommand(ident("inc"), ident("idx"))))
|
newCommand(ident("inc"), ident("idx"))))
|
||||||
|
|
||||||
|
|
@ -497,26 +595,26 @@ proc doGenerateMethod(tree: PNode, methodBindRegistry: var HashSet[string],
|
||||||
newDotExpr(ident(methodBindName),
|
newDotExpr(ident(methodBindName),
|
||||||
ident(if isVarargs: "call" else: "ptrCall")),
|
ident(if isVarargs: "call" else: "ptrCall")),
|
||||||
newDotExpr(ident("self"), ident("godotObject")),
|
newDotExpr(ident("self"), ident("godotObject")),
|
||||||
if meth.args.len > 0: argsName else: newNode(nkNilLit),
|
if meth.args.len > 0: argsName else: newPNode(nkNilLit),
|
||||||
argLenNode,
|
argLenNode,
|
||||||
if not isVarargs: ident(retName) else: ident("callError")
|
if not isVarargs: ident(retName) else: ident("callError")
|
||||||
)
|
)
|
||||||
if not isVarargs:
|
if not isVarargs:
|
||||||
theCall.sons.delete(3)
|
theCall.sons.delete(3)
|
||||||
let freeCall = newCall("godotFree", argsName)
|
let freeCall = newCall("godotFree", argsName)
|
||||||
body = newNode(nkStmtList)
|
body = newPNode(nkStmtList)
|
||||||
if meth.typ.isSingleton:
|
if meth.typ.isSingleton:
|
||||||
let varName = singletonName(meth.typ.name)
|
let varName = singletonName(meth.typ.name)
|
||||||
body.add(newNilCheck(varName, newCall(
|
body.add(newNilCheck(varName, newCall(
|
||||||
newBracketExpr(ident("getSingleton"), ident(meth.typ.name)))))
|
newBracketExpr(ident("getSingleton"), ident(meth.typ.name)))))
|
||||||
body.add(newNode(nkLetSection).addChain(newIdentDefs(
|
body.add(newPNode(nkLetSection).addChain(newIdentDefs(
|
||||||
ident("self"), newNode(nkEmpty), varName
|
ident("self"), newPNode(nkEmpty), varName
|
||||||
)))
|
)))
|
||||||
body.add(nilCheck)
|
body.add(nilCheck)
|
||||||
body.add(vars)
|
body.add(vars)
|
||||||
body.add(argConversions)
|
body.add(argConversions)
|
||||||
if not isVarargs:
|
if not isVarargs:
|
||||||
let retPtrDecl = newNode(nkVarSection).addChain(
|
let retPtrDecl = newPNode(nkVarSection).addChain(
|
||||||
newIdentDefs(ident(retName), ident("pointer"), newEmptyNode())
|
newIdentDefs(ident(retName), ident("pointer"), newEmptyNode())
|
||||||
)
|
)
|
||||||
body.add(retPtrDecl)
|
body.add(retPtrDecl)
|
||||||
|
|
@ -526,105 +624,109 @@ proc doGenerateMethod(tree: PNode, methodBindRegistry: var HashSet[string],
|
||||||
var isStringRet: bool
|
var isStringRet: bool
|
||||||
var isWrapperRet: bool
|
var isWrapperRet: bool
|
||||||
let retValIdent = if not isVarargs: ident("ptrCallVal") else: ident(retName)
|
let retValIdent = if not isVarargs: ident("ptrCallVal") else: ident(retName)
|
||||||
if not meth.returnType.isNil and not isVarargs:
|
if meth.returnType.isSome and not isVarargs:
|
||||||
|
let returnType = meth.returnType.get
|
||||||
var addrToAssign = newCall("addr", retValIdent)
|
var addrToAssign = newCall("addr", retValIdent)
|
||||||
if meth.returnType in smallIntTypes:
|
if returnType in smallIntTypes:
|
||||||
isConversionRet = true
|
isConversionRet = true
|
||||||
body.add(newNode(nkVarSection).addChain(newIdentDefs(
|
body.add(newPNode(nkVarSection).addChain(newIdentDefs(
|
||||||
retValIdent, ident("int64"),
|
retValIdent, ident("int64"),
|
||||||
)))
|
)))
|
||||||
elif meth.returnType in float32Types:
|
elif returnType in float32Types:
|
||||||
isConversionRet = true
|
isConversionRet = true
|
||||||
body.add(newNode(nkVarSection).addChain(newIdentDefs(
|
body.add(newPNode(nkVarSection).addChain(newIdentDefs(
|
||||||
retValIdent, ident("float64"),
|
retValIdent, ident("float64"),
|
||||||
)))
|
)))
|
||||||
elif meth.returnType in wrapperTypes:
|
elif returnType in wrapperTypes:
|
||||||
isWrapperRet = true
|
isWrapperRet = true
|
||||||
body.add(newNode(nkVarSection).addChain(newIdentDefs(
|
body.add(newPNode(nkVarSection).addChain(newIdentDefs(
|
||||||
retValIdent, ident("Godot" & meth.returnType),
|
retValIdent, ident("Godot" & returnType),
|
||||||
)))
|
)))
|
||||||
elif meth.returnType in standardTypes:
|
if returnType != "NodePath":
|
||||||
|
body.add(newCall("initGodot" & returnType, retValIdent))
|
||||||
|
elif returnType in standardTypes:
|
||||||
addrToAssign = newCall("addr", ident("result"))
|
addrToAssign = newCall("addr", ident("result"))
|
||||||
elif meth.returnType == "string":
|
elif returnType == "string":
|
||||||
isStringRet = true
|
isStringRet = true
|
||||||
body.add(newNode(nkVarSection).addChain(newIdentDefs(
|
body.add(newPNode(nkVarSection).addChain(newIdentDefs(
|
||||||
retValIdent, ident("GodotString"),
|
retValIdent, ident("GodotString"),
|
||||||
)))
|
)))
|
||||||
elif meth.returnType != "void":
|
elif returnType != "void":
|
||||||
isObjRet = true
|
isObjRet = true
|
||||||
body.add(newNode(nkVarSection).addChain(newIdentDefs(
|
body.add(newPNode(nkVarSection).addChain(newIdentDefs(
|
||||||
retValIdent, newNode(nkPtrTy).addChain(ident("GodotObject")),
|
retValIdent, newPNode(nkPtrTy).addChain(ident("GodotObject")),
|
||||||
)))
|
)))
|
||||||
body.add(newNode(nkAsgn).addChain(ident(retName), addrToAssign))
|
body.add(newPNode(nkAsgn).addChain(ident(retName), addrToAssign))
|
||||||
|
|
||||||
if not isVarargs:
|
if not isVarargs:
|
||||||
body.add(theCall)
|
body.add(theCall)
|
||||||
else:
|
else:
|
||||||
if not meth.returnType.isNil:
|
if meth.returnType.isSome:
|
||||||
isVariantRet = true
|
isVariantRet = true
|
||||||
let callStmt = newNode(nkLetSection).addChain(
|
let callStmt = newPNode(nkLetSection).addChain(
|
||||||
newIdentDefs(
|
newIdentDefs(
|
||||||
newNode(nkPragmaExpr).addChain(
|
newPNode(nkPragmaExpr).addChain(
|
||||||
ident(retName), newNode(nkPragma).addChain(ident("used"))),
|
ident(retName), newPNode(nkPragma).addChain(ident("used"))),
|
||||||
newNode(nkEmpty), theCall))
|
newPNode(nkEmpty), theCall))
|
||||||
body.add(callStmt)
|
body.add(callStmt)
|
||||||
|
|
||||||
if varargsName.isNil:
|
if varargsName.isNone:
|
||||||
for idx, arg in meth.args:
|
for idx, arg in meth.args:
|
||||||
if arg.typ == "string":
|
if arg.typ == "string":
|
||||||
body.add(newCall("deinit", ident("argToPassToGodot" & $idx)))
|
body.add(newCall("deinit", ident("argToPassToGodot" & $idx)))
|
||||||
|
|
||||||
if meth.args.len > 0 and not varargsName.isNil:
|
if varargsName.isSome:
|
||||||
body.add(freeCall)
|
if meth.args.len > 0:
|
||||||
if not varargsName.isNil:
|
body.add(freeCall)
|
||||||
|
body.add(destructors)
|
||||||
let errCheck = newIfStmt(
|
let errCheck = newIfStmt(
|
||||||
infix(newDotExpr(ident("callError"), ident("error")), ident("!="),
|
infix(newDotExpr(ident("callError"), ident("error")), ident("!="),
|
||||||
newDotExpr(ident("VariantCallErrorType"), ident("OK"))),
|
newDotExpr(ident("VariantCallErrorType"), ident("OK"))),
|
||||||
newNode(nkRaiseStmt).addChain(
|
newPNode(nkRaiseStmt).addChain(
|
||||||
newCall("newCallError", ident("callError")))
|
newCall("newCallError", ident("callError")))
|
||||||
)
|
)
|
||||||
body.add(errCheck)
|
body.add(errCheck)
|
||||||
if isVariantRet:
|
if isVariantRet:
|
||||||
let convErrDef = newNode(nkLetSection).addChain(
|
let convErrDef = newPNode(nkLetSection).addChain(
|
||||||
newIdentDefs(ident("convErr"), newNode(nkEmpty),
|
newIdentDefs(ident("convErr"), newPNode(nkEmpty),
|
||||||
newCall("fromVariant", ident("result"),
|
newCall("fromVariant", ident("result"),
|
||||||
newCall("newVariant", retValIdent))))
|
newCall("newVariant", retValIdent))))
|
||||||
let convCheck = newIfStmt(
|
let convCheck = newIfStmt(
|
||||||
infix(ident("convErr"), ident("!="),
|
infix(ident("convErr"), ident("!="),
|
||||||
newDotExpr(ident("ConversionResult"), ident("OK"))),
|
newDotExpr(ident("ConversionResult"), ident("OK"))),
|
||||||
newNode(nkRaiseStmt).addChain(
|
newPNode(nkRaiseStmt).addChain(
|
||||||
newCall("newConversionError", ident("convErr")))
|
newCall("newConversionError", ident("convErr")))
|
||||||
)
|
)
|
||||||
body.add(convErrDef)
|
body.add(convErrDef)
|
||||||
body.add(convCheck)
|
body.add(convCheck)
|
||||||
if isStringRet:
|
if isStringRet:
|
||||||
body.add(newNode(nkAsgn).addChain(
|
body.add(newPNode(nkAsgn).addChain(
|
||||||
ident("result"), prefix("$", retValIdent)))
|
ident("result"), prefix("$", retValIdent)))
|
||||||
body.add(newCall("deinit", retValIdent))
|
body.add(newCall("deinit", retValIdent))
|
||||||
elif isConversionRet:
|
elif isConversionRet:
|
||||||
body.add(newNode(nkAsgn).addChain(
|
body.add(newPNode(nkAsgn).addChain(
|
||||||
ident("result"),
|
ident("result"),
|
||||||
newCall(meth.returnType, retValIdent)))
|
newCall(meth.returnType.get, retValIdent)))
|
||||||
elif isWrapperRet:
|
elif isWrapperRet:
|
||||||
body.add(newNode(nkAsgn).addChain(
|
body.add(newPNode(nkAsgn).addChain(
|
||||||
ident("result"),
|
ident("result"),
|
||||||
newCall("new" & meth.returnType, retValIdent)))
|
newCall("new" & meth.returnType.get, retValIdent)))
|
||||||
elif isObjRet:
|
elif isObjRet:
|
||||||
body.add(newNode(nkAsgn).addChain(ident("result"),
|
body.add(newPNode(nkAsgn).addChain(ident("result"),
|
||||||
newCall(newBracketExpr(ident("asNimGodotObject"),
|
newCall(newBracketExpr(ident("asNimGodotObject"),
|
||||||
newCall("type", ident("result"))),
|
newCall("type", ident("result"))),
|
||||||
retValIdent, ident("false"), ident("true"))))
|
retValIdent, ident("false"), ident("true"))))
|
||||||
elif isStringRet:
|
elif isStringRet:
|
||||||
body.add(newNode(nkAsgn).addChain(ident("result"),
|
body.add(newPNode(nkAsgn).addChain(ident("result"),
|
||||||
newCall("$", retValIdent)))
|
newCall("$", retValIdent)))
|
||||||
|
|
||||||
let procType = if meth.isVirtual: nkMethodDef
|
let procType = if meth.isVirtual: nkMethodDef
|
||||||
else: nkProcDef
|
else: nkProcDef
|
||||||
var params = newSeqOfCap[PNode](meth.args.len + 2)
|
var params = newSeqOfCap[PNode](meth.args.len + 2)
|
||||||
if not meth.returnType.isNil:
|
if meth.returnType.isSome:
|
||||||
params.add(ident(meth.returnType))
|
params.add(ident(meth.returnType.get))
|
||||||
else:
|
else:
|
||||||
params.add(newNode(nkEmpty))
|
params.add(newPNode(nkEmpty))
|
||||||
if not meth.typ.isSingleton:
|
if not meth.typ.isSingleton:
|
||||||
params.add(newIdentDefs(ident("self"), ident(toNimType(meth.typ.name))))
|
params.add(newIdentDefs(ident("self"), ident(toNimType(meth.typ.name))))
|
||||||
|
|
||||||
|
|
@ -635,7 +737,7 @@ proc doGenerateMethod(tree: PNode, methodBindRegistry: var HashSet[string],
|
||||||
params.add(newIdentDefs(ident(arg.name), ident(arg.typ), defaultValue))
|
params.add(newIdentDefs(ident(arg.name), ident(arg.typ), defaultValue))
|
||||||
of ArgKind.VarArgs:
|
of ArgKind.VarArgs:
|
||||||
params.add(newIdentDefs(ident(arg.name),
|
params.add(newIdentDefs(ident(arg.name),
|
||||||
newNode(nkBracketExpr).addChain(ident("varargs"), ident(arg.typ))))
|
newPNode(nkBracketExpr).addChain(ident("varargs"), ident(arg.typ))))
|
||||||
of ArgKind.Bound:
|
of ArgKind.Bound:
|
||||||
discard
|
discard
|
||||||
|
|
||||||
|
|
@ -643,14 +745,14 @@ proc doGenerateMethod(tree: PNode, methodBindRegistry: var HashSet[string],
|
||||||
else: meth.name,
|
else: meth.name,
|
||||||
params, body, procType)
|
params, body, procType)
|
||||||
if not withImplementation:
|
if not withImplementation:
|
||||||
let pragma = newNode(nkPragma)
|
let pragma = newPNode(nkPragma)
|
||||||
pragma.add(ident("gcsafe"))
|
pragma.add(ident("gcsafe"))
|
||||||
pragma.add(newNode(nkExprColonExpr).addChain(ident("locks"),
|
pragma.add(newPNode(nkExprColonExpr).addChain(ident("locks"),
|
||||||
newIntLit(0)))
|
newIntLit(0)))
|
||||||
if meth.isVirtual and meth.isBase and meth.typ.name != "PhysicsBody":
|
if meth.isVirtual and meth.isBase and meth.typ.name != "PhysicsBody":
|
||||||
# Nim doesn't like `base` on PhysicsBody methods - wtf
|
# Nim doesn't like `base` on PhysicsBody methods - wtf
|
||||||
pragma.add(ident("base"))
|
pragma.add(ident("base"))
|
||||||
if meth.isDiscardable and not meth.returnType.isNil:
|
if meth.isDiscardable and meth.returnType.isSome:
|
||||||
pragma.add(ident("discardable"))
|
pragma.add(ident("discardable"))
|
||||||
procDecl.sons[4] = pragma
|
procDecl.sons[4] = pragma
|
||||||
tree.add(procDecl)
|
tree.add(procDecl)
|
||||||
|
|
@ -695,9 +797,9 @@ proc getMethodInfo(methodObj: JsonNode, types: Table[string, GodotType],
|
||||||
nimName = nimName & "Impl"
|
nimName = nimName & "Impl"
|
||||||
|
|
||||||
let returnType = if methodObj["return_type"].str != "void":
|
let returnType = if methodObj["return_type"].str != "void":
|
||||||
toNimType(types, methodObj["return_type"].str)
|
some(toNimType(types, methodObj["return_type"].str))
|
||||||
else: nil
|
else: none(string)
|
||||||
const discardableMethods = toSet(["emit_signal"])
|
const discardableMethods = toHashSet(["emit_signal"])
|
||||||
result = MethodInfo(
|
result = MethodInfo(
|
||||||
name: ident(nimName),
|
name: ident(nimName),
|
||||||
typ: typ,
|
typ: typ,
|
||||||
|
|
@ -719,19 +821,24 @@ proc makeProperty(types: Table[string, GodotType], tree: PNode,
|
||||||
methodBindRegistry: var HashSet[string],
|
methodBindRegistry: var HashSet[string],
|
||||||
typ: GodotType, propertyObj: JsonNode, obj: JsonNode,
|
typ: GodotType, propertyObj: JsonNode, obj: JsonNode,
|
||||||
withImplementation: bool) =
|
withImplementation: bool) =
|
||||||
|
for meth in obj["methods"]:
|
||||||
|
if meth["name"].str == '_' & propertyObj["name"].str:
|
||||||
|
# Don't generate properties if there is a name clash - otherwise
|
||||||
|
# using the property would not compile due to ambiguity.
|
||||||
|
return
|
||||||
let getterNameStr = toNimStyle(propertyObj["name"].str)
|
let getterNameStr = toNimStyle(propertyObj["name"].str)
|
||||||
let getterName = ident(getterNameStr)
|
let getterName = ident(getterNameStr)
|
||||||
let setterName = newNode(nkAccQuoted).addChain(ident(getterNameStr & "="))
|
let setterName = newPNode(nkAccQuoted).addChain(ident(getterNameStr & "="))
|
||||||
|
|
||||||
let getter = findMethod(obj, propertyObj["getter"].str)
|
let getter = findMethod(obj, propertyObj["getter"].str)
|
||||||
let nimType = if getter.isNil: toNimType(types, propertyObj["type"].str)
|
let nimType = if getter.isNil: toNimType(types, propertyObj["type"].str)
|
||||||
else: getMethodInfo(getter, types, typ).returnType
|
else: getMethodInfo(getter, types, typ).returnType.get("void")
|
||||||
let getterInfo = MethodInfo(
|
let getterInfo = MethodInfo(
|
||||||
name: getterName,
|
name: getterName,
|
||||||
typ: typ,
|
typ: typ,
|
||||||
godotName: propertyObj["getter"].str,
|
godotName: propertyObj["getter"].str,
|
||||||
args: @[],
|
args: newSeq[MethodArg](),
|
||||||
returnType: nimType
|
returnType: some(nimType)
|
||||||
)
|
)
|
||||||
let setterInfo = MethodInfo(
|
let setterInfo = MethodInfo(
|
||||||
name: setterName,
|
name: setterName,
|
||||||
|
|
@ -740,10 +847,12 @@ proc makeProperty(types: Table[string, GodotType], tree: PNode,
|
||||||
args: @[MethodArg(name: "val", typ: nimType)]
|
args: @[MethodArg(name: "val", typ: nimType)]
|
||||||
)
|
)
|
||||||
if "index" in propertyObj and propertyObj["index"] != newJInt(-1):
|
if "index" in propertyObj and propertyObj["index"] != newJInt(-1):
|
||||||
getterInfo.args = @[MethodArg(defaultVal: newJString($propertyObj["index"]),
|
getterInfo.args =
|
||||||
typ: "int", kind: ArgKind.Bound)] & getterInfo.args
|
@[MethodArg(defaultVal: newJString($propertyObj["index"]),
|
||||||
setterInfo.args = @[MethodArg(defaultVal: newJString($propertyObj["index"]),
|
typ: "int", kind: ArgKind.Bound)] & getterInfo.args
|
||||||
typ: "int", kind: ArgKind.Bound)] & setterInfo.args
|
setterInfo.args =
|
||||||
|
@[MethodArg(defaultVal: newJString($propertyObj["index"]),
|
||||||
|
typ: "int", kind: ArgKind.Bound)] & setterInfo.args
|
||||||
generateMethod(tree, methodBindRegistry, getterInfo, withImplementation)
|
generateMethod(tree, methodBindRegistry, getterInfo, withImplementation)
|
||||||
generateMethod(tree, methodBindRegistry, setterInfo, withImplementation)
|
generateMethod(tree, methodBindRegistry, setterInfo, withImplementation)
|
||||||
|
|
||||||
|
|
@ -757,8 +866,14 @@ proc makeMethod(types: Table[string, GodotType], tree: PNode,
|
||||||
# supposed to be used on an object (have at least 2 params).
|
# supposed to be used on an object (have at least 2 params).
|
||||||
for prop in typ.jsonNode["properties"]:
|
for prop in typ.jsonNode["properties"]:
|
||||||
if prop["getter"].str == methodObj["name"].str or
|
if prop["getter"].str == methodObj["name"].str or
|
||||||
prop["setter"].str == methodObj["name"].str:
|
prop["setter"].str == methodObj["name"].str:
|
||||||
return
|
var hasDuplicateMethod = false
|
||||||
|
for meth in typ.jsonNode["methods"]:
|
||||||
|
if meth["name"].str == '_' & prop["name"].str:
|
||||||
|
hasDuplicateMethod = true
|
||||||
|
break
|
||||||
|
if not hasDuplicateMethod:
|
||||||
|
return
|
||||||
|
|
||||||
let methodInfo = getMethodInfo(methodObj, types, typ)
|
let methodInfo = getMethodInfo(methodObj, types, typ)
|
||||||
|
|
||||||
|
|
@ -794,15 +909,15 @@ proc typeNameToModuleName(name: string): string =
|
||||||
proc newRegisterClassNode(typ: GodotType): PNode =
|
proc newRegisterClassNode(typ: GodotType): PNode =
|
||||||
newCall("registerClass",
|
newCall("registerClass",
|
||||||
ident(typ.name),
|
ident(typ.name),
|
||||||
newCStringLit(typ.godotName),
|
newStrLit(typ.godotName),
|
||||||
ident("true") # isNative
|
ident("true") # isNative
|
||||||
)
|
)
|
||||||
|
|
||||||
proc genSingletonDecl(typ: string): PNode =
|
proc genSingletonDecl(typ: string): PNode =
|
||||||
result = newNode(nkVarSection)
|
result = newPNode(nkVarSection)
|
||||||
let name = singletonName(typ)
|
let name = singletonName(typ)
|
||||||
let threadvar = newNode(nkPragma).addChain(ident("threadvar"))
|
let threadvar = newPNode(nkPragma).addChain(ident("threadvar"))
|
||||||
result.add(newIdentDefs(newNode(nkPragmaExpr).addChain(name, threadvar),
|
result.add(newIdentDefs(newPNode(nkPragmaExpr).addChain(name, threadvar),
|
||||||
ident(typ)))
|
ident(typ)))
|
||||||
|
|
||||||
proc shouldExport(typ: GodotType, types: Table[string, GodotType]): bool =
|
proc shouldExport(typ: GodotType, types: Table[string, GodotType]): bool =
|
||||||
|
|
@ -819,9 +934,9 @@ proc sortByDerivedCount(types: Table[string, GodotType]): seq[GodotType] =
|
||||||
proc genTypeFile(types: Table[string, GodotType], targetDir: string) =
|
proc genTypeFile(types: Table[string, GodotType], targetDir: string) =
|
||||||
let sortedTypes = sortByDerivedCount(types)
|
let sortedTypes = sortByDerivedCount(types)
|
||||||
|
|
||||||
let godotApiTypesTree = newNode(nkStmtList)
|
let godotApiTypesTree = newPNode(nkStmtList)
|
||||||
godotApiTypesTree.add(newNode(nkImportStmt).addChain(ident("godot")))
|
godotApiTypesTree.add(newPNode(nkImportStmt).addChain(ident("godot")))
|
||||||
let typeSection = newNode(nkTypeSection)
|
let typeSection = newPNode(nkTypeSection)
|
||||||
godotApiTypesTree.add(typeSection)
|
godotApiTypesTree.add(typeSection)
|
||||||
|
|
||||||
for typ in sortedTypes:
|
for typ in sortedTypes:
|
||||||
|
|
@ -832,7 +947,7 @@ proc genTypeFile(types: Table[string, GodotType], targetDir: string) =
|
||||||
if not typ.shouldExport(types): continue
|
if not typ.shouldExport(types): continue
|
||||||
let regNode = newCall("registerClass",
|
let regNode = newCall("registerClass",
|
||||||
ident(typ.name),
|
ident(typ.name),
|
||||||
newCStringLit(typ.godotName),
|
newStrLit(typ.godotName),
|
||||||
ident("true") # isNative
|
ident("true") # isNative
|
||||||
)
|
)
|
||||||
godotApiTypesTree.add(regNode)
|
godotApiTypesTree.add(regNode)
|
||||||
|
|
@ -843,10 +958,10 @@ proc genSingletonWithDerived(tree: PNode, typ: GodotType,
|
||||||
types: Table[string, GodotType]) =
|
types: Table[string, GodotType]) =
|
||||||
let sortedTypes = sortByDerivedCount(types)
|
let sortedTypes = sortByDerivedCount(types)
|
||||||
|
|
||||||
var parents = initSet[string]()
|
var parents = initHashSet[string]()
|
||||||
parents.incl(typ.name)
|
parents.incl(typ.name)
|
||||||
|
|
||||||
let typeDecl = newNode(nkTypeSection)
|
let typeDecl = newPNode(nkTypeSection)
|
||||||
tree.add(typeDecl)
|
tree.add(typeDecl)
|
||||||
proc genDecl(typ: GodotType) =
|
proc genDecl(typ: GodotType) =
|
||||||
newRefTypeNode(typeDecl, typ.name, typ.baseName, typ.doc,
|
newRefTypeNode(typeDecl, typ.name, typ.baseName, typ.doc,
|
||||||
|
|
@ -875,7 +990,7 @@ proc genApi*(targetDir: string, apiJsonFile: string) =
|
||||||
let className = godotClassName.replace("_", "")
|
let className = godotClassName.replace("_", "")
|
||||||
var baseClassName = obj["base_class"].str
|
var baseClassName = obj["base_class"].str
|
||||||
baseClassName = toNimType(baseClassName.replace("_", ""))
|
baseClassName = toNimType(baseClassName.replace("_", ""))
|
||||||
if baseClassName.isNil or baseClassName.len == 0:
|
if baseClassName.len == 0:
|
||||||
baseClassName = "NimGodotObject"
|
baseClassName = "NimGodotObject"
|
||||||
var doc = ""
|
var doc = ""
|
||||||
for attr in classAttributes:
|
for attr in classAttributes:
|
||||||
|
|
@ -896,17 +1011,17 @@ proc genApi*(targetDir: string, apiJsonFile: string) =
|
||||||
for typ in types.values():
|
for typ in types.values():
|
||||||
let moduleName = typeNameToModuleName(typ.name)
|
let moduleName = typeNameToModuleName(typ.name)
|
||||||
echo "Generating ", moduleName, ".nim..."
|
echo "Generating ", moduleName, ".nim..."
|
||||||
let tree = newNode(nkStmtList)
|
let tree = newPNode(nkStmtList)
|
||||||
let importStmt = newNode(nkImportStmt)
|
let importStmt = newPNode(nkImportStmt)
|
||||||
importStmt.add(ident("godot"))
|
importStmt.add(ident("godot"))
|
||||||
importStmt.add(ident("godottypes"))
|
importStmt.add(ident("godottypes"))
|
||||||
importStmt.add(ident("godotinternal"))
|
importStmt.add(ident("godotinternal"))
|
||||||
tree.add(importStmt)
|
tree.add(importStmt)
|
||||||
let exportStmt = newNode(nkExportStmt)
|
let exportStmt = newPNode(nkExportStmt)
|
||||||
exportStmt.add(ident("godottypes"))
|
exportStmt.add(ident("godottypes"))
|
||||||
tree.add(exportStmt)
|
tree.add(exportStmt)
|
||||||
|
|
||||||
var methodBindRegsitry = initSet[string]()
|
var methodBindRegsitry = initHashSet[string]()
|
||||||
let obj = typ.jsonNode
|
let obj = typ.jsonNode
|
||||||
if typ.baseName != "NimGodotObject":
|
if typ.baseName != "NimGodotObject":
|
||||||
let baseModule = typeNameToModuleName(typ.baseName)
|
let baseModule = typeNameToModuleName(typ.baseName)
|
||||||
|
|
@ -967,7 +1082,6 @@ when isMainModule:
|
||||||
import os
|
import os
|
||||||
|
|
||||||
const usage = """Tool for wrapping Godot API into Nim
|
const usage = """Tool for wrapping Godot API into Nim
|
||||||
|
|
||||||
godotapigen [godot binary path] [target directory]"""
|
godotapigen [godot binary path] [target directory]"""
|
||||||
|
|
||||||
proc main() =
|
proc main() =
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,8 @@
|
||||||
# Copyright 2018 Xored Software, Inc.
|
# Copyright 2018 Xored Software, Inc.
|
||||||
|
|
||||||
import internal.godotinternaltypes, internal.godotarrays,
|
import internal/godotinternaltypes, internal/godotarrays,
|
||||||
internal.godotnodepaths, internal.godotpoolarrays, internal.godotstrings,
|
internal/godotnodepaths, internal/godotpoolarrays, internal/godotstrings,
|
||||||
internal.godotvariants, internal.godotdictionaries
|
internal/godotvariants, internal/godotdictionaries
|
||||||
|
|
||||||
import gdnativeapi
|
import gdnativeapi
|
||||||
export godotinternaltypes, godotarrays, godotnodepaths, godotpoolarrays,
|
export godotinternaltypes, godotarrays, godotnodepaths, godotpoolarrays,
|
||||||
|
|
@ -93,6 +93,11 @@ proc getClassName*(o: ptr GodotObject): string =
|
||||||
# There are physics type not known by ClassDB
|
# There are physics type not known by ClassDB
|
||||||
result = result[0..result.len-3]
|
result = result[0..result.len-3]
|
||||||
|
|
||||||
|
proc getClassNameRaw*(o: ptr GodotObject): GodotString =
|
||||||
|
if getClassMethodBind.isNil:
|
||||||
|
getClassMethodBind = getMethod(cstring"Object", cstring"get_class")
|
||||||
|
getClassMethodBind.ptrCall(o, nil, addr result)
|
||||||
|
|
||||||
proc getGodotSingleton*(name: cstring): ptr GodotObject {.inline.} =
|
proc getGodotSingleton*(name: cstring): ptr GodotObject {.inline.} =
|
||||||
getGDNativeAPI().globalGetSingleton(name)
|
getGDNativeAPI().globalGetSingleton(name)
|
||||||
|
|
||||||
|
|
|
||||||
19
godot/internal/backwardcompat.inc.nim
Normal file
19
godot/internal/backwardcompat.inc.nim
Normal file
|
|
@ -0,0 +1,19 @@
|
||||||
|
# Copyright 2019 Xored Software, Inc.
|
||||||
|
|
||||||
|
when (NimMajor, NimMinor, NimPatch) < (0, 19, 0):
|
||||||
|
import macros, sets
|
||||||
|
|
||||||
|
proc strVal(n: NimNode): string {.used.} =
|
||||||
|
case n.kind
|
||||||
|
of nnkIdent:
|
||||||
|
$n.ident
|
||||||
|
of nnkSym:
|
||||||
|
$n.symbol
|
||||||
|
else:
|
||||||
|
macros.strVal(n)
|
||||||
|
|
||||||
|
proc toHashSet[A](keys: openArray[A]): HashSet[A] {.inline, used.} =
|
||||||
|
toSet(keys)
|
||||||
|
|
||||||
|
proc initHashSet[A](): HashSet[A] {.inline, used.} =
|
||||||
|
initSet[A]()
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
# Copyright (c) 2018 Xored Software, Inc.
|
# Copyright (c) 2018 Xored Software, Inc.
|
||||||
|
|
||||||
import godotinternaltypes, gdnativeapi, core.godotcoretypes
|
import godotinternaltypes, gdnativeapi, core/godotcoretypes
|
||||||
|
|
||||||
proc len*(self: GodotArray): cint {.inline.} =
|
proc len*(self: GodotArray): cint {.inline.} =
|
||||||
getGDNativeAPI().arraySize(self)
|
getGDNativeAPI().arraySize(self)
|
||||||
|
|
|
||||||
|
|
@ -66,6 +66,8 @@ type
|
||||||
GodotString* {.byref.} = object
|
GodotString* {.byref.} = object
|
||||||
data: array[sizeof(int), byte]
|
data: array[sizeof(int), byte]
|
||||||
|
|
||||||
|
cwchar_t* {.importc: "wchar_t", nodecl.} = object
|
||||||
|
|
||||||
GodotCharString* {.byref.} = object
|
GodotCharString* {.byref.} = object
|
||||||
data: array[sizeof(int), byte]
|
data: array[sizeof(int), byte]
|
||||||
|
|
||||||
|
|
@ -114,7 +116,8 @@ type
|
||||||
expected*: VariantType
|
expected*: VariantType
|
||||||
|
|
||||||
GodotVariant* {.byref.} = object
|
GodotVariant* {.byref.} = object
|
||||||
data: array[4 + sizeof(int) div 4, float32]
|
data: array[2, int64]
|
||||||
|
data2: int
|
||||||
|
|
||||||
type GodotMethodBind* = object
|
type GodotMethodBind* = object
|
||||||
|
|
||||||
|
|
@ -305,3 +308,6 @@ type
|
||||||
|
|
||||||
GodotClassConstructor* = proc (): ptr GodotObject {.
|
GodotClassConstructor* = proc (): ptr GodotObject {.
|
||||||
noconv, gcsafe, locks: 0, raises: [], tags: [].}
|
noconv, gcsafe, locks: 0, raises: [], tags: [].}
|
||||||
|
|
||||||
|
template offset*[T](p: ptr T, offset: int): ptr T =
|
||||||
|
cast[ptr T](cast[ByteAddress](p) +% (offset * sizeof(T)))
|
||||||
|
|
@ -1,10 +1,7 @@
|
||||||
# Copyright (c) 2018 Xored Software, Inc.
|
# Copyright (c) 2018 Xored Software, Inc.
|
||||||
|
|
||||||
import godotinternaltypes, gdnativeapi
|
import godotinternaltypes, gdnativeapi
|
||||||
import core.godotcoretypes
|
import core/godotcoretypes
|
||||||
|
|
||||||
proc offset[T](p: ptr T, offset: int): ptr T {.inline.} =
|
|
||||||
cast[ptr T](cast[ByteAddress](p) +% (offset * sizeof(T)))
|
|
||||||
|
|
||||||
template genPoolArrayAPI(ArrayT, initIdent, DataT,
|
template genPoolArrayAPI(ArrayT, initIdent, DataT,
|
||||||
newProc, newCopyProc, newWithArrayProc, appendProc,
|
newProc, newCopyProc, newWithArrayProc, appendProc,
|
||||||
|
|
@ -48,7 +45,15 @@ template genPoolArrayAPI(ArrayT, initIdent, DataT,
|
||||||
getGDNativeAPI().setProc(self, idx, data)
|
getGDNativeAPI().setProc(self, idx, data)
|
||||||
|
|
||||||
proc `[]`*(self: ArrayT; idx: cint): DataT {.inline.} =
|
proc `[]`*(self: ArrayT; idx: cint): DataT {.inline.} =
|
||||||
getGDNativeAPI().getProc(self, idx)
|
let data = getGDNativeAPI().getProc(self, idx)
|
||||||
|
when DataT is Color:
|
||||||
|
data.toColor()
|
||||||
|
elif DataT is Vector2:
|
||||||
|
data.toVector2()
|
||||||
|
elif DataT is Vector3:
|
||||||
|
data.toVector3()
|
||||||
|
else:
|
||||||
|
data
|
||||||
|
|
||||||
proc len*(self: ArrayT): cint {.inline.} =
|
proc len*(self: ArrayT): cint {.inline.} =
|
||||||
getGDNativeAPI().sizeProc(self)
|
getGDNativeAPI().sizeProc(self)
|
||||||
|
|
@ -91,14 +96,14 @@ template genPoolArrayAPI(ArrayT, initIdent, DataT,
|
||||||
|
|
||||||
initIdent(result)
|
initIdent(result)
|
||||||
if actualIdxFrom < 0 or actualIdxFrom >= ownLen:
|
if actualIdxFrom < 0 or actualIdxFrom >= ownLen:
|
||||||
let (file, line) = instantiationInfo()
|
let instInfo = instantiationInfo()
|
||||||
getGDNativeAPI().printError(
|
getGDNativeAPI().printError(
|
||||||
cstring"Invalid subarray begin index", cstring"subarray", file, line.cint)
|
cstring"Invalid subarray begin index", cstring"subarray", instInfo.filename, instInfo.line.cint)
|
||||||
return
|
return
|
||||||
if actualIdxTo < 0 or actualIdxTo >= ownLen:
|
if actualIdxTo < 0 or actualIdxTo >= ownLen:
|
||||||
let (file, line) = instantiationInfo()
|
let instInfo = instantiationInfo()
|
||||||
getGDNativeAPI().printError(
|
getGDNativeAPI().printError(
|
||||||
cstring"Invalid subarray end index", cstring"subarray", file, line.cint)
|
cstring"Invalid subarray end index", cstring"subarray", instInfo.filename, instInfo.line.cint)
|
||||||
return
|
return
|
||||||
let span = actualIdxTo - actualIdxFrom + 1
|
let span = actualIdxTo - actualIdxFrom + 1
|
||||||
result.setLen(span)
|
result.setLen(span)
|
||||||
|
|
|
||||||
|
|
@ -22,6 +22,12 @@ proc `&`*(self, b: GodotString): GodotString {.inline.} =
|
||||||
proc deinit*(self: var GodotString) {.inline.} =
|
proc deinit*(self: var GodotString) {.inline.} =
|
||||||
getGDNativeAPI().stringDestroy(self)
|
getGDNativeAPI().stringDestroy(self)
|
||||||
|
|
||||||
|
proc len*(self: GodotString): cint {.inline.} =
|
||||||
|
getGDNativeAPI().stringLength(self)
|
||||||
|
|
||||||
|
proc dataPtr*(self: GodotString): ptr cwchar_t {.inline.} =
|
||||||
|
getGDNativeAPI().stringWideStr(self)
|
||||||
|
|
||||||
proc `$`*(self: GodotString): string =
|
proc `$`*(self: GodotString): string =
|
||||||
## Converts the ``GodotString`` into Nim string
|
## Converts the ``GodotString`` into Nim string
|
||||||
var charStr = getGDNativeAPI().stringUtf8(self)
|
var charStr = getGDNativeAPI().stringUtf8(self)
|
||||||
|
|
@ -29,14 +35,16 @@ proc `$`*(self: GodotString): string =
|
||||||
result = newString(length)
|
result = newString(length)
|
||||||
copyMem(addr result[0], getGDNativeAPI().charStringGetData(charStr), length)
|
copyMem(addr result[0], getGDNativeAPI().charStringGetData(charStr), length)
|
||||||
getGDNativeAPI().charStringDestroy(charStr)
|
getGDNativeAPI().charStringDestroy(charStr)
|
||||||
assert(result[length] == '\0')
|
|
||||||
|
|
||||||
proc toGodotString*(s: string): GodotString {.inline.} =
|
proc toGodotString*(s: string): GodotString {.inline.} =
|
||||||
## Converts the Nim string into ``GodotString``
|
## Converts the Nim string into ``GodotString``
|
||||||
if s.isNil:
|
when (NimMajor, NimMinor, NimPatch) < (0, 19, 0):
|
||||||
initGodotString(result)
|
if s.isNil:
|
||||||
|
initGodotString(result)
|
||||||
|
else:
|
||||||
|
initGodotString(result, cstring(s), cint(s.len + 1))
|
||||||
else:
|
else:
|
||||||
initGodotString(result, unsafeAddr s[0], cint(s.len + 1))
|
initGodotString(result, cstring(s), cint(s.len + 1))
|
||||||
|
|
||||||
proc toGodotString*(s: cstring): GodotString {.inline.} =
|
proc toGodotString*(s: cstring): GodotString {.inline.} =
|
||||||
## Converts the cstring into ``GodotString``
|
## Converts the cstring into ``GodotString``
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
# Copyright 2018 Xored Software, Inc.
|
# Copyright 2018 Xored Software, Inc.
|
||||||
|
|
||||||
import core.godotcoretypes, godotinternaltypes, gdnativeapi
|
import core/godotcoretypes, godotinternaltypes, gdnativeapi
|
||||||
|
|
||||||
proc getType*(p: GodotVariant): VariantType {.inline.} =
|
proc getType*(p: GodotVariant): VariantType {.inline.} =
|
||||||
getGDNativeAPI().variantGetType(p)
|
getGDNativeAPI().variantGetType(p)
|
||||||
|
|
@ -121,34 +121,34 @@ proc asGodotString*(self: GodotVariant): GodotString {.inline.} =
|
||||||
getGDNativeAPI().variantAsString(self)
|
getGDNativeAPI().variantAsString(self)
|
||||||
|
|
||||||
proc asVector2*(self: GodotVariant): Vector2 {.inline.} =
|
proc asVector2*(self: GodotVariant): Vector2 {.inline.} =
|
||||||
getGDNativeAPI().variantAsVector2(self)
|
getGDNativeAPI().variantAsVector2(self).toVector2()
|
||||||
|
|
||||||
proc asRect2*(self: GodotVariant): Rect2 {.inline.} =
|
proc asRect2*(self: GodotVariant): Rect2 {.inline.} =
|
||||||
getGDNativeAPI().variantAsRect2(self)
|
getGDNativeAPI().variantAsRect2(self).toRect2()
|
||||||
|
|
||||||
proc asVector3*(self: GodotVariant): Vector3 {.inline.} =
|
proc asVector3*(self: GodotVariant): Vector3 {.inline.} =
|
||||||
getGDNativeAPI().variantAsVector3(self)
|
getGDNativeAPI().variantAsVector3(self).toVector3()
|
||||||
|
|
||||||
proc asTransform2D*(self: GodotVariant): Transform2D {.inline.} =
|
proc asTransform2D*(self: GodotVariant): Transform2D {.inline.} =
|
||||||
getGDNativeAPI().variantAsTransform2D(self)
|
getGDNativeAPI().variantAsTransform2D(self).toTransform2D()
|
||||||
|
|
||||||
proc asPlane*(self: GodotVariant): Plane {.inline.} =
|
proc asPlane*(self: GodotVariant): Plane {.inline.} =
|
||||||
getGDNativeAPI().variantAsPlane(self)
|
getGDNativeAPI().variantAsPlane(self).toPlane()
|
||||||
|
|
||||||
proc asQuat*(self: GodotVariant): Quat {.inline.} =
|
proc asQuat*(self: GodotVariant): Quat {.inline.} =
|
||||||
getGDNativeAPI().variantAsQuat(self)
|
getGDNativeAPI().variantAsQuat(self).toQuat()
|
||||||
|
|
||||||
proc asAABB*(self: GodotVariant): AABB {.inline.} =
|
proc asAABB*(self: GodotVariant): AABB {.inline.} =
|
||||||
getGDNativeAPI().variantAsAABB(self)
|
getGDNativeAPI().variantAsAABB(self).toAABB()
|
||||||
|
|
||||||
proc asBasis*(self: GodotVariant): Basis {.inline.} =
|
proc asBasis*(self: GodotVariant): Basis {.inline.} =
|
||||||
getGDNativeAPI().variantAsBasis(self)
|
getGDNativeAPI().variantAsBasis(self).toBasis()
|
||||||
|
|
||||||
proc asTransform*(self: GodotVariant): Transform {.inline.} =
|
proc asTransform*(self: GodotVariant): Transform {.inline.} =
|
||||||
getGDNativeAPI().variantAsTransform(self)
|
getGDNativeAPI().variantAsTransform(self).toTransform()
|
||||||
|
|
||||||
proc asColor*(self: GodotVariant): Color {.inline.} =
|
proc asColor*(self: GodotVariant): Color {.inline.} =
|
||||||
getGDNativeAPI().variantAsColor(self)
|
getGDNativeAPI().variantAsColor(self).toColor()
|
||||||
|
|
||||||
proc asNodePath*(self: GodotVariant): GodotNodePath {.inline.} =
|
proc asNodePath*(self: GodotVariant): GodotNodePath {.inline.} =
|
||||||
getGDNativeAPI().variantAsNodePath(self)
|
getGDNativeAPI().variantAsNodePath(self)
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,8 @@
|
||||||
# Copyright 2018 Xored Software, Inc.
|
# Copyright 2018 Xored Software, Inc.
|
||||||
|
|
||||||
import macros, tables, typetraits
|
import macros, tables, typetraits, strutils, sets, sequtils, options, algorithm
|
||||||
import godotinternal, internal.godotvariants
|
import godotinternal, internal/godotvariants
|
||||||
import godotnim, core.variants
|
import godotnim, core/variants
|
||||||
|
|
||||||
type
|
type
|
||||||
VarDecl = ref object
|
VarDecl = ref object
|
||||||
|
|
@ -10,8 +10,8 @@ type
|
||||||
typ: NimNode
|
typ: NimNode
|
||||||
defaultValue: NimNode
|
defaultValue: NimNode
|
||||||
isNoGodot: bool
|
isNoGodot: bool
|
||||||
hint: string
|
hint: Option[string]
|
||||||
hintStr: string
|
hintStr: Option[string]
|
||||||
usage: NimNode
|
usage: NimNode
|
||||||
isExported: bool
|
isExported: bool
|
||||||
|
|
||||||
|
|
@ -32,6 +32,8 @@ type
|
||||||
|
|
||||||
ParseError = object of Exception
|
ParseError = object of Exception
|
||||||
|
|
||||||
|
include "internal/backwardcompat.inc.nim"
|
||||||
|
|
||||||
proc godotToNim[T](val: Variant): (T, ConversionResult) =
|
proc godotToNim[T](val: Variant): (T, ConversionResult) =
|
||||||
mixin fromVariant
|
mixin fromVariant
|
||||||
result[1] = fromVariant(result[0], val)
|
result[1] = fromVariant(result[0], val)
|
||||||
|
|
@ -51,15 +53,15 @@ template parseError(node: NimNode, msg: string) =
|
||||||
proc extractNames(definition: NimNode):
|
proc extractNames(definition: NimNode):
|
||||||
tuple[name, parentName: string] =
|
tuple[name, parentName: string] =
|
||||||
if definition.kind == nnkIdent:
|
if definition.kind == nnkIdent:
|
||||||
result.name = $(definition.ident)
|
result.name = definition.strVal
|
||||||
else:
|
else:
|
||||||
if not (definition.kind == nnkInfix and
|
if not (definition.kind == nnkInfix and
|
||||||
definition[0].ident == toNimIdent("of")):
|
definition[0].strVal == "of"):
|
||||||
parseError(definition, "invalid type definition")
|
parseError(definition, "invalid type definition")
|
||||||
result.name = $(definition[1].ident)
|
result.name = definition[1].strVal
|
||||||
case definition[2].kind:
|
case definition[2].kind:
|
||||||
of nnkIdent:
|
of nnkIdent:
|
||||||
result.parentName = $definition[2].ident
|
result.parentName = definition[2].strVal
|
||||||
else:
|
else:
|
||||||
parseError(definition[2], "parent type expected")
|
parseError(definition[2], "parent type expected")
|
||||||
|
|
||||||
|
|
@ -72,13 +74,13 @@ proc newCStringLit(s: string): NimNode {.compileTime.} =
|
||||||
newNimNode(nnkCallStrLit).add(ident("cstring"), newRStrLit(s))
|
newNimNode(nnkCallStrLit).add(ident("cstring"), newRStrLit(s))
|
||||||
|
|
||||||
iterator pragmas(node: NimNode):
|
iterator pragmas(node: NimNode):
|
||||||
tuple[key: NimIdent, value: NimNode, index: int] =
|
tuple[key: string, value: NimNode, index: int] =
|
||||||
assert node.kind in {nnkPragma, nnkEmpty}
|
assert node.kind in {nnkPragma, nnkEmpty}
|
||||||
for index in countdown(node.len - 1, 0):
|
for index in countdown(node.len - 1, 0):
|
||||||
if node[index].kind == nnkExprColonExpr:
|
if node[index].kind == nnkExprColonExpr:
|
||||||
yield (node[index][0].ident, node[index][1], index)
|
yield (node[index][0].strVal, node[index][1], index)
|
||||||
elif node[index].kind == nnkIdent:
|
elif node[index].kind == nnkIdent:
|
||||||
yield (node[index].ident, nil, index)
|
yield (node[index].strVal, nil, index)
|
||||||
|
|
||||||
proc removePragmaNode(statement: NimNode,
|
proc removePragmaNode(statement: NimNode,
|
||||||
pname: string): NimNode {.compileTime.} =
|
pname: string): NimNode {.compileTime.} =
|
||||||
|
|
@ -91,9 +93,8 @@ proc removePragmaNode(statement: NimNode,
|
||||||
result = nil
|
result = nil
|
||||||
var pragmas = if RoutineNodes.contains(statement.kind): statement.pragma()
|
var pragmas = if RoutineNodes.contains(statement.kind): statement.pragma()
|
||||||
else: statement[1]
|
else: statement[1]
|
||||||
let pnameIdent = toNimIdent(pname)
|
|
||||||
for ident, val, i in pragmas(pragmas):
|
for ident, val, i in pragmas(pragmas):
|
||||||
if ident == pnameIdent:
|
if ident.eqIdent(pname):
|
||||||
pragmas.del(i)
|
pragmas.del(i)
|
||||||
return val
|
return val
|
||||||
|
|
||||||
|
|
@ -104,19 +105,18 @@ proc removePragma(statement: NimNode, pname: string): bool =
|
||||||
return false
|
return false
|
||||||
var pragmas = if RoutineNodes.contains(statement.kind): statement.pragma()
|
var pragmas = if RoutineNodes.contains(statement.kind): statement.pragma()
|
||||||
else: statement[1]
|
else: statement[1]
|
||||||
let pnameIdent = toNimIdent(pname)
|
|
||||||
for ident, val, i in pragmas(pragmas):
|
for ident, val, i in pragmas(pragmas):
|
||||||
if ident == pnameIdent:
|
if ident.eqIdent(pname):
|
||||||
pragmas.del(i)
|
pragmas.del(i)
|
||||||
return true
|
return true
|
||||||
|
|
||||||
proc removeStrPragma(statement: NimNode,
|
proc removeStrPragma(statement: NimNode,
|
||||||
pname: string): string {.compileTime.} =
|
pname: string): Option[string] {.compileTime.} =
|
||||||
## Removes the pragma from the node and returns value of the pragma
|
## Removes the pragma from the node and returns value of the pragma
|
||||||
## Works for routine nodes or nnkPragmaExpr
|
## Works for routine nodes or nnkPragmaExpr
|
||||||
let node = removePragmaNode(statement, pname)
|
let node = removePragmaNode(statement, pname)
|
||||||
result = if node.isNil: nil
|
result = if node.isNil: none(string)
|
||||||
else: $node
|
else: some($node)
|
||||||
|
|
||||||
proc isExported(node: NimNode): bool {.compileTime.} =
|
proc isExported(node: NimNode): bool {.compileTime.} =
|
||||||
if node.kind == nnkPragmaExpr:
|
if node.kind == nnkPragmaExpr:
|
||||||
|
|
@ -172,10 +172,15 @@ proc parseMethod(meth: NimNode): MethodDecl =
|
||||||
|
|
||||||
proc parseVarSection(decl: NimNode): seq[VarDecl] =
|
proc parseVarSection(decl: NimNode): seq[VarDecl] =
|
||||||
assert(decl.kind == nnkVarSection)
|
assert(decl.kind == nnkVarSection)
|
||||||
result = identDefsToVarDecls(decl[0])
|
for i in 0..<decl.len:
|
||||||
|
if i == 0:
|
||||||
|
result = identDefsToVarDecls(decl[i])
|
||||||
|
else:
|
||||||
|
result.add(identDefsToVarDecls(decl[i]))
|
||||||
|
|
||||||
proc parseType(definition, callSite: NimNode): ObjectDecl =
|
proc parseType(ast: NimNode): ObjectDecl =
|
||||||
let body = callSite[^1]
|
let definition = ast[0]
|
||||||
|
let body = ast[^1]
|
||||||
result = ObjectDecl(
|
result = ObjectDecl(
|
||||||
fields: newSeq[VarDecl](),
|
fields: newSeq[VarDecl](),
|
||||||
methods: newSeq[MethodDecl]()
|
methods: newSeq[MethodDecl]()
|
||||||
|
|
@ -183,17 +188,17 @@ proc parseType(definition, callSite: NimNode): ObjectDecl =
|
||||||
(result.name, result.parentName) = extractNames(definition)
|
(result.name, result.parentName) = extractNames(definition)
|
||||||
|
|
||||||
var isTool = false
|
var isTool = false
|
||||||
for i in 2..(callSite.len - 2):
|
for i in 1..(ast.len - 2):
|
||||||
let option = callSite[i]
|
let option = ast[i]
|
||||||
if option.kind != nnkIdent:
|
if option.kind != nnkIdent:
|
||||||
parseError(option, "type specifier expected")
|
parseError(option, "type specifier expected")
|
||||||
if option.ident == toNimIdent("tool"):
|
if option.strVal == "tool":
|
||||||
isTool = true
|
isTool = true
|
||||||
else:
|
else:
|
||||||
parseError(option, "valid type specifier expected")
|
parseError(option, "valid type specifier expected")
|
||||||
result.isTool = isTool
|
result.isTool = isTool
|
||||||
|
|
||||||
if result.parentName.isNil: result.parentName = "Object"
|
if result.parentName.len == 0: result.parentName = "Object"
|
||||||
for statement in body:
|
for statement in body:
|
||||||
case statement.kind:
|
case statement.kind:
|
||||||
of nnkVarSection:
|
of nnkVarSection:
|
||||||
|
|
@ -210,7 +215,7 @@ proc parseType(definition, callSite: NimNode): ObjectDecl =
|
||||||
macro invokeVarArgs(procIdent, objIdent;
|
macro invokeVarArgs(procIdent, objIdent;
|
||||||
minArgs, maxArgs: static[int], numArgsIdent,
|
minArgs, maxArgs: static[int], numArgsIdent,
|
||||||
argSeqIdent; argTypes: seq[NimNode],
|
argSeqIdent; argTypes: seq[NimNode],
|
||||||
hasReturnValue, isStaticCall: static[bool]): typed =
|
hasReturnValue, isStaticCall: static[bool]): untyped =
|
||||||
## Produces statement in form:
|
## Produces statement in form:
|
||||||
##
|
##
|
||||||
## .. code-block:: nim
|
## .. code-block:: nim
|
||||||
|
|
@ -267,8 +272,12 @@ macro invokeVarArgs(procIdent, objIdent;
|
||||||
invocation = newNimNode(nnkCall).add(ident("procCall"), invocation)
|
invocation = newNimNode(nnkCall).add(ident("procCall"), invocation)
|
||||||
|
|
||||||
if hasReturnValue:
|
if hasReturnValue:
|
||||||
|
let resultVariant = genSym(nskLet, "ret")
|
||||||
|
branchBody.add(
|
||||||
|
newNimNode(nnkLetSection).add(
|
||||||
|
newIdentDefs(resultVariant, ident("Variant"), newCall("toVariant", invocation))))
|
||||||
let theCall = newNimNode(nnkBracketExpr).add(newNimNode(nnkDotExpr).add(
|
let theCall = newNimNode(nnkBracketExpr).add(newNimNode(nnkDotExpr).add(
|
||||||
newCall("toVariant", invocation), ident("godotVariant")))
|
resultVariant, ident("godotVariant")))
|
||||||
branchBody.add(getAst(initGodotVariantCall(ident("result"), theCall)))
|
branchBody.add(getAst(initGodotVariantCall(ident("result"), theCall)))
|
||||||
else:
|
else:
|
||||||
branchBody.add(invocation)
|
branchBody.add(invocation)
|
||||||
|
|
@ -283,7 +292,7 @@ macro invokeVarArgs(procIdent, objIdent;
|
||||||
" arguments, but got " & $numArgs)
|
" arguments, but got " & $numArgs)
|
||||||
|
|
||||||
result.add(newNimNode(nnkElse).add(getAst(
|
result.add(newNimNode(nnkElse).add(getAst(
|
||||||
printInvokeErr($procIdent.ident, minArgs, maxArgs, numArgsIdent))))
|
printInvokeErr(procIdent.strVal, minArgs, maxArgs, numArgsIdent))))
|
||||||
|
|
||||||
proc typeError(nimType: string, value: string, godotType: VariantType,
|
proc typeError(nimType: string, value: string, godotType: VariantType,
|
||||||
className: cstring, propertyName: cstring): string =
|
className: cstring, propertyName: cstring): string =
|
||||||
|
|
@ -391,10 +400,9 @@ template registerGodotField(classNameLit, classNameIdent, propNameLit,
|
||||||
getFunc: getFuncIdent
|
getFunc: getFuncIdent
|
||||||
)
|
)
|
||||||
mixin godotTypeInfo
|
mixin godotTypeInfo
|
||||||
static:
|
const typeInfo = when compiles(godotTypeInfo(propTypeIdent)):
|
||||||
var typeInfo: GodotTypeInfo
|
godotTypeInfo(propTypeIdent)
|
||||||
when compiles(godotTypeInfo(propTypeIdent)):
|
else: GodotTypeInfo()
|
||||||
typeInfo = godotTypeInfo(propTypeIdent)
|
|
||||||
const hintStr = when hintStrLit != "NIM":
|
const hintStr = when hintStrLit != "NIM":
|
||||||
hintStrLit
|
hintStrLit
|
||||||
else:
|
else:
|
||||||
|
|
@ -420,9 +428,6 @@ template registerGodotField(classNameLit, classNameIdent, propNameLit,
|
||||||
unsafeAddr attr, setFunc, getFunc)
|
unsafeAddr attr, setFunc, getFunc)
|
||||||
hintStrGodot.deinit()
|
hintStrGodot.deinit()
|
||||||
|
|
||||||
static:
|
|
||||||
import strutils, sets, sequtils
|
|
||||||
|
|
||||||
proc toGodotStyle(s: string): string {.compileTime.} =
|
proc toGodotStyle(s: string): string {.compileTime.} =
|
||||||
result = newStringOfCap(s.len + 10)
|
result = newStringOfCap(s.len + 10)
|
||||||
for c in s:
|
for c in s:
|
||||||
|
|
@ -443,7 +448,7 @@ proc genType(obj: ObjectDecl): NimNode {.compileTime.} =
|
||||||
let objTy = newNimNode(nnkObjectTy)
|
let objTy = newNimNode(nnkObjectTy)
|
||||||
typeDef.add(newNimNode(nnkRefTy).add(objTy))
|
typeDef.add(newNimNode(nnkRefTy).add(objTy))
|
||||||
objTy.add(newEmptyNode())
|
objTy.add(newEmptyNode())
|
||||||
if obj.parentName.isNil:
|
if obj.parentName.len == 0:
|
||||||
objTy.add(newEmptyNode())
|
objTy.add(newEmptyNode())
|
||||||
else:
|
else:
|
||||||
objTy.add(newNimNode(nnkOfInherit).add(ident(obj.parentName)))
|
objTy.add(newNimNode(nnkOfInherit).add(ident(obj.parentName)))
|
||||||
|
|
@ -453,7 +458,8 @@ proc genType(obj: ObjectDecl): NimNode {.compileTime.} =
|
||||||
let initBody = newStmtList()
|
let initBody = newStmtList()
|
||||||
for decl in obj.fields:
|
for decl in obj.fields:
|
||||||
if not decl.defaultValue.isNil and decl.defaultValue.kind != nnkEmpty:
|
if not decl.defaultValue.isNil and decl.defaultValue.kind != nnkEmpty:
|
||||||
initBody.add(newNimNode(nnkAsgn).add(decl.name, decl.defaultValue))
|
initBody.add(newNimNode(nnkAsgn).add(newDotExpr(ident("self"), decl.name),
|
||||||
|
decl.defaultValue))
|
||||||
let name = if not decl.isExported: decl.name
|
let name = if not decl.isExported: decl.name
|
||||||
else: postfix(decl.name, "*")
|
else: postfix(decl.name, "*")
|
||||||
recList.add(newIdentDefs(name, decl.typ))
|
recList.add(newIdentDefs(name, decl.typ))
|
||||||
|
|
@ -479,10 +485,11 @@ proc genType(obj: ObjectDecl): NimNode {.compileTime.} =
|
||||||
else:
|
else:
|
||||||
initMethod.body.insert(0, initBody)
|
initMethod.body.insert(0, initBody)
|
||||||
|
|
||||||
# {.this: self.} for convenience
|
when (NimMajor, NimMinor, NimPatch) < (0, 19, 0):
|
||||||
result.add(newNimNode(nnkPragma).add(newNimNode(nnkExprColonExpr).add(
|
# {.this: self.} for convenience
|
||||||
ident("this"), ident("self")
|
result.add(newNimNode(nnkPragma).add(newNimNode(nnkExprColonExpr).add(
|
||||||
)))
|
ident("this"), ident("self")
|
||||||
|
)))
|
||||||
|
|
||||||
# Nim proc defintions
|
# Nim proc defintions
|
||||||
var decls = newSeqOfCap[NimNode](obj.methods.len)
|
var decls = newSeqOfCap[NimNode](obj.methods.len)
|
||||||
|
|
@ -502,23 +509,25 @@ proc genType(obj: ObjectDecl): NimNode {.compileTime.} =
|
||||||
result.add(meth.nimNode)
|
result.add(meth.nimNode)
|
||||||
|
|
||||||
# Register Godot object
|
# Register Godot object
|
||||||
let parentName = if obj.parentName.isNil: newStrLitNode("Object")
|
let parentName = if obj.parentName.len == 0: newStrLitNode("Object")
|
||||||
else: newStrLitNode(obj.parentName)
|
else: newStrLitNode(obj.parentName)
|
||||||
let classNameLit = newCStringLit(obj.name)
|
let classNameLit = newStrLitNode(obj.name)
|
||||||
let classNameIdent = ident(obj.name)
|
let classNameIdent = ident(obj.name)
|
||||||
let isRef: bool = if obj.parentName.isNil: false
|
let isRef: bool = if obj.parentName.len == 0: false
|
||||||
else: obj.parentName in refClasses
|
else: obj.parentName in refClasses
|
||||||
|
# Wrapping bools with a newLit is required as a temporary workaround for
|
||||||
|
# https://github.com/nim-lang/Nim/issues/7375
|
||||||
result.add(getAst(
|
result.add(getAst(
|
||||||
registerGodotClass(classNameIdent, classNameLit, isRef, parentName,
|
registerGodotClass(classNameIdent, classNameLit, newLit(isRef), parentName,
|
||||||
genSym(nskProc, "createFunc"), obj.isTool)))
|
genSym(nskProc, "createFunc"), newLit(obj.isTool))))
|
||||||
|
|
||||||
# Register fields (properties)
|
# Register fields (properties)
|
||||||
for field in obj.fields:
|
for field in obj.fields:
|
||||||
if field.isNoGodot: continue
|
if field.isNoGodot: continue
|
||||||
let hintStr = if field.hintStr.isNil: "NIM"
|
let hintStr = if field.hintStr.isNone: "NIM"
|
||||||
else: field.hintStr
|
else: field.hintStr.get
|
||||||
let hint = if field.hint.isNil: "NIM"
|
let hint = if field.hint.isNone: "NIM"
|
||||||
else: field.hint
|
else: field.hint.get
|
||||||
let usage =
|
let usage =
|
||||||
if field.usage.isNil:
|
if field.usage.isNil:
|
||||||
newLit(ord(GodotPropertyUsage.Default) or
|
newLit(ord(GodotPropertyUsage.Default) or
|
||||||
|
|
@ -541,17 +550,23 @@ proc genType(obj: ObjectDecl): NimNode {.compileTime.} =
|
||||||
template registerGodotMethod(classNameLit, classNameIdent, methodNameIdent,
|
template registerGodotMethod(classNameLit, classNameIdent, methodNameIdent,
|
||||||
methodNameLit, minArgs, maxArgs,
|
methodNameLit, minArgs, maxArgs,
|
||||||
argTypes, methFuncIdent, hasReturnValue) =
|
argTypes, methFuncIdent, hasReturnValue) =
|
||||||
{.emit: """/*TYPESECTION*/
|
when (NimMajor, NimMinor, NimPatch) < (0, 19, 0):
|
||||||
|
{.emit: """/*TYPESECTION*/
|
||||||
N_NOINLINE(void, setStackBottom)(void* thestackbottom);
|
N_NOINLINE(void, setStackBottom)(void* thestackbottom);
|
||||||
""".}
|
""".}
|
||||||
|
|
||||||
proc methFuncIdent(obj: ptr GodotObject, methodData: pointer,
|
proc methFuncIdent(obj: ptr GodotObject, methodData: pointer,
|
||||||
userData: pointer, numArgs: cint,
|
userData: pointer, numArgs: cint,
|
||||||
args: var array[MAX_ARG_COUNT, ptr GodotVariant]):
|
args: var array[MAX_ARG_COUNT, ptr GodotVariant]):
|
||||||
GodotVariant {.noconv.} =
|
GodotVariant {.noconv.} =
|
||||||
var stackBottom {.volatile.}: pointer
|
var stackBottom {.volatile.}: pointer
|
||||||
{.emit: """
|
stackBottom = addr(stackBottom)
|
||||||
setStackBottom((void*)(&`stackBottom`));
|
when (NimMajor, NimMinor, NimPatch) < (0, 19, 0):
|
||||||
""".}
|
{.emit: """
|
||||||
|
setStackBottom((void*)(&`stackBottom`));
|
||||||
|
""".}
|
||||||
|
else:
|
||||||
|
nimGC_setStackBottom(stackBottom)
|
||||||
let self = cast[classNameIdent](userData)
|
let self = cast[classNameIdent](userData)
|
||||||
const isStaticCall = methodNameLit == cstring"_ready" or
|
const isStaticCall = methodNameLit == cstring"_ready" or
|
||||||
methodNameLit == cstring"_process" or
|
methodNameLit == cstring"_process" or
|
||||||
|
|
@ -594,8 +609,8 @@ N_NOINLINE(void, setStackBottom)(void* thestackbottom);
|
||||||
else: toGodotStyle(meth.name)
|
else: toGodotStyle(meth.name)
|
||||||
let hasReturnValueBool = not (meth.returnType.isNil or
|
let hasReturnValueBool = not (meth.returnType.isNil or
|
||||||
meth.returnType.kind == nnkEmpty or
|
meth.returnType.kind == nnkEmpty or
|
||||||
(meth.returnType.kind == nnkIdent and
|
(meth.returnType.kind == nnkIdent and
|
||||||
meth.returnType.ident == toNimIdent("void")))
|
meth.returnType.strVal == "void"))
|
||||||
let hasReturnValue = if hasReturnValueBool: ident("true")
|
let hasReturnValue = if hasReturnValueBool: ident("true")
|
||||||
else: ident("false")
|
else: ident("false")
|
||||||
result.add(getAst(
|
result.add(getAst(
|
||||||
|
|
@ -621,11 +636,7 @@ N_NOINLINE(void, setStackBottom)(void* thestackbottom);
|
||||||
GodotMethodAttributes(), refDec)
|
GodotMethodAttributes(), refDec)
|
||||||
result.add(getAst(registerRefIncDec(classNameLit)))
|
result.add(getAst(registerRefIncDec(classNameLit)))
|
||||||
|
|
||||||
{.push warning[Deprecated]: off.}
|
macro gdobj*(ast: varargs[untyped]): untyped =
|
||||||
# immediate macros are deprecated, but `untyped` doesn't make it immediate,
|
|
||||||
# as the warning and the documentation claim.
|
|
||||||
|
|
||||||
macro gdobj*(definition: untyped, body: typed): typed {.immediate.} =
|
|
||||||
## Generates Godot type. Self-documenting example:
|
## Generates Godot type. Self-documenting example:
|
||||||
##
|
##
|
||||||
## .. code-block:: nim
|
## .. code-block:: nim
|
||||||
|
|
@ -633,7 +644,7 @@ macro gdobj*(definition: untyped, body: typed): typed {.immediate.} =
|
||||||
##
|
##
|
||||||
## gdobj MyObj of Node:
|
## gdobj MyObj of Node:
|
||||||
## var myField: int
|
## var myField: int
|
||||||
## ## Not exported to Godot (i.e. editor will not see this field).
|
## ## Not exported to Godot (i.e. editor and scripts will not see this field).
|
||||||
##
|
##
|
||||||
## var myString* {.gdExport, hint: Length, hintStr: "20".}: string
|
## var myString* {.gdExport, hint: Length, hintStr: "20".}: string
|
||||||
## ## Exported to Godot as ``my_string``.
|
## ## Exported to Godot as ``my_string``.
|
||||||
|
|
@ -646,12 +657,12 @@ macro gdobj*(definition: untyped, body: typed): typed {.immediate.} =
|
||||||
## ## Exported methods are exported to Godot by default,
|
## ## Exported methods are exported to Godot by default,
|
||||||
## ## and their Godot names are prefixed with ``_``
|
## ## and their Godot names are prefixed with ``_``
|
||||||
## ## (in this case ``_ready``)
|
## ## (in this case ``_ready``)
|
||||||
## print("I am ready! myString is: " & myString)
|
## print("I am ready! myString is: " & self.myString)
|
||||||
##
|
##
|
||||||
## proc myProc*() {.gdExport.} =
|
## proc myProc*() {.gdExport.} =
|
||||||
## ## Exported to Godot as ``my_proc``
|
## ## Exported to Godot as ``my_proc``
|
||||||
## print("myProc is called! Incrementing myField.")
|
## print("myProc is called! Incrementing myField.")
|
||||||
## inc myField
|
## inc self.myField
|
||||||
##
|
##
|
||||||
## If parent type is omitted, the type is inherited from ``Object``.
|
## If parent type is omitted, the type is inherited from ``Object``.
|
||||||
##
|
##
|
||||||
|
|
@ -669,7 +680,5 @@ macro gdobj*(definition: untyped, body: typed): typed {.immediate.} =
|
||||||
## `gdnew <godotnim.html#gdnew>`_ or by using
|
## `gdnew <godotnim.html#gdnew>`_ or by using
|
||||||
## `load <godotapi/resource_loader.html#load,string,string,bool>`_ or any other way
|
## `load <godotapi/resource_loader.html#load,string,string,bool>`_ or any other way
|
||||||
## that you can find in `Godot API <index.html#modules-godot-api>`_.
|
## that you can find in `Godot API <index.html#modules-godot-api>`_.
|
||||||
let typeDef = parseType(definition, callsite())
|
let typeDef = parseType(ast)
|
||||||
result = genType(typeDef)
|
result = genType(typeDef)
|
||||||
|
|
||||||
{.push warning[Deprecated]: on.}
|
|
||||||
|
|
|
||||||
|
|
@ -1,14 +1,14 @@
|
||||||
# Copyright 2018 Xored Software, Inc.
|
# Copyright 2018 Xored Software, Inc.
|
||||||
|
|
||||||
import tables, typetraits, macros
|
import tables, typetraits, macros, unicode, strutils, sets, options
|
||||||
import gdnativeapi
|
import gdnativeapi
|
||||||
import core.godotcoretypes, core.godotbase
|
import core/godotcoretypes, core/godotbase
|
||||||
import core.vector2, core.rect2,
|
import core/vector2, core/rect2,
|
||||||
core.vector3, core.transform2d,
|
core/vector3, core/transform2d,
|
||||||
core.planes, core.quats, core.aabb,
|
core/planes, core/quats, core/aabb,
|
||||||
core.basis, core.transforms, core.colors,
|
core/basis, core/transforms, core/colors,
|
||||||
core.nodepaths, core.rids, core.dictionaries,
|
core/nodepaths, core/rids, core/dictionaries,
|
||||||
core.arrays, core.poolarrays, core.variants
|
core/arrays, core/poolarrays, core/variants
|
||||||
import godotinternal
|
import godotinternal
|
||||||
|
|
||||||
## This module defines ``NimGodotObject`` and ``toVariant``/``fromVariant``
|
## This module defines ``NimGodotObject`` and ``toVariant``/``fromVariant``
|
||||||
|
|
@ -31,7 +31,7 @@ type
|
||||||
## The base type all Godot types inherit from.
|
## The base type all Godot types inherit from.
|
||||||
## Manages lifecycle of the wrapped ``GodotObject``.
|
## Manages lifecycle of the wrapped ``GodotObject``.
|
||||||
godotObject: ptr GodotObject
|
godotObject: ptr GodotObject
|
||||||
linkedObject: NimGodotObject
|
linkedObjectPtr: pointer
|
||||||
## Wrapper around native object that is the container of the Nim "script"
|
## Wrapper around native object that is the container of the Nim "script"
|
||||||
## This is needed for `of` checks and `as` conversions to work as
|
## This is needed for `of` checks and `as` conversions to work as
|
||||||
## expected. For example, Nim type may inherit from ``Spatial``, but the
|
## expected. For example, Nim type may inherit from ``Spatial``, but the
|
||||||
|
|
@ -39,6 +39,8 @@ type
|
||||||
## ``Particles`` is valid, but Nim type system is not aware of that.
|
## ``Particles`` is valid, but Nim type system is not aware of that.
|
||||||
## This works in both directions - for linked native object this
|
## This works in both directions - for linked native object this
|
||||||
## reference points to Nim object.
|
## reference points to Nim object.
|
||||||
|
## This is stored as a raw pointer to avoid reference cycles and therefore
|
||||||
|
## improve GC performance.
|
||||||
isRef*: bool
|
isRef*: bool
|
||||||
isFinalized: bool
|
isFinalized: bool
|
||||||
isNative: bool
|
isNative: bool
|
||||||
|
|
@ -89,21 +91,71 @@ type
|
||||||
## values.
|
## values.
|
||||||
## See documentation of ``GodotPropertyHint`` for description of formats.
|
## See documentation of ``GodotPropertyHint`` for description of formats.
|
||||||
|
|
||||||
|
FNV1Hash = uint32
|
||||||
|
|
||||||
|
include "internal/backwardcompat.inc.nim"
|
||||||
|
|
||||||
proc isFinalized*(obj: NimGodotObject): bool {.inline.} =
|
proc isFinalized*(obj: NimGodotObject): bool {.inline.} =
|
||||||
obj.isFinalized
|
obj.isFinalized
|
||||||
|
|
||||||
var classRegistry {.threadvar.}: TableRef[cstring, ObjectInfo]
|
var classRegistry {.threadvar.}: TableRef[FNV1Hash, ObjectInfo]
|
||||||
var classRegistryStatic* {.compileTime.}: TableRef[cstring, ObjectInfo]
|
var classRegistryStatic* {.compileTime.}: TableRef[FNV1Hash, ObjectInfo]
|
||||||
## Compile-time variable used for implementation of several procedures
|
## Compile-time variable used for implementation of several procedures
|
||||||
## and macros
|
## and macros
|
||||||
static:
|
static:
|
||||||
classRegistryStatic = newTable[cstring, ObjectInfo]()
|
classRegistryStatic = newTable[FNV1Hash, ObjectInfo]()
|
||||||
|
|
||||||
static:
|
|
||||||
import sets, strutils
|
|
||||||
var nativeClasses {.compileTime.} = newSeq[string]()
|
var nativeClasses {.compileTime.} = newSeq[string]()
|
||||||
var refClasses* {.compileTime.} = newSeq[string]()
|
var refClasses* {.compileTime.} = newSeq[string]()
|
||||||
|
|
||||||
|
template initFNV1Hash(hash: var FNV1Hash) =
|
||||||
|
hash = 0x811c9dc5'u32
|
||||||
|
|
||||||
|
template appendFNV1Hash(hash: var FNV1Hash, val: uint8) =
|
||||||
|
block:
|
||||||
|
let u64hash = hash.uint64
|
||||||
|
hash = ((
|
||||||
|
u64hash +
|
||||||
|
(u64hash shl 1'u64) +
|
||||||
|
(u64hash shl 4'u64) +
|
||||||
|
(u64hash shl 7'u64) +
|
||||||
|
(u64hash shl 8'u64) +
|
||||||
|
(u64hash shl 24'u64)) and 0xFFFFFFFF'u32).uint32 xor val
|
||||||
|
|
||||||
|
{.push stackTrace:off.}
|
||||||
|
proc lsb(c: ptr cwchar_t): char {.noinit, inline.} =
|
||||||
|
{.emit: [result, " = (char)(", c[]," & 0xFF);"]}
|
||||||
|
{.pop.}
|
||||||
|
|
||||||
|
proc fnv1Hash(godotClassName: GodotString): FNV1Hash =
|
||||||
|
var charsCount = godotClassName.len
|
||||||
|
let charsPtr = godotClassName.dataPtr
|
||||||
|
if charsCount > 2 and
|
||||||
|
charsPtr.offset(charsCount - 2).lsb == 'S' and
|
||||||
|
charsPtr.offset(charsCount - 1).lsb == 'W':
|
||||||
|
charsCount -= 2
|
||||||
|
|
||||||
|
initFNV1Hash(result)
|
||||||
|
for i in 0..<charsCount:
|
||||||
|
let c = charsPtr.offset(i).lsb
|
||||||
|
appendFNV1Hash(result, c.uint8)
|
||||||
|
|
||||||
|
proc fnv1Hash(godotClassName: string): FNV1Hash {.compileTime.} =
|
||||||
|
var charsCount = godotClassName.len
|
||||||
|
if godotClassName.endsWith("SW"):
|
||||||
|
charsCount -= 2
|
||||||
|
|
||||||
|
initFNV1Hash(result)
|
||||||
|
var i = 0
|
||||||
|
for rune in runes(godotClassName):
|
||||||
|
if i >= charsCount:
|
||||||
|
break
|
||||||
|
let firstByte = uint8(rune.uint64 and 0xFF'u64)
|
||||||
|
appendFNV1Hash(result, firstByte)
|
||||||
|
# We don't really need to calculate hash of other bytes,
|
||||||
|
# since we only use hashes of ASCII strings
|
||||||
|
inc i
|
||||||
|
|
||||||
proc getClassName*(o: NimGodotObject): string =
|
proc getClassName*(o: NimGodotObject): string =
|
||||||
o.godotObject.getClassName()
|
o.godotObject.getClassName()
|
||||||
|
|
||||||
|
|
@ -135,12 +187,15 @@ proc deinit*(obj: NimGodotObject) =
|
||||||
obj.godotObject.deinit()
|
obj.godotObject.deinit()
|
||||||
obj.godotObject = nil
|
obj.godotObject = nil
|
||||||
|
|
||||||
|
proc linkedObject(obj: NimGodotObject): NimGodotObject {.inline.} =
|
||||||
|
cast[NimGodotObject](obj.linkedObjectPtr)
|
||||||
|
|
||||||
proc nimGodotObjectFinalizer*[T: NimGodotObject](obj: T) =
|
proc nimGodotObjectFinalizer*[T: NimGodotObject](obj: T) =
|
||||||
if obj.godotObject.isNil or obj.isNative: return
|
if obj.godotObject.isNil or obj.isNative: return
|
||||||
# important to set it before so that ``unreference`` is aware
|
# important to set it before so that ``unreference`` is aware
|
||||||
obj.isFinalized = true
|
obj.isFinalized = true
|
||||||
if obj.isRef and obj.godotObject.unreference() or
|
if (obj.isRef or not obj.linkedObject.isNil and obj.linkedObject.isRef) and
|
||||||
not obj.linkedObject.isNil:
|
obj.godotObject.unreference():
|
||||||
obj.deinit()
|
obj.deinit()
|
||||||
|
|
||||||
macro baseNativeType(T: typedesc): cstring =
|
macro baseNativeType(T: typedesc): cstring =
|
||||||
|
|
@ -154,7 +209,7 @@ macro baseNativeType(T: typedesc): cstring =
|
||||||
if typeName == "NimGodotObject":
|
if typeName == "NimGodotObject":
|
||||||
break
|
break
|
||||||
t = getType(t[1][1])
|
t = getType(t[1][1])
|
||||||
if baseT.isNil:
|
if baseT.len == 0:
|
||||||
result = newNilLit()
|
result = newNilLit()
|
||||||
else:
|
else:
|
||||||
let rStr = newNimNode(nnkRStrLit)
|
let rStr = newNimNode(nnkRStrLit)
|
||||||
|
|
@ -179,12 +234,12 @@ macro isResource(T: typedesc): bool =
|
||||||
result = if inherits(getType(T), "Resource"): ident("true")
|
result = if inherits(getType(T), "Resource"): ident("true")
|
||||||
else: ident("false")
|
else: ident("false")
|
||||||
|
|
||||||
template registerClass*(T: typedesc; godotClassName: cstring,
|
template registerClass*(T: typedesc; godotClassName: string or cstring,
|
||||||
native: bool) =
|
native: bool) =
|
||||||
## Registers the specified Godot type.
|
## Registers the specified Godot type.
|
||||||
## Used by ``gdobj`` macro and `godotapigen <godotapigen.html>`_.
|
## Used by ``gdobj`` macro and `godotapigen <godotapigen.html>`_.
|
||||||
if classRegistry.isNil:
|
if classRegistry.isNil:
|
||||||
classRegistry = newTable[cstring, ObjectInfo]()
|
classRegistry = newTable[FNV1Hash, ObjectInfo]()
|
||||||
let constructor = proc(): NimGodotObject =
|
let constructor = proc(): NimGodotObject =
|
||||||
var t: T
|
var t: T
|
||||||
new(t, nimGodotObjectFinalizer[T])
|
new(t, nimGodotObjectFinalizer[T])
|
||||||
|
|
@ -198,14 +253,22 @@ template registerClass*(T: typedesc; godotClassName: cstring,
|
||||||
isNative: native,
|
isNative: native,
|
||||||
isRef: isRef
|
isRef: isRef
|
||||||
)
|
)
|
||||||
classRegistry[godotClassName] = objInfo
|
classRegistry[fnv1Hash($godotClassName)] = objInfo
|
||||||
static:
|
static:
|
||||||
let objInfoStatic = ObjectInfo(
|
let objInfoStatic = ObjectInfo(
|
||||||
baseNativeClass: base,
|
baseNativeClass: base,
|
||||||
isNative: native,
|
isNative: native,
|
||||||
isRef: isRef,
|
isRef: isRef,
|
||||||
)
|
)
|
||||||
classRegistryStatic[godotClassName] = objInfoStatic
|
let nameHash = fnv1Hash($godotClassName)
|
||||||
|
if not classRegistryStatic.contains(nameHash):
|
||||||
|
classRegistryStatic[nameHash] = objInfoStatic
|
||||||
|
elif not endsWith($godotClassName, "SW"):
|
||||||
|
# For simplicity we assume that all class names must have
|
||||||
|
# different hashes
|
||||||
|
# If this exception is ever raised, I guess, we should
|
||||||
|
# implement a proper collision resolving
|
||||||
|
raise newException(Exception, "Hash collision " & $godotClassName)
|
||||||
when isRef:
|
when isRef:
|
||||||
static:
|
static:
|
||||||
refClasses.add(T.name)
|
refClasses.add(T.name)
|
||||||
|
|
@ -214,10 +277,10 @@ template registerClass*(T: typedesc; godotClassName: cstring,
|
||||||
nativeClasses.add(T.name)
|
nativeClasses.add(T.name)
|
||||||
|
|
||||||
proc newNimGodotObject[T: NimGodotObject](
|
proc newNimGodotObject[T: NimGodotObject](
|
||||||
godotObject: ptr GodotObject, godotClassName: cstring, noRef: bool): T =
|
godotObject: ptr GodotObject, godotClassName: GodotString, noRef: bool): T =
|
||||||
assert(not classRegistry.isNil)
|
assert(not classRegistry.isNil)
|
||||||
assert(not godotObject.isNil)
|
assert(not godotObject.isNil)
|
||||||
let objInfo = classRegistry.getOrDefault(godotClassName)
|
let objInfo = classRegistry.getOrDefault(fnv1Hash(godotClassName))
|
||||||
if objInfo.constructor.isNil:
|
if objInfo.constructor.isNil:
|
||||||
printError("Nim constructor not found for class " & $godotClassName)
|
printError("Nim constructor not found for class " & $godotClassName)
|
||||||
else:
|
else:
|
||||||
|
|
@ -240,9 +303,11 @@ proc asNimGodotObject*[T: NimGodotObject](
|
||||||
# Could be data from other bindings
|
# Could be data from other bindings
|
||||||
result = nil
|
result = nil
|
||||||
if result.isNil:
|
if result.isNil:
|
||||||
|
var classNameStr = godotObject.getClassNameRaw()
|
||||||
result = newNimGodotObject[T](
|
result = newNimGodotObject[T](
|
||||||
godotObject, cstring(godotObject.getClassName()),
|
godotObject, classNameStr,
|
||||||
forceNativeObject or noRef)
|
forceNativeObject or noRef)
|
||||||
|
deinit(classNameStr)
|
||||||
|
|
||||||
proc newVariant*(obj: NimGodotObject): Variant {.inline.} =
|
proc newVariant*(obj: NimGodotObject): Variant {.inline.} =
|
||||||
newVariant(obj.godotObject)
|
newVariant(obj.godotObject)
|
||||||
|
|
@ -267,45 +332,35 @@ proc `as`*[T: NimGodotObject](obj: NimGodotObject, t: typedesc[T]): T =
|
||||||
## This can be used either in dot notation (``node.as(Button)``) or
|
## This can be used either in dot notation (``node.as(Button)``) or
|
||||||
## infix notation (``node as Button``).
|
## infix notation (``node as Button``).
|
||||||
if obj.isNil: return nil
|
if obj.isNil: return nil
|
||||||
if obj of T:
|
if system.`of`(obj, T):
|
||||||
result = T(obj)
|
result = T(obj)
|
||||||
elif not obj.linkedObject.isNil and obj.linkedObject of T:
|
elif not obj.linkedObject.isNil and system.`of`(obj.linkedObject, T):
|
||||||
result = T(obj.linkedObject)
|
result = T(obj.linkedObject)
|
||||||
else:
|
else:
|
||||||
when not defined(release):
|
|
||||||
printError("Failed to cast object to " &
|
|
||||||
T.name & "\n" & getStackTrace())
|
|
||||||
result = nil
|
result = nil
|
||||||
|
|
||||||
proc `of`*[T: NimGodotObject](obj: NimGodotObject,
|
proc `of`*[T1, T2: NimGodotObject](obj: T1, t: typedesc[T2]): bool {.inline.} =
|
||||||
t: typedesc[T]): bool {.inline.} =
|
|
||||||
## Godot-specific inheritance check.
|
## Godot-specific inheritance check.
|
||||||
not obj.isNil and (system.`of`(obj, T) or system.`of`(obj.linkedObject, T))
|
not obj.isNil and (system.`of`(obj, T2) or system.`of`(obj.linkedObject, T2))
|
||||||
|
|
||||||
proc newRStrLit(s: string): NimNode {.compileTime.} =
|
proc newRStrLit(s: string): NimNode {.compileTime.} =
|
||||||
result = newNimNode(nnkRStrLit)
|
result = newNimNode(nnkRStrLit)
|
||||||
result.strVal = s
|
result.strVal = s
|
||||||
|
|
||||||
static:
|
macro toGodotName(T: typedesc): untyped =
|
||||||
import strutils
|
|
||||||
|
|
||||||
macro toGodotName(T: typedesc): string =
|
|
||||||
var godotName: string
|
|
||||||
if T is GodotString or T is string:
|
if T is GodotString or T is string:
|
||||||
godotName = "String"
|
newStrLitNode"String"
|
||||||
elif T is SomeFloat:
|
elif T is SomeFloat:
|
||||||
godotName = "float"
|
newStrLitNode"float"
|
||||||
elif T is SomeUnsignedInt or T is SomeSignedInt:
|
elif T is SomeUnsignedInt or T is SomeSignedInt:
|
||||||
godotName = "int"
|
newStrLitNode"int"
|
||||||
if godotName.isNil:
|
else:
|
||||||
let nameStr: string = (($T.getType()[1][1].symbol).split(':')[0])
|
let nameStr = ((T.getType()[1][1].strVal).split(':')[0])
|
||||||
godotName = case nameStr:
|
case nameStr:
|
||||||
of "File", "Directory", "Thread", "Mutex", "Semaphore":
|
of "File", "Directory", "Thread", "Mutex", "Semaphore":
|
||||||
"_" & nameStr
|
newStrLitNode("_" & nameStr)
|
||||||
else:
|
else:
|
||||||
nameStr
|
newStrLitNode(nameStr)
|
||||||
|
|
||||||
result = newLit(godotName)
|
|
||||||
|
|
||||||
macro asCString(s: static[string]): cstring =
|
macro asCString(s: static[string]): cstring =
|
||||||
result = newNimNode(nnkCallStrLit).add(
|
result = newNimNode(nnkCallStrLit).add(
|
||||||
|
|
@ -364,17 +419,18 @@ proc newOwnObj[T: NimGodotObject](name: cstring): T =
|
||||||
|
|
||||||
proc gdnew*[T: NimGodotObject](): T =
|
proc gdnew*[T: NimGodotObject](): T =
|
||||||
## Instantiates new object of type ``T``.
|
## Instantiates new object of type ``T``.
|
||||||
const godotName = asCString(toGodotName(T))
|
const godotName = toGodotName(T)
|
||||||
const objInfo = classRegistryStatic[godotName]
|
const cGodotName = asCString(godotName)
|
||||||
|
const objInfo = classRegistryStatic[fnv1Hash(godotName)]
|
||||||
when objInfo.isNative:
|
when objInfo.isNative:
|
||||||
let godotObject = getClassConstructor(godotName)()
|
let godotObject = getClassConstructor(cGodotName)()
|
||||||
new(result, nimGodotObjectFinalizer[T])
|
new(result, nimGodotObjectFinalizer[T])
|
||||||
result.godotObject = godotObject
|
result.godotObject = godotObject
|
||||||
when objInfo.isRef:
|
when objInfo.isRef:
|
||||||
godotObject.initRef()
|
godotObject.initRef()
|
||||||
result.isRef = true
|
result.isRef = true
|
||||||
else:
|
else:
|
||||||
result = newOwnObj[T](godotName)
|
result = newOwnObj[T](cGodotName)
|
||||||
|
|
||||||
proc newCallError*(err: VariantCallError): ref CallError =
|
proc newCallError*(err: VariantCallError): ref CallError =
|
||||||
## Instantiates ``CallError`` from Godot ``err``.
|
## Instantiates ``CallError`` from Godot ``err``.
|
||||||
|
|
@ -414,14 +470,17 @@ proc setGodotObject*(nimObj: NimGodotObject, obj: ptr GodotObject) {.inline.} =
|
||||||
proc setNativeObject*(nimObj: NimGodotObject,
|
proc setNativeObject*(nimObj: NimGodotObject,
|
||||||
nativeObj: NimGodotObject) {.inline.} =
|
nativeObj: NimGodotObject) {.inline.} =
|
||||||
## Used from Godot constructor produced by ``gdobj`` macro. Do not call.
|
## Used from Godot constructor produced by ``gdobj`` macro. Do not call.
|
||||||
nimObj.linkedObject = nativeObj
|
GC_ref(nativeObj)
|
||||||
nativeObj.linkedObject = nimObj
|
nimObj.linkedObjectPtr = cast[pointer](nativeObj)
|
||||||
|
nativeObj.linkedObjectPtr = cast[pointer](nimObj)
|
||||||
nativeObj.isNative = true
|
nativeObj.isNative = true
|
||||||
|
|
||||||
proc removeGodotObject*(nimObj: NimGodotObject) {.inline.} =
|
proc removeGodotObject*(nimObj: NimGodotObject) {.inline.} =
|
||||||
## Used from Godot destructor produced by ``gdobj`` macro. Do not call.
|
## Used from Godot destructor produced by ``gdobj`` macro. Do not call.
|
||||||
|
GC_unref(nimObj.linkedObject)
|
||||||
nimObj.godotObject = nil
|
nimObj.godotObject = nil
|
||||||
nimObj.linkedObject.godotObject = nil
|
nimObj.linkedObject.godotObject = nil
|
||||||
|
nimObj.linkedObjectPtr = nil
|
||||||
|
|
||||||
proc `==`*(self, other: NimGodotObject): bool {.inline.} =
|
proc `==`*(self, other: NimGodotObject): bool {.inline.} =
|
||||||
## Compares objects by referential equality.
|
## Compares objects by referential equality.
|
||||||
|
|
@ -553,7 +612,11 @@ proc fromVariant*[T: SomeSignedInt or SomeUnsignedInt](
|
||||||
else: uint64)
|
else: uint64)
|
||||||
intVal = when T is SomeSignedInt: val.asInt()
|
intVal = when T is SomeSignedInt: val.asInt()
|
||||||
else: val.asUint()
|
else: val.asUint()
|
||||||
if intVal > high(T) or intVal < low(T):
|
const highT = when T is SomeSignedInt: high(T).int64
|
||||||
|
else: high(T).uint64
|
||||||
|
const lowT = when T is SomeSignedInt: low(T).int64
|
||||||
|
else: low(T).uint64
|
||||||
|
if intVal > highT or intVal < lowT:
|
||||||
result = ConversionResult.RangeError
|
result = ConversionResult.RangeError
|
||||||
else:
|
else:
|
||||||
self = T(intVal)
|
self = T(intVal)
|
||||||
|
|
@ -657,7 +720,10 @@ proc fromVariant*(s: var string, val: Variant): ConversionResult =
|
||||||
if val.getType() == VariantType.String:
|
if val.getType() == VariantType.String:
|
||||||
s = val.asString()
|
s = val.asString()
|
||||||
elif val.getType() == VariantType.Nil:
|
elif val.getType() == VariantType.Nil:
|
||||||
s = nil
|
when (NimMajor, NimMinor, NimPatch) < (0, 19, 0):
|
||||||
|
s = nil
|
||||||
|
else:
|
||||||
|
s = ""
|
||||||
else:
|
else:
|
||||||
result = ConversionResult.TypeError
|
result = ConversionResult.TypeError
|
||||||
|
|
||||||
|
|
@ -731,10 +797,31 @@ proc fromVariant*[T: array](s: var T, val: Variant): ConversionResult =
|
||||||
else:
|
else:
|
||||||
result = ConversionResult.TypeError
|
result = ConversionResult.TypeError
|
||||||
|
|
||||||
proc godotTypeInfo*(T: typedesc[Table|TableRef]): GodotTypeInfo {.inline.} =
|
proc godotTypeInfo*[T](OptT: typedesc[Option[T]]): GodotTypeInfo =
|
||||||
|
when compiles(godotTypeInfo(T)):
|
||||||
|
result.variantType = godotTypeInfo(T)
|
||||||
|
else:
|
||||||
|
result.variantType = VariantType.Nil
|
||||||
|
|
||||||
|
proc toVariant*[T](option: Option[T]): Variant =
|
||||||
|
if option.isSome():
|
||||||
|
result = toVariant(option.unsafeGet())
|
||||||
|
else:
|
||||||
|
result = newVariant()
|
||||||
|
|
||||||
|
proc fromVariant*[T](option: var Option[T], val: Variant): ConversionResult =
|
||||||
|
if val.getType() == VariantType.Nil:
|
||||||
|
option = none(T)
|
||||||
|
else:
|
||||||
|
var v: T
|
||||||
|
result = fromVariant(v, val)
|
||||||
|
if result == ConversionResult.OK:
|
||||||
|
option = some(result)
|
||||||
|
|
||||||
|
proc godotTypeInfo*(T: typedesc[Table|TableRef|OrderedTable|OrderedTableRef]): GodotTypeInfo {.inline.} =
|
||||||
result.variantType = VariantType.Dictionary
|
result.variantType = VariantType.Dictionary
|
||||||
|
|
||||||
proc toVariant*[T: Table or TableRef](t: T): Variant =
|
proc toVariant*[T: Table or TableRef or OrderedTable or OrderedTableRef](t: T): Variant =
|
||||||
when t is ref:
|
when t is ref:
|
||||||
if t.isNil:
|
if t.isNil:
|
||||||
return newVariant()
|
return newVariant()
|
||||||
|
|
@ -744,7 +831,7 @@ proc toVariant*[T: Table or TableRef](t: T): Variant =
|
||||||
dict[toVariant(k)] = toVariant(v)
|
dict[toVariant(k)] = toVariant(v)
|
||||||
result = newVariant(dict)
|
result = newVariant(dict)
|
||||||
|
|
||||||
proc fromVariant*[T: Table or TableRef](t: var T,
|
proc fromVariant*[T: Table or TableRef or OrderedTable or OrderedTableRef](t: var T,
|
||||||
val: Variant): ConversionResult =
|
val: Variant): ConversionResult =
|
||||||
if val.getType() == VariantType.Nil:
|
if val.getType() == VariantType.Nil:
|
||||||
when t is ref:
|
when t is ref:
|
||||||
|
|
@ -754,8 +841,12 @@ proc fromVariant*[T: Table or TableRef](t: var T,
|
||||||
mixin fromVariant
|
mixin fromVariant
|
||||||
when t is Table:
|
when t is Table:
|
||||||
t = initTable[type(t.keys()), type(t.values())]()
|
t = initTable[type(t.keys()), type(t.values())]()
|
||||||
else:
|
elif t is TableRef:
|
||||||
t = newTable[type(t.keys()), type(t.values())]()
|
t = newTable[type(t.keys()), type(t.values())]()
|
||||||
|
elif t is OrderedTable:
|
||||||
|
t = initOrderedTable[type(t.keys()), type(t.values())]()
|
||||||
|
else:
|
||||||
|
t = newOrderedTable[type(t.keys()), type(t.values())]()
|
||||||
for k, v in dict:
|
for k, v in dict:
|
||||||
var nimKey: type(t.keys())
|
var nimKey: type(t.keys())
|
||||||
var nimVal: type(t.values())
|
var nimVal: type(t.values())
|
||||||
|
|
@ -773,10 +864,11 @@ proc fromVariant*[T: Table or TableRef](t: var T,
|
||||||
else:
|
else:
|
||||||
result = ConversionResult.TypeError
|
result = ConversionResult.TypeError
|
||||||
|
|
||||||
{.emit: """/*TYPESECTION*/
|
when (NimMajor, NimMinor, NimPatch) < (0, 19, 0):
|
||||||
void NimMain(void);
|
{.emit: """/*TYPESECTION*/
|
||||||
N_NOINLINE(void, setStackBottom)(void* thestackbottom);
|
N_LIB_EXPORT N_CDECL(void, NimMain)(void);
|
||||||
""".}
|
N_NOINLINE(void, setStackBottom)(void* thestackbottom);
|
||||||
|
""".}
|
||||||
|
|
||||||
var nativeLibHandle: pointer
|
var nativeLibHandle: pointer
|
||||||
proc getNativeLibHandle*(): pointer =
|
proc getNativeLibHandle*(): pointer =
|
||||||
|
|
@ -789,10 +881,16 @@ proc godot_nativescript_init(handle: pointer) {.
|
||||||
nativeLibHandle = handle
|
nativeLibHandle = handle
|
||||||
|
|
||||||
var stackBottom {.volatile.}: pointer
|
var stackBottom {.volatile.}: pointer
|
||||||
|
stackBottom = addr(stackBottom)
|
||||||
{.emit: """
|
{.emit: """
|
||||||
NimMain();
|
NimMain();
|
||||||
setStackBottom((void*)(&`stackBottom`));
|
|
||||||
""".}
|
""".}
|
||||||
|
when (NimMajor, NimMinor, NimPatch) < (0, 19, 0):
|
||||||
|
{.emit: """
|
||||||
|
setStackBottom((void*)(&`stackBottom`));
|
||||||
|
""".}
|
||||||
|
else:
|
||||||
|
nimGC_setStackBottom(stackBottom)
|
||||||
GC_fullCollect()
|
GC_fullCollect()
|
||||||
GC_disable()
|
GC_disable()
|
||||||
|
|
||||||
|
|
@ -803,7 +901,8 @@ proc godot_gdnative_init(options: ptr GDNativeInitOptions) {.
|
||||||
|
|
||||||
proc godot_gdnative_terminate(options: ptr GDNativeTerminateOptions) {.
|
proc godot_gdnative_terminate(options: ptr GDNativeTerminateOptions) {.
|
||||||
cdecl, exportc, dynlib.} =
|
cdecl, exportc, dynlib.} =
|
||||||
deallocHeap(runFinalizers = not options[].inEditor, allowGcAfterwards = false)
|
if not options[].inEditor or not compileOption("threads"):
|
||||||
|
deallocHeap(runFinalizers = not options[].inEditor, allowGcAfterwards = false)
|
||||||
|
|
||||||
const nimGcStepLengthUs {.intdefine.} = 2000
|
const nimGcStepLengthUs {.intdefine.} = 2000
|
||||||
|
|
||||||
|
|
@ -827,9 +926,13 @@ proc registerFrameCallback*(cb: proc () {.closure.}) =
|
||||||
|
|
||||||
proc godot_nativescript_frame() {.cdecl, exportc, dynlib.} =
|
proc godot_nativescript_frame() {.cdecl, exportc, dynlib.} =
|
||||||
var stackBottom {.volatile.}: pointer
|
var stackBottom {.volatile.}: pointer
|
||||||
{.emit: """
|
stackBottom = addr(stackBottom)
|
||||||
setStackBottom((void*)(&`stackBottom`));
|
when (NimMajor, NimMinor, NimPatch) < (0, 19, 0):
|
||||||
""".}
|
{.emit: """
|
||||||
|
setStackBottom((void*)(&`stackBottom`));
|
||||||
|
""".}
|
||||||
|
else:
|
||||||
|
nimGC_setStackBottom(stackBottom)
|
||||||
for cb in idleCallbacks:
|
for cb in idleCallbacks:
|
||||||
cb()
|
cb()
|
||||||
GC_step(nimGcStepLengthUs, true, 0)
|
GC_step(nimGcStepLengthUs, true, 0)
|
||||||
|
|
|
||||||
|
|
@ -1 +1,2 @@
|
||||||
--path:"$projectdir/../"
|
--path:"$projectdir/../"
|
||||||
|
-d:useRealtimeGc
|
||||||
Loading…
Add table
Add a link
Reference in a new issue