diff --git a/README.md b/README.md index 891a920..62e28d3 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ -# Nim bindings for Godot Engine [![Build Status](https://travis-ci.org/pragmagic/godot-nim.svg?branch=master)](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/ @@ -13,4 +13,4 @@ Documentation: https://pragmagic.github.io/godot-nim/ This project is licensed under the MIT license. Read [LICENSE](LICENSE) file for details. -Copyright (c) 2018 Xored Software, Inc. \ No newline at end of file +Copyright (c) 2018 Xored Software, Inc. diff --git a/docs/docbuild.nim b/docs/docbuild.nim index bb3e21c..477c45b 100644 --- a/docs/docbuild.nim +++ b/docs/docbuild.nim @@ -71,7 +71,7 @@ proc fixupHrefs(file: string) = proc getGitHash(): string = result = execProcess("git rev-parse HEAD") - if not result.isNil and result.len > 0: + if result.len > 0: result = result.replace("\L", "").replace("\r", "") proc buildDocs*(outDir, godotNimDir, godotBin: string) = @@ -104,14 +104,15 @@ proc buildDocs*(outDir, godotNimDir, godotBin: string) = createDir(godotApiFolder) genApiFiles(godotApiFolder, godotBinAbs) 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() var gitHash: string withDir(godotBinAbs.parentDir()): gitHash = getGitHash() - if gitHash.isNil or gitHash.len == 0: + if gitHash.len == 0: raise newException(Exception, "Godot executable is not under Git repository") diff --git a/godot.nimble b/godot.nimble index b8bfed5..d7ca12b 100644 --- a/godot.nimble +++ b/godot.nimble @@ -1,4 +1,4 @@ -version = "0.7.11" +version = "0.8.2" author = "Xored Software, Inc." description = "Godot Engine bindings" license = "MIT" diff --git a/godot/core/aabb.nim b/godot/core/aabb.nim index 88bf66a..2d816da 100644 --- a/godot/core/aabb.nim +++ b/godot/core/aabb.nim @@ -1,6 +1,9 @@ # Copyright (c) 2018 Xored Software, Inc. -import internal.godotinternaltypes, internal.godotstrings +import hashes + +import vector3 +import internal/godotinternaltypes, internal/godotstrings import godotcoretypes, gdnativeapi proc initAABB*(pos, size: Vector3): AABB {.inline.} = @@ -9,6 +12,9 @@ proc initAABB*(pos, size: Vector3): AABB {.inline.} = proc `$`*(self: AABB): string {.inline.} = $getGDNativeAPI().aabbAsString(self) +proc hash*(self: AABB): Hash {.inline.} = + !$(self.position.hash() !& self.size.hash()) + proc area*(self: AABB): float32 {.inline.} = getGDNativeAPI().aabbGetArea(self) @@ -25,10 +31,10 @@ proc encloses*(self, other: AABB): bool {.inline.} = getGDNativeAPI().aabbEncloses(self, other) proc merge*(self, other: AABB): AABB {.inline.} = - getGDNativeAPI().aabbMerge(self, other) + getGDNativeAPI().aabbMerge(self, other).toAABB() proc intersection*(self, other: AABB): AABB {.inline.} = - getGDNativeAPI().aabbIntersection(self, other) + getGDNativeAPI().aabbIntersection(self, other).toAABB() proc intersectsPlane*(self: AABB; plane: Plane): bool {.inline.} = getGDNativeAPI().aabbIntersectsPlane(self, plane) @@ -40,10 +46,10 @@ proc contains*(self: AABB; point: Vector3): bool {.inline.} = getGDNativeAPI().aabbHasPoint(self, point) proc getSupport*(self: AABB; dir: Vector3): Vector3 {.inline.} = - getGDNativeAPI().aabbGetSupport(self, dir) + getGDNativeAPI().aabbGetSupport(self, dir).toVector3() proc getLongestAxis*(self: AABB): Vector3 {.inline.} = - getGDNativeAPI().aabbGetLongestAxis(self) + getGDNativeAPI().aabbGetLongestAxis(self).toVector3() proc getLongestAxisIndex*(self: AABB): cint {.inline.} = getGDNativeAPI().aabbGetLongestAxisIndex(self) @@ -52,7 +58,7 @@ proc getLongestAxisSize*(self: AABB): float32 {.inline.} = getGDNativeAPI().aabbGetLongestAxisSize(self) proc getShortestAxis*(self: AABB): Vector3 {.inline.} = - getGDNativeAPI().aabbGetShortestAxis(self) + getGDNativeAPI().aabbGetShortestAxis(self).toVector3() proc getShortestAxisIndex*(self: AABB): cint {.inline.} = getGDNativeAPI().aabbGetShortestAxisIndex(self) @@ -61,13 +67,13 @@ proc getShortestAxisSize*(self: AABB): float32 {.inline.} = getGDNativeAPI().aabbGetShortestAxisSize(self) 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.} = - getGDNativeAPI().aabbGrow(self, by) + getGDNativeAPI().aabbGrow(self, by).toAABB() proc getEndpoint*(self: AABB; idx: cint): Vector3 {.inline.} = - getGDNativeAPI().aabbGetEndpoint(self, idx) + getGDNativeAPI().aabbGetEndpoint(self, idx).toVector3() proc `==`*(a, b: AABB): bool {.inline.} = getGDNativeAPI().aabbOperatorEqual(a, b) diff --git a/godot/core/arrays.nim b/godot/core/arrays.nim index afe8131..fcbafb2 100644 --- a/godot/core/arrays.nim +++ b/godot/core/arrays.nim @@ -1,7 +1,7 @@ # Copyright 2018 Xored Software, Inc. import hashes -import internal.godotinternaltypes, internal.godotarrays +import internal/godotinternaltypes, internal/godotarrays type Array* = ref object diff --git a/godot/core/basis.nim b/godot/core/basis.nim index 538ca60..704f666 100644 --- a/godot/core/basis.nim +++ b/godot/core/basis.nim @@ -1,6 +1,7 @@ # Copyright (c) 2018 Xored Software, Inc. -import math +import math, hashes + import godotbase, vector3, quats import godotcoretypes @@ -201,6 +202,9 @@ proc `$`*(self: Basis): string {.inline.} = result.add(", ") 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 = self.elements[row1][col1] * self.elements[row2][col2] - self.elements[row1][col2] * self.elements[row2][col1] diff --git a/godot/core/colors.nim b/godot/core/colors.nim index 46fcaf3..8e01b7a 100644 --- a/godot/core/colors.nim +++ b/godot/core/colors.nim @@ -1,5 +1,7 @@ # Copyright (c) 2018 Xored Software, Inc. +import hashes + import godotcoretypes, gdnativeapi 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($self.a) +proc hash*(self: Color): Hash {.inline.} = + !$(self.r.hash() !& self.g.hash() !& self.b.hash() !& self.a.hash()) + proc toHex(val: float32, target: var string, targetIdx: int) = let val = clamp(int(val * 255), 0, 255) let nums = [(val and 0xF0) shr 4, val and 0xF] @@ -59,16 +64,16 @@ proc gray*(self: Color): float32 {.inline.} = getGDNativeAPI().colorGray(self) proc inverted*(self: Color): Color {.inline.} = - getGDNativeAPI().colorInverted(self) + getGDNativeAPI().colorInverted(self).toColor() proc contrasted*(self: Color): Color {.inline.} = - getGDNativeAPI().colorContrasted(self) + getGDNativeAPI().colorContrasted(self).toColor() 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.} = - getGDNativeAPI().colorBlend(self, over) + getGDNativeAPI().colorBlend(self, over).toColor() proc `==`*(a, b: Color): bool {.inline.} = a.r == b.r and a.g == b.g and a.b == b.b and a.a == b.a diff --git a/godot/core/dictionaries.nim b/godot/core/dictionaries.nim index 85970e5..3aea17a 100644 --- a/godot/core/dictionaries.nim +++ b/godot/core/dictionaries.nim @@ -1,8 +1,8 @@ # Copyright 2018 Xored Software, Inc. import hashes -import internal.godotinternaltypes, internal.godotdictionaries, - internal.godotvariants, internal.godotstrings +import internal/godotinternaltypes, internal/godotdictionaries, + internal/godotvariants, internal/godotstrings type Dictionary* = ref object @@ -33,6 +33,9 @@ proc isEmpty*(self: Dictionary): bool {.inline.} = proc clear*(self: Dictionary) {.inline.} = self.godotDictionary.clear() +proc hash*(self: Dictionary): Hash {.inline.} = + hash(self.godotDictionary.godotHash()) + import variants, arrays proc newVariant*(dict: Dictionary): Variant {.inline.} = @@ -40,7 +43,7 @@ proc newVariant*(dict: Dictionary): Variant {.inline.} = initGodotVariant(result.godotVariant[], dict.godotDictionary) proc asDictionary*(self: Variant): Dictionary {.inline.} = - newDictionary(self.godotVariant[].asGodotDictionary) + newDictionary(self.godotVariant[].asGodotDictionary()) proc contains*(self: Dictionary; key: Variant): bool {.inline.}= self.godotDictionary.contains(key.godotVariant[]) @@ -51,9 +54,6 @@ proc contains*(self: Dictionary; keys: Array): bool {.inline.} = proc del*(self: Dictionary; key: Variant) {.inline.} = self.godotDictionary.del(key.godotVariant[]) -proc hash*(self: Dictionary): Hash {.inline.} = - hash(self.godotDictionary.godotHash()) - proc keys*(self: Dictionary): Array {.inline.} = newArray(self.godotDictionary.keys()) diff --git a/godot/core/godotbase.nim b/godot/core/godotbase.nim index d76f544..7b5b804 100644 --- a/godot/core/godotbase.nim +++ b/godot/core/godotbase.nim @@ -30,14 +30,17 @@ proc stepify*(value, step: float32): float32 {.inline, noinit.} = else: value -proc min*(x, y: float32): float32 {.inline, noinit.} = - if x <= y: x else: y +when (NimMajor, NimMinor, NimPatch) < (0, 20, 4): + # Newer Nim has these procs in system module -proc abs*(x: float32): float32 {.inline, noinit.} = - if x < 0.0: -x else: x + proc min*(x, y: float32): float32 {.inline, noinit.} = + if x <= y: x else: y -proc max*(x, y: float32): float32 {.inline, noinit.} = - if y <= x: x else: y + proc abs*(x: float32): float32 {.inline, noinit.} = + if x < 0.0: -x else: x + + proc max*(x, y: float32): float32 {.inline, noinit.} = + if y <= x: x else: y {.pop.} # stackTrace: off diff --git a/godot/core/nodepaths.nim b/godot/core/nodepaths.nim index 428e261..bf690d7 100644 --- a/godot/core/nodepaths.nim +++ b/godot/core/nodepaths.nim @@ -1,7 +1,9 @@ # Copyright 2018 Xored Software, Inc. -import internal.godotinternaltypes, internal.godotnodepaths, - internal.godotstrings +import hashes + +import internal/godotinternaltypes, internal/godotnodepaths, + internal/godotstrings type NodePath* = ref object @@ -32,6 +34,9 @@ proc `$`*(self: NodePath): string {.inline.} = result = $s s.deinit() +proc hash*(self: NodePath): Hash {.inline.} = + ($self).hash() + proc isAbsolute*(self: NodePath): bool {.inline.} = self.path.isAbsolute() diff --git a/godot/core/planes.nim b/godot/core/planes.nim index 66de34e..2d15c79 100644 --- a/godot/core/planes.nim +++ b/godot/core/planes.nim @@ -1,8 +1,10 @@ # Copyright (c) 2018 Xored Software, Inc. +import hashes + import vector3 -import internal.godotinternaltypes, internal.godotstrings +import internal/godotinternaltypes, internal/godotstrings import godotcoretypes, gdnativeapi 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.} = $getGDNativeAPI().planeAsString(self) +proc hash*(self: Plane): Hash {.inline, noinit.} = + !$(self.normal.hash() !& self.d.hash()) + proc normalized*(self: Plane): Plane {.inline.} = - getGDNativeAPI().planeNormalized(self) + getGDNativeAPI().planeNormalized(self).toPlane() proc center*(self: Plane): Vector3 {.inline.} = - getGDNativeAPI().planeCenter(self) + getGDNativeAPI().planeCenter(self).toVector3() proc getAnyPoint*(self: Plane): Vector3 {.inline.} = - getGDNativeAPI().planeGetAnyPoint(self) + getGDNativeAPI().planeGetAnyPoint(self).toVector3() proc isPointOver*(self: Plane; point: Vector3): bool {.inline.} = getGDNativeAPI().planeIsPointOver(self, point) @@ -40,7 +45,7 @@ proc contains*(self: Plane; point: Vector3; getGDNativeAPI().planeHasPoint(self, point, epsilon) proc project*(self: Plane; point: Vector3): Vector3 {.inline.} = - getGDNativeAPI().planeProject(self, point) + getGDNativeAPI().planeProject(self, point).toVector3() proc intersect3*(self: Plane; dest: var Vector3; b, c: Plane): bool {.inline.} = @@ -55,7 +60,7 @@ proc intersectsSegment*(self: Plane; dest: var Vector3; getGDNativeAPI().planeIntersectsSegment(self, dest, segmentBegin, segmentEnd) proc `-`*(self: Plane): Plane {.inline.} = - getGDNativeAPI().planeOperatorNeg(self) + getGDNativeAPI().planeOperatorNeg(self).toPlane() proc `==`*(a, b: Plane): bool {.inline.} = getGDNativeAPI().planeOperatorEqual(a, b) diff --git a/godot/core/poolarrays.nim b/godot/core/poolarrays.nim index 8206662..29fda96 100644 --- a/godot/core/poolarrays.nim +++ b/godot/core/poolarrays.nim @@ -1,8 +1,11 @@ # Copyright 2018 Xored Software, Inc. +import hashes + import godotcoretypes -import internal.godotinternaltypes, internal.godotpoolarrays, - internal.godotstrings +import internal/godotinternaltypes, internal/godotpoolarrays, + internal/godotstrings +import vector2, vector3, colors template definePoolArrayBase(T, GodotT, DataT, fieldName, newProcName, initProcName) = @@ -26,6 +29,36 @@ template definePoolArrayBase(T, GodotT, DataT, fieldName, newProcName, new(result, poolArrayFinalizer) 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; noData = false) = @@ -83,30 +116,6 @@ template definePoolArray(T, GodotT, DataT, fieldName, newProcName, initProcName; for pair in arr.fieldName.mpairs: 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, godotPoolByteArray, newPoolByteArray, initGodotPoolByteArray) diff --git a/godot/core/quats.nim b/godot/core/quats.nim index a60efc8..db88b10 100644 --- a/godot/core/quats.nim +++ b/godot/core/quats.nim @@ -1,6 +1,8 @@ # Copyright (c) 2018 Xored Software, Inc. -import internal.godotinternaltypes, internal.godotstrings +import hashes + +import internal/godotinternaltypes, internal/godotstrings import godotcoretypes, gdnativeapi 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.} = $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.} = getGDNativeAPI().quatLength(self) @@ -24,50 +29,50 @@ proc lengthSquared*(self: Quat): float32 {.inline.} = getGDNativeAPI().quatLengthSquared(self) proc normalized*(self: Quat): Quat {.inline.} = - getGDNativeAPI().quatNormalized(self) + getGDNativeAPI().quatNormalized(self).toQuat() proc isNormalized*(self: Quat): bool {.inline.} = getGDNativeAPI().quatIsNormalized(self) proc inverse*(self: Quat): Quat {.inline.} = - getGDNativeAPI().quatInverse(self) + getGDNativeAPI().quatInverse(self).toQuat() proc dot*(a, b: Quat): float32 {.inline.} = getGDNativeAPI().quatDot(a, b) 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.} = - getGDNativeAPI().quatSlerp(self, b, t) + getGDNativeAPI().quatSlerp(self, b, t).toQuat() 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; 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.} = - getGDNativeAPI().quatOperatorMultiply(a, b) + getGDNativeAPI().quatOperatorMultiply(a, b).toQuat() proc `*=`*(a: var Quat, b: float32) {.inline.} = a = a * b proc `+`*(a, b: Quat): Quat {.inline.} = - getGDNativeAPI().quatOperatorAdd(a, b) + getGDNativeAPI().quatOperatorAdd(a, b).toQuat() proc `+=`*(a: var Quat, b: Quat) {.inline.} = a = a + b proc `-`*(a, b: Quat): Quat {.inline.} = - getGDNativeAPI().quatOperatorSubtract(a, b) + getGDNativeAPI().quatOperatorSubtract(a, b).toQuat() proc `-=`* (a: var Quat, b: Quat) {.inline.} = a = a - b proc `/`*(self: Quat; b: float32): Quat {.inline.} = - getGDNativeAPI().quatOperatorDivide(self, b) + getGDNativeAPI().quatOperatorDivide(self, b).toQuat() proc `/=`*(self: var Quat, b: float32) {.inline.} = self = self / b @@ -76,4 +81,4 @@ proc `==`*(a, b: Quat): bool {.inline.} = getGDNativeAPI().quatOperatorEqual(a, b) proc `-`*(self: Quat): Quat {.inline.} = - getGDNativeAPI().quatOperatorNeg(self) + getGDNativeAPI().quatOperatorNeg(self).toQuat() diff --git a/godot/core/rect2.nim b/godot/core/rect2.nim index 2e73571..19b8cbf 100644 --- a/godot/core/rect2.nim +++ b/godot/core/rect2.nim @@ -1,7 +1,9 @@ # Copyright (c) 2018 Xored Software, Inc. +import hashes + import vector2 -import internal.godotinternaltypes, internal.godotstrings +import internal/godotinternaltypes, internal/godotstrings import godotcoretypes, gdnativeapi {.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.} = Rect2(position: vec2(x, y), size: vec2(sizeX, sizeY)) -proc `$`*(self: Rect2): string {.inline.} = +proc `$`*(self: Rect2): string {.inline, noinit.} = $getGDNativeAPI().rect2AsString(self) +proc hash*(self: Rect2): Hash {.inline, noinit.} = + !$(self.position.hash() !& self.size.hash()) + proc area*(self: Rect2): float32 {.inline, noinit.} = self.size.x * self.size.y diff --git a/godot/core/rids.nim b/godot/core/rids.nim index 35e054a..a64137d 100644 --- a/godot/core/rids.nim +++ b/godot/core/rids.nim @@ -1,6 +1,8 @@ # Copyright (c) 2018 Xored Software, Inc. -import godotcoretypes, internal.godotinternaltypes, gdnativeapi +import hashes + +import godotcoretypes, internal/godotinternaltypes, gdnativeapi proc initRID*(): RID {.inline.} = getGDNativeAPI().ridNew(result) @@ -14,6 +16,9 @@ proc id*(self: RID): uint32 {.inline.} = proc `$`*(self: RID): string {.inline.} = $self.id +proc hash*(self: RID): Hash {.inline.} = + self.id.hash() + proc `==`*(a, b: RID): bool {.inline.} = getGDNativeAPI().ridOperatorEqual(a, b) diff --git a/godot/core/transform2d.nim b/godot/core/transform2d.nim index 6fa4619..a8db09e 100644 --- a/godot/core/transform2d.nim +++ b/godot/core/transform2d.nim @@ -1,6 +1,8 @@ # Copyright (c) 2018 Xored Software, Inc. -import internal.godotinternaltypes, internal.godotstrings +import hashes, vector2 + +import internal/godotinternaltypes, internal/godotstrings import godotcoretypes, gdnativeapi proc initTransform2D*(): Transform2D {.inline.} = @@ -15,60 +17,63 @@ proc initTransform2D*(xAxis, yAxis, origin: Vector2): Transform2D {.inline.} = proc `$`*(self: Transform2D): string {.inline.} = $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.} = - getGDNativeAPI().transform2DInverse(self) + getGDNativeAPI().transform2DInverse(self).toTransform2D() proc affineInverse*(self: Transform2D): Transform2D {.inline.} = - getGDNativeAPI().transform2DAffineInverse(self) + getGDNativeAPI().transform2DAffineInverse(self).toTransform2D() proc rotation*(self: Transform2D): float32 {.inline.} = getGDNativeAPI().transform2DGetRotation(self) proc origin*(self: Transform2D): Vector2 {.inline.} = - getGDNativeAPI().transform2DGetOrigin(self) + getGDNativeAPI().transform2DGetOrigin(self).toVector2() proc scale*(self: Transform2D): Vector2 {.inline.} = - getGDNativeAPI().transform2DGetScale(self) + getGDNativeAPI().transform2DGetScale(self).toVector2() proc orthonormalized*(self: Transform2D): Transform2D {.inline.} = - getGDNativeAPI().transform2DOrthonormalized(self) + getGDNativeAPI().transform2DOrthonormalized(self).toTransform2D() 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.} = - getGDNativeAPI().transform2DScaled(self, scale) + getGDNativeAPI().transform2DScaled(self, scale).toTransform2D() 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.} = - getGDNativeAPI().transform2DXformVector2(self, v) + getGDNativeAPI().transform2DXformVector2(self, v).toVector2() 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.} = - getGDNativeAPI().transform2DBasisXformVector2(self, v) + getGDNativeAPI().transform2DBasisXformVector2(self, v).toVector2() 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.} = - getGDNativeAPI().transform2DXformRect2(self, rect) + getGDNativeAPI().transform2DXformRect2(self, rect).toRect2() proc xformInvRect2*(self: Transform2D; rect: Rect2): Rect2 {.inline.} = - getGDNativeAPI().transform2DXformInvRect2(self, rect) + getGDNativeAPI().transform2DXformInvRect2(self, rect).toRect2() proc interpolateWith*(self, m: Transform2D; c: float32): Transform2D {.inline.} = - getGDNativeAPI().transform2DInterpolateWith(self, m, c) + getGDNativeAPI().transform2DInterpolateWith(self, m, c).toTransform2D() proc `==`*(a, b: Transform2D): bool {.inline.} = getGDNativeAPI().transform2DOperatorEqual(a, b) proc `*`*(a, b: Transform2D): Transform2D {.inline.} = - getGDNativeAPI().transform2DOperatorMultiply(a, b) + getGDNativeAPI().transform2DOperatorMultiply(a, b).toTransform2D() proc `*=`*(a: var Transform2D, b: Transform2D) {.inline.} = a = a * b diff --git a/godot/core/transforms.nim b/godot/core/transforms.nim index c9021d6..501f743 100644 --- a/godot/core/transforms.nim +++ b/godot/core/transforms.nim @@ -1,8 +1,10 @@ # Copyright (c) 2018 Xored Software, Inc. -import internal.godotinternaltypes, internal.godotstrings +import hashes + +import internal/godotinternaltypes, internal/godotstrings import godotcoretypes, gdnativeapi -import basis +import basis, vector3 proc initTransform*(): Transform {.inline.} = result.basis = initBasis() @@ -21,51 +23,54 @@ proc initTransform*(basis: Basis, origin: Vector3): Transform {.inline.} = proc `$`*(self: Transform): string {.inline.} = $getGDNativeAPI().transformAsString(self) +proc hash*(self: Transform): Hash {.inline.} = + !$(self.basis.hash() !& self.origin.hash()) + proc inverse*(self: Transform): Transform {.inline.} = - getGDNativeAPI().transformInverse(self) + getGDNativeAPI().transformInverse(self).toTransform() proc affineInverse*(self: Transform): Transform {.inline.} = - getGDNativeAPI().transformAffineInverse(self) + getGDNativeAPI().transformAffineInverse(self).toTransform() proc orthonormalized*(self: Transform): Transform {.inline.} = - getGDNativeAPI().transformOrthonormalized(self) + getGDNativeAPI().transformOrthonormalized(self).toTransform() proc rotated*(self: Transform; axis: Vector3; phi: float32): Transform {.inline.} = - getGDNativeAPI().transformRotated(self, axis, phi) + getGDNativeAPI().transformRotated(self, axis, phi).toTransform() 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.} = - getGDNativeAPI().transformTranslated(self, offset) + getGDNativeAPI().transformTranslated(self, offset).toTransform() 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.} = - getGDNativeAPI().transformXformPlane(self, plane) + getGDNativeAPI().transformXformPlane(self, plane).toPlane() 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.} = - getGDNativeAPI().transformXformVector3(self, v) + getGDNativeAPI().transformXformVector3(self, v).toVector3() 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.} = - getGDNativeAPI().transformXformAABB(self, rect) + getGDNativeAPI().transformXformAABB(self, rect).toAABB() proc xformInvAABB*(self: Transform; rect: AABB): AABB {.inline.} = - getGDNativeAPI().transformXformInvAABB(self, rect) + getGDNativeAPI().transformXformInvAABB(self, rect).toAABB() proc `==`*(self: Transform; b: Transform): bool {.inline.} = getGDNativeAPI().transformOperatorEqual(self, b) proc `*`*(self, other: Transform): Transform {.inline.} = - getGDNativeAPI().transformOperatorMultiply(self, other) + getGDNativeAPI().transformOperatorMultiply(self, other).toTransform() proc `*=`*(self: var Transform, other: Transform) {.inline.} = self = self * other diff --git a/godot/core/variants.nim b/godot/core/variants.nim index 55284a1..fcb2b04 100644 --- a/godot/core/variants.nim +++ b/godot/core/variants.nim @@ -1,8 +1,9 @@ -import tables +import tables, hashes import godotcoretypes -import internal.godotinternaltypes, internal.godotvariants, - internal.godotstrings +import internal/godotinternaltypes, internal/godotvariants, + internal/godotstrings, internal/godotdictionaries, + internal/godotarrays type Variant* = ref object @@ -72,12 +73,13 @@ proc newVariant*(r: cdouble): Variant {.inline.} = proc newVariant*(s: string): Variant {.inline.} = new(result, variantFinalizer) - if s.isNil: - initGodotVariant(result.godotVariant) - else: - var godotStr = s.toGodotString() - initGodotVariant(result.godotVariant, godotStr) - godotStr.deinit() + when (NimMajor, NimMinor, NimPatch) < (0, 19, 0): + if s.isNil: + initGodotVariant(result.godotVariant) + return + var godotStr = s.toGodotString() + initGodotVariant(result.godotVariant, godotStr) + godotStr.deinit() import basis, nodepaths import planes, quats, rect2, aabb, rids @@ -140,11 +142,7 @@ proc newVariant*(obj: ptr GodotObject): Variant {.inline.} = new(result, variantFinalizer) initGodotVariant(result.godotVariant, obj) -import arrays, poolarrays - -proc newVariant*(arr: Array): Variant {.inline.} = - new(result, variantFinalizer) - initGodotVariant(result.godotVariant, arr.godotArray[]) +import poolarrays proc newVariant*(pba: PoolByteArray): Variant {.inline.} = new(result, variantFinalizer) @@ -177,81 +175,119 @@ proc newVariant*(pca: PoolColorArray): Variant {.inline.} = proc asBool*(self: Variant): bool {.inline.} = self.godotVariant.asBool() -proc asUInt*(self: Variant): uint64 = +proc asUInt*(self: Variant): uint64 {.inline.} = self.godotVariant.asUInt() -proc asInt*(self: Variant): int64 = +proc asInt*(self: Variant): int64 {.inline.} = self.godotVariant.asInt() -proc asReal*(self: Variant): cdouble = +proc asReal*(self: Variant): cdouble {.inline.} = self.godotVariant.asReal() -proc asString*(self: Variant): string = +proc asString*(self: Variant): string {.inline.} = $self -proc asVector2*(self: Variant): Vector2 = +proc asVector2*(self: Variant): Vector2 {.inline.} = self.godotVariant.asVector2() -proc asRect2*(self: Variant): Rect2 = +proc asRect2*(self: Variant): Rect2 {.inline.} = self.godotVariant.asRect2() -proc asVector3*(self: Variant): Vector3 = +proc asVector3*(self: Variant): Vector3 {.inline.} = self.godotVariant.asVector3() -proc asTransform2D*(self: Variant): Transform2D = +proc asTransform2D*(self: Variant): Transform2D {.inline.} = self.godotVariant.asTransform2D() -proc asPlane*(self: Variant): Plane = +proc asPlane*(self: Variant): Plane {.inline.} = self.godotVariant.asPlane() -proc asQuat*(self: Variant): Quat = +proc asQuat*(self: Variant): Quat {.inline.} = self.godotVariant.asQuat() -proc asAABB*(self: Variant): AABB = +proc asAABB*(self: Variant): AABB {.inline.} = self.godotVariant.asAABB() -proc asBasis*(self: Variant): Basis = +proc asBasis*(self: Variant): Basis {.inline.} = self.godotVariant.asBasis() -proc asTransform*(self: Variant): Transform = +proc asTransform*(self: Variant): Transform {.inline.} = self.godotVariant.asTransform() -proc asColor*(self: Variant): Color = +proc asColor*(self: Variant): Color {.inline.} = self.godotVariant.asColor() -proc asNodePath*(self: Variant): NodePath = +proc asNodePath*(self: Variant): NodePath {.inline.} = result = newNodePath(self.godotVariant.asNodePath()) -proc asRID*(self: Variant): RID = +proc asRID*(self: Variant): RID {.inline.} = self.godotVariant.asRID() -proc asGodotObject*(self: Variant): ptr GodotObject = +proc asGodotObject*(self: Variant): ptr GodotObject {.inline.} = self.godotVariant.asGodotObject() -proc asArray*(self: Variant): Array = - newArray(self.godotVariant.asGodotArray()) - -proc asPoolByteArray*(self: Variant): PoolByteArray = +proc asPoolByteArray*(self: Variant): PoolByteArray {.inline.} = newPoolByteArray(self.godotVariant.asGodotPoolByteArray()) -proc asPoolIntArray*(self: Variant): PoolIntArray = +proc asPoolIntArray*(self: Variant): PoolIntArray {.inline.} = newPoolIntArray(self.godotVariant.asGodotPoolIntArray()) -proc asPoolRealArray*(self: Variant): PoolRealArray = +proc asPoolRealArray*(self: Variant): PoolRealArray {.inline.} = newPoolRealArray(self.godotVariant.asGodotPoolRealArray()) -proc asPoolStringArray*(self: Variant): PoolStringArray = +proc asPoolStringArray*(self: Variant): PoolStringArray {.inline.} = newPoolStringArray(self.godotVariant.asGodotPoolStringArray()) -proc asPoolVector2Array*(self: Variant): PoolVector2Array = +proc asPoolVector2Array*(self: Variant): PoolVector2Array {.inline.} = newPoolVector2Array(self.godotVariant.asGodotPoolVector2Array()) -proc asPoolVector3Array*(self: Variant): PoolVector3Array = +proc asPoolVector3Array*(self: Variant): PoolVector3Array {.inline.} = newPoolVector3Array(self.godotVariant.asGodotPoolVector3Array()) -proc asPoolColorArray*(self: Variant): PoolColorArray = +proc asPoolColorArray*(self: Variant): PoolColorArray {.inline.} = newPoolColorArray(self.godotVariant.asGodotPoolColorArray()) +proc hash*(self: Variant): Hash = + proc objectHash(obj: ptr GodotObject): Hash = + if not obj.isNil: cast[int](obj).hash() else: 0.hash() + result = case self.getType(): + of VariantType.Nil: Hash(0) + of VariantType.Bool: self.asBool().hash() + of VariantType.Int: self.asInt().hash() + of VariantType.Real: self.asReal().hash() + of VariantType.String: self.asString().hash() + of VariantType.Vector2: self.asVector2().hash() + of VariantType.Rect2: self.asRect2().hash() + of VariantType.Vector3: self.asVector3().hash() + of VariantType.Transform2D: self.asTransform2D().hash() + of VariantType.Plane: self.asPlane().hash() + of VariantType.Quat: self.asQuat().hash() + of VariantType.AABB: self.asAABB().hash() + of VariantType.Basis: self.asBasis().hash() + of VariantType.Transform: self.asTransform().hash() + of VariantType.Color: self.asColor().hash() + of VariantType.NodePath: self.asNodePath().hash() + of VariantType.RID: self.asRID().hash() + of VariantType.Object: self.asGodotObject().objectHash() + of VariantType.Dictionary: hash(self.godotVariant.asGodotDictionary().godotHash()) + of VariantType.Array: hash(self.godotVariant.asGodotArray().godotHash()) + of VariantType.PoolByteArray: self.asPoolByteArray().hash() + of VariantType.PoolIntArray: self.asPoolIntArray().hash() + of VariantType.PoolRealArray: self.asPoolRealArray().hash() + of VariantType.PoolStringArray: self.asPoolStringArray().hash() + of VariantType.PoolVector2Array: self.asPoolVector2Array().hash() + of VariantType.PoolVector3Array: self.asPoolVector3Array().hash() + of VariantType.PoolColorArray: self.asPoolColorArray().hash() + +import arrays + +proc newVariant*(arr: Array): Variant {.inline.} = + new(result, variantFinalizer) + initGodotVariant(result.godotVariant, arr.godotArray[]) + +proc asArray*(self: Variant): Array {.inline.} = + newArray(self.godotVariant.asGodotArray()) + proc hasMethod*(self: Variant; meth: string): bool = var s = meth.toGodotString() result = self.godotVariant.hasMethod(s) diff --git a/godot/core/vector2.nim b/godot/core/vector2.nim index f15bd2f..390f1f6 100644 --- a/godot/core/vector2.nim +++ b/godot/core/vector2.nim @@ -1,10 +1,12 @@ # 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 +const EPSILON = 0.00001'f32 + {.push stackTrace: off.} proc vec2*(): Vector2 {.inline, noinit.} = @@ -16,6 +18,9 @@ proc vec2*(x, y: float32): Vector2 {.inline, noinit.} = proc `$`*(self: Vector2): string {.inline, noinit.} = $getGDNativeAPI().vector2AsString(self) +proc hash*(self: Vector2): Hash {.inline, noinit.} = + !$(self.x.hash() !& self.y.hash()) + proc `+`*(self, other: Vector2): Vector2 {.inline, noinit.} = 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.} = 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 if len != 0: len = sqrt(len) @@ -196,4 +201,14 @@ proc clamped*(self: Vector2; length: float32): Vector2 {.noinit.} = result /= len result *= length +proc moveToward*(vFrom, to: Vector2, delta: float32): Vector2 = + let + vd = to - vFrom + vLen = vd.length + + if vLen <= delta or vLen < EPSILON: + result = to + else: + result = vFrom + (vd / vLen) * delta + {.pop.} # stackTrace: off diff --git a/godot/core/vector3.nim b/godot/core/vector3.nim index 4ed9922..ed2903a 100644 --- a/godot/core/vector3.nim +++ b/godot/core/vector3.nim @@ -1,8 +1,10 @@ # Copyright (c) 2018 Xored Software, Inc. -import math +import math, hashes import godotbase, godotcoretypes +const EPSILON = 0.00001'f32 + {.push stackTrace: off.} proc vec3*(): Vector3 {.inline.} = @@ -21,6 +23,9 @@ proc `$`*(self: Vector3): string {.inline.} = result.add($self.z) result.add(')') +proc hash*(self: Vector3): Hash {.inline, noinit.} = + !$(self.x.hash() !& self.y.hash() !& self.z.hash()) + proc `+`*(a, b: Vector3): Vector3 {.inline.} = result.x = a.x + b.x result.y = a.y + b.y @@ -236,4 +241,14 @@ proc cubicInterpolate*(self, b, preA, postB: Vector3; (2.0 * p0 - 5.0 * p1 + 4 * p2 - p3) * t2 + (-p0 + 3.0 * p1 - 3.0 * p2 + p3) * t3) +proc moveToward*(vFrom, to: Vector3, delta: float32): Vector3 = + let + vd = to - vFrom + vLen = vd.length + + if vLen <= delta or vLen < EPSILON: + result = to + else: + result = vFrom + (vd / vLen) * delta + {.pop.} # stackTrace: off \ No newline at end of file diff --git a/godot/gdnativeapi.nim b/godot/gdnativeapi.nim index 3ece69b..bb05425 100644 --- a/godot/gdnativeapi.nim +++ b/godot/gdnativeapi.nim @@ -1,8 +1,38 @@ # Copyright 2018 Xored Software, Inc. -import internal.godotinternaltypes, core.godotcoretypes, macros +import internal/godotinternaltypes, core/godotcoretypes, macros type + ColorData* {.byref.} = object + data: array[16, uint8] + + Vector3Data* {.byref.} = object + data: array[12, uint8] + + Vector2Data* {.byref.} = object + data: array[8, uint8] + + PlaneData* {.byref.} = object + data: array[16, uint8] + + BasisData* {.byref.} = object + data: array[36, uint8] + + QuatData* {.byref.} = object + data: array[16, uint8] + + AABBData* {.byref.} = object + data: array[24, uint8] + + Rect2Data* {.byref.} = object + data: array[16, uint8] + + Transform2DData* {.byref.} = object + data: array[24, uint8] + + TransformData* {.byref.} = object + data: array[48, uint8] + GDNativeAPIType {.size: sizeof(cuint).} = enum GDNativeCore, GDNativeExtNativeScript, @@ -93,14 +123,14 @@ type {.noconv, raises: [], gcsafe, tags: [], locks: 0.} colorGray: proc (self: Color): float32 {.noconv, raises: [], gcsafe, tags: [], locks: 0.} - colorInverted: proc (self: Color): Color + colorInverted: proc (self: Color): ColorData {.noconv, raises: [], gcsafe, tags: [], locks: 0.} - colorContrasted: proc (self: Color): Color + colorContrasted: proc (self: Color): ColorData {.noconv, raises: [], gcsafe, tags: [], locks: 0.} - colorLinearInterpolate: proc (self, other: Color, t: float32): Color + colorLinearInterpolate: proc (self, other: Color, t: float32): ColorData {.noconv, raises: [], gcsafe, tags: [], locks: 0.} - colorBlend: proc (self, other: Color): Color + colorBlend: proc (self, other: Color): ColorData {.noconv, raises: [], gcsafe, tags: [], locks: 0.} colorToHtml: proc (self: Color, withAlpha: bool): GodotString {.noconv, raises: [], gcsafe, tags: [], locks: 0.} @@ -114,7 +144,7 @@ type {.noconv, raises: [], gcsafe, tags: [], locks: 0.} vector2AsString: proc (self: Vector2): GodotString {.noconv, raises: [], gcsafe, tags: [], locks: 0.} - vector2Normalized: proc (self: Vector2): Vector2 + vector2Normalized: proc (self: Vector2): Vector2Data {.noconv, raises: [], gcsafe, tags: [], locks: 0.} vector2Length: proc (self: Vector2): float32 {.noconv, raises: [], gcsafe, tags: [], locks: 0.} @@ -133,57 +163,57 @@ type {.noconv, raises: [], gcsafe, tags: [], locks: 0.} vector2AngleToPoint: proc (self, to: Vector2): float32 {.noconv, raises: [], gcsafe, tags: [], locks: 0.} - vector2LinearInterpolate: proc (self, b: Vector2, t: float32): Vector2 + vector2LinearInterpolate: proc (self, b: Vector2, t: float32): Vector2Data {.noconv, raises: [], gcsafe, tags: [], locks: 0.} vector2CubicInterpolate: proc (self, b, preA, postB: Vector2, - t: float32): Vector2 + t: float32): Vector2Data {.noconv, raises: [], gcsafe, tags: [], locks: 0.} - vector2Rotated: proc (self: Vector2, phi: float32): Vector2 + vector2Rotated: proc (self: Vector2, phi: float32): Vector2Data {.noconv, raises: [], gcsafe, tags: [], locks: 0.} - vector2Tangent: proc (self: Vector2): Vector2 + vector2Tangent: proc (self: Vector2): Vector2Data {.noconv, raises: [], gcsafe, tags: [], locks: 0.} - vector2Floor: proc (self: Vector2): Vector2 + vector2Floor: proc (self: Vector2): Vector2Data {.noconv, raises: [], gcsafe, tags: [], locks: 0.} - vector2Snapped: proc (self, by: Vector2): Vector2 + vector2Snapped: proc (self, by: Vector2): Vector2Data {.noconv, raises: [], gcsafe, tags: [], locks: 0.} vector2Aspect: proc (self: Vector2): float32 {.noconv, raises: [], gcsafe, tags: [], locks: 0.} vector2Dot: proc (self, other: Vector2): float32 {.noconv, raises: [], gcsafe, tags: [], locks: 0.} - vector2Slide: proc (self, n: Vector2): Vector2 + vector2Slide: proc (self, n: Vector2): Vector2Data {.noconv, raises: [], gcsafe, tags: [], locks: 0.} - vector2Bounce: proc (self, n: Vector2): Vector2 + vector2Bounce: proc (self, n: Vector2): Vector2Data {.noconv, raises: [], gcsafe, tags: [], locks: 0.} - vector2Reflect: proc (self, n: Vector2): Vector2 + vector2Reflect: proc (self, n: Vector2): Vector2Data {.noconv, raises: [], gcsafe, tags: [], locks: 0.} - vector2Abs: proc (self: Vector2): Vector2 + vector2Abs: proc (self: Vector2): Vector2Data {.noconv, raises: [], gcsafe, tags: [], locks: 0.} - vector2Clamped: proc (self: Vector2, length: float32): Vector2 + vector2Clamped: proc (self: Vector2, length: float32): Vector2Data {.noconv, raises: [], gcsafe, tags: [], locks: 0.} - vector2OperatorAdd: proc (self, other: Vector2): Vector2 + vector2OperatorAdd: proc (self, other: Vector2): Vector2Data {.noconv, raises: [], gcsafe, tags: [], locks: 0.} - vector2OperatorSubtract: proc (self, other: Vector2): Vector2 + vector2OperatorSubtract: proc (self, other: Vector2): Vector2Data {.noconv, raises: [], gcsafe, tags: [], locks: 0.} - vector2OperatorMultiplyVector: proc (self, other: Vector2): Vector2 + vector2OperatorMultiplyVector: proc (self, other: Vector2): Vector2Data {.noconv, raises: [], gcsafe, tags: [], locks: 0.} - vector2OperatorMultiplyScalar: proc (self: Vector2, scalar: float32): Vector2 + vector2OperatorMultiplyScalar: proc (self: Vector2, scalar: float32): Vector2Data {.noconv, raises: [], gcsafe, tags: [], locks: 0.} - vector2OperatorDivideVector: proc (self, other: Vector2): Vector2 + vector2OperatorDivideVector: proc (self, other: Vector2): Vector2Data {.noconv, raises: [], gcsafe, tags: [], locks: 0.} - vector2OperatorDivideScalar: proc (self: Vector2, scalar: float32): Vector2 + vector2OperatorDivideScalar: proc (self: Vector2, scalar: float32): Vector2Data {.noconv, raises: [], gcsafe, tags: [], locks: 0.} vector2OperatorEqual: proc (self, other: Vector2): bool {.noconv, raises: [], gcsafe, tags: [], locks: 0.} vector2OperatorLess: proc (self, other: Vector2): bool {.noconv, raises: [], gcsafe, tags: [], locks: 0.} - vector2OperatorNeg: proc (self: Vector2): Vector2 + vector2OperatorNeg: proc (self: Vector2): Vector2Data {.noconv, raises: [], gcsafe, tags: [], locks: 0.} vector2SetX: pointer vector2SetY: pointer @@ -218,33 +248,33 @@ type {.noconv, raises: [], gcsafe, tags: [], locks: 0.} quatLengthSquared: proc (self: Quat): float32 {.noconv, raises: [], gcsafe, tags: [], locks: 0.} - quatNormalized: proc (self: Quat): Quat + quatNormalized: proc (self: Quat): QuatData {.noconv, raises: [], gcsafe, tags: [], locks: 0.} quatIsNormalized: proc (self: Quat): bool {.noconv, raises: [], gcsafe, tags: [], locks: 0.} - quatInverse: proc (self: Quat): Quat + quatInverse: proc (self: Quat): QuatData {.noconv, raises: [], gcsafe, tags: [], locks: 0.} quatDot: proc (self, other: Quat): float32 {.noconv, raises: [], gcsafe, tags: [], locks: 0.} - quatXform: proc (self: Quat, v: Vector3): Vector3 + quatXform: proc (self: Quat, v: Vector3): Vector3Data {.noconv, raises: [], gcsafe, tags: [], locks: 0.} - quatSlerp: proc (self, other: Quat, t: float32): Quat + quatSlerp: proc (self, other: Quat, t: float32): QuatData {.noconv, raises: [], gcsafe, tags: [], locks: 0.} - quatSlerpni: proc (self, other: Quat, t: float32): Quat + quatSlerpni: proc (self, other: Quat, t: float32): QuatData {.noconv, raises: [], gcsafe, tags: [], locks: 0.} - quatCubicSlerp: proc (self, other, preA, postB: Quat, t: float32): Quat + quatCubicSlerp: proc (self, other, preA, postB: Quat, t: float32): QuatData {.noconv, raises: [], gcsafe, tags: [], locks: 0.} - quatOperatorMultiply: proc (self: Quat, b: float32): Quat + quatOperatorMultiply: proc (self: Quat, b: float32): QuatData {.noconv, raises: [], gcsafe, tags: [], locks: 0.} - quatOperatorAdd: proc (self, other: Quat): Quat + quatOperatorAdd: proc (self, other: Quat): QuatData {.noconv, raises: [], gcsafe, tags: [], locks: 0.} - quatOperatorSubtract: proc (self, other: Quat): Quat + quatOperatorSubtract: proc (self, other: Quat): QuatData {.noconv, raises: [], gcsafe, tags: [], locks: 0.} - quatOperatorDivide: proc (self: Quat, divider: float32): Quat + quatOperatorDivide: proc (self: Quat, divider: float32): QuatData {.noconv, raises: [], gcsafe, tags: [], locks: 0.} quatOperatorEqual: proc (self, other: Quat): bool {.noconv, raises: [], gcsafe, tags: [], locks: 0.} - quatOperatorNeg: proc (self: Quat): Quat + quatOperatorNeg: proc (self: Quat): QuatData {.noconv, raises: [], gcsafe, tags: [], locks: 0.} # Basis API @@ -534,7 +564,7 @@ type poolVector2ArraySet: proc (self: var GodotPoolVector2Array, idx: cint, data: Vector2) {.noconv, raises: [], gcsafe, tags: [], locks: 0.} - poolVector2ArrayGet: proc (self: GodotPoolVector2Array, idx: cint): Vector2 + poolVector2ArrayGet: proc (self: GodotPoolVector2Array, idx: cint): Vector2Data {.noconv, raises: [], gcsafe, tags: [], locks: 0.} poolVector2ArraySize: proc (self: GodotPoolVector2Array): cint {.noconv, raises: [], gcsafe, tags: [], locks: 0.} @@ -583,7 +613,7 @@ type poolVector3ArraySet: proc (self: var GodotPoolVector3Array, idx: cint, data: Vector3) {.noconv, raises: [], gcsafe, tags: [], locks: 0.} - poolVector3ArrayGet: proc (self: GodotPoolVector3Array, idx: cint): Vector3 + poolVector3ArrayGet: proc (self: GodotPoolVector3Array, idx: cint): Vector3Data {.noconv, raises: [], gcsafe, tags: [], locks: 0.} poolVector3ArraySize: proc (self: GodotPoolVector3Array): cint {.noconv, raises: [], gcsafe, tags: [], locks: 0.} @@ -628,7 +658,7 @@ type poolColorArraySet: proc (self: var GodotPoolColorArray, idx: cint, data: Color) {.noconv, raises: [], gcsafe, tags: [], locks: 0.} - poolColorArrayGet: proc (self: GodotPoolColorArray, idx: cint): Color + poolColorArrayGet: proc (self: GodotPoolColorArray, idx: cint): ColorData {.noconv, raises: [], gcsafe, tags: [], locks: 0.} poolColorArraySize: proc (self: GodotPoolColorArray): cint {.noconv, raises: [], gcsafe, tags: [], locks: 0.} @@ -937,11 +967,11 @@ type {.noconv, raises: [], gcsafe, tags: [], locks: 0.} planeAsString: proc (self: Plane): GodotString {.noconv, raises: [], gcsafe, tags: [], locks: 0.} - planeNormalized: proc (self: Plane): Plane + planeNormalized: proc (self: Plane): PlaneData {.noconv, raises: [], gcsafe, tags: [], locks: 0.} - planeCenter: proc (self: Plane): Vector3 + planeCenter: proc (self: Plane): Vector3Data {.noconv, raises: [], gcsafe, tags: [], locks: 0.} - planeGetAnyPoint: proc (self: Plane): Vector3 + planeGetAnyPoint: proc (self: Plane): Vector3Data {.noconv, raises: [], gcsafe, tags: [], locks: 0.} planeIsPointOver: proc (self: Plane, point: Vector3): bool {.noconv, raises: [], gcsafe, tags: [], locks: 0.} @@ -949,7 +979,7 @@ type {.noconv, raises: [], gcsafe, tags: [], locks: 0.} planeHasPoint: proc (self: Plane, point: Vector3, epsilon: float32): bool {.noconv, raises: [], gcsafe, tags: [], locks: 0.} - planeProject: proc (self: Plane, point: Vector3): Vector3 + planeProject: proc (self: Plane, point: Vector3): Vector3Data {.noconv, raises: [], gcsafe, tags: [], locks: 0.} planeIntersect3: proc (self: Plane, dest: var Vector3, b, c: Plane): bool {.noconv, raises: [], gcsafe, tags: [], locks: 0.} @@ -960,13 +990,13 @@ type segmentBegin, segmentEnd: Vector3): bool {.noconv, raises: [], gcsafe, tags: [], locks: 0.} - planeOperatorNeg: proc (self: Plane): Plane + planeOperatorNeg: proc (self: Plane): PlaneData {.noconv, raises: [], gcsafe, tags: [], locks: 0.} planeOperatorEqual: proc (self, other: Plane): bool {.noconv, raises: [], gcsafe, tags: [], locks: 0.} planeSetNormal: proc (self: var Plane, normal: Vector3) {.noconv, raises: [], gcsafe, tags: [], locks: 0.} - planeGetNormal: proc (self: Plane): Vector3 + planeGetNormal: proc (self: Plane): Vector3Data {.noconv, raises: [], gcsafe, tags: [], locks: 0.} planeGetD: proc (self: Plane): float32 {.noconv, raises: [], gcsafe, tags: [], locks: 0.} @@ -989,21 +1019,21 @@ type {.noconv, raises: [], gcsafe, tags: [], locks: 0.} rect2HasNoArea: proc (self: Rect2): bool {.noconv, raises: [], gcsafe, tags: [], locks: 0.} - rect2Clip: proc (self, other: Rect2): Rect2 + rect2Clip: proc (self, other: Rect2): Rect2Data {.noconv, raises: [], gcsafe, tags: [], locks: 0.} - rect2Merge: proc (self, other: Rect2): Rect2 + rect2Merge: proc (self, other: Rect2): Rect2Data {.noconv, raises: [], gcsafe, tags: [], locks: 0.} rect2HasPoint: proc (self: Rect2, point: Vector2): bool {.noconv, raises: [], gcsafe, tags: [], locks: 0.} - rect2Grow: proc (self: Rect2, by: float32): Rect2 + rect2Grow: proc (self: Rect2, by: float32): Rect2Data {.noconv, raises: [], gcsafe, tags: [], locks: 0.} - rect2Expand: proc (self: Rect2, to: Vector2): Rect2 + rect2Expand: proc (self: Rect2, to: Vector2): Rect2Data {.noconv, raises: [], gcsafe, tags: [], locks: 0.} rect2OperatorEqual: proc (self, other: Rect2): bool {.noconv, raises: [], gcsafe, tags: [], locks: 0.} - rect2GetPosition: proc (self: Rect2): Vector2 + rect2GetPosition: proc (self: Rect2): Vector2Data {.noconv, raises: [], gcsafe, tags: [], locks: 0.} - rect2GetSize: proc (self: Rect2): Vector2 + rect2GetSize: proc (self: Rect2): Vector2Data {.noconv, raises: [], gcsafe, tags: [], locks: 0.} rect2SetPosition: proc (self: var Rect2, pos: Vector2) {.noconv, raises: [], gcsafe, tags: [], locks: 0.} @@ -1013,11 +1043,11 @@ type # AABB API aabbNew: proc (dest: var AABB, pos, size: Vector3) {.noconv, raises: [], gcsafe, tags: [], locks: 0.} - aabbGetPosition: proc (self: AABB): Vector3 + aabbGetPosition: proc (self: AABB): Vector3Data {.noconv, raises: [], gcsafe, tags: [], locks: 0.} aabbSetPosition: proc (self: var AABB, pos: Vector3) {.noconv, raises: [], gcsafe, tags: [], locks: 0.} - aabbGetSize: proc (self: AABB): Vector3 + aabbGetSize: proc (self: AABB): Vector3Data {.noconv, raises: [], gcsafe, tags: [], locks: 0.} aabbSetSize: proc (self: var AABB, pos: Vector3) {.noconv, raises: [], gcsafe, tags: [], locks: 0.} @@ -1033,9 +1063,9 @@ type {.noconv, raises: [], gcsafe, tags: [], locks: 0.} aabbEncloses: proc (self, other: AABB): bool {.noconv, raises: [], gcsafe, tags: [], locks: 0.} - aabbMerge: proc (self, other: AABB): AABB + aabbMerge: proc (self, other: AABB): AABBData {.noconv, raises: [], gcsafe, tags: [], locks: 0.} - aabbIntersection: proc (self, other: AABB): AABB + aabbIntersection: proc (self, other: AABB): AABBData {.noconv, raises: [], gcsafe, tags: [], locks: 0.} aabbIntersectsPlane: proc (self: AABB, plane: Plane): bool {.noconv, raises: [], gcsafe, tags: [], locks: 0.} @@ -1044,9 +1074,9 @@ type locks: 0.} aabbHasPoint: proc (self: AABB, point: Vector3): bool {.noconv, raises: [], gcsafe, tags: [], locks: 0.} - aabbGetSupport: proc (self: AABB, dir: Vector3): Vector3 + aabbGetSupport: proc (self: AABB, dir: Vector3): Vector3Data {.noconv, raises: [], gcsafe, tags: [], locks: 0.} - aabbGetLongestAxis: proc (self: AABB): Vector3 + aabbGetLongestAxis: proc (self: AABB): Vector3Data {.noconv, raises: [], gcsafe, tags: [], locks: 0.} aabbGetLongestAxisIndex: proc (self: AABB): cint {.noconv, raises: [], gcsafe, tags: [], @@ -1054,7 +1084,7 @@ type aabbGetLongestAxisSize: proc (self: AABB): float32 {.noconv, raises: [], gcsafe, tags: [], locks: 0.} - aabbGetShortestAxis: proc (self: AABB): Vector3 + aabbGetShortestAxis: proc (self: AABB): Vector3Data {.noconv, raises: [], gcsafe, tags: [], locks: 0.} aabbGetShortestAxisIndex: proc (self: AABB): cint {.noconv, raises: [], gcsafe, tags: [], @@ -1062,11 +1092,11 @@ type aabbGetShortestAxisSize: proc (self: AABB): float32 {.noconv, raises: [], gcsafe, tags: [], locks: 0.} - aabbExpand: proc (self: AABB, toPoint: Vector3): AABB + aabbExpand: proc (self: AABB, toPoint: Vector3): AABBData {.noconv, raises: [], gcsafe, tags: [], locks: 0.} - aabbGrow: proc (self: AABB, by: float32): AABB + aabbGrow: proc (self: AABB, by: float32): AABBData {.noconv, raises: [], gcsafe, tags: [], locks: 0.} - aabbGetEndpoint: proc (self: AABB, idx: cint): Vector3 + aabbGetEndpoint: proc (self: AABB, idx: cint): Vector3Data {.noconv, raises: [], gcsafe, tags: [], locks: 0.} aabbOperatorEqual: proc (self, other: AABB): bool {.noconv, raises: [], gcsafe, tags: [], locks: 0.} @@ -1090,36 +1120,36 @@ type locks: 0.} transformNew: proc (dest: var Transform, basis: Basis, origin: Vector3) {.noconv, raises: [], gcsafe, tags: [], locks: 0.} - transformGetBasis: proc (self: Transform): Basis + transformGetBasis: proc (self: Transform): BasisData {.noconv, raises: [], gcsafe, tags: [], locks: 0.} transformSetBasis: proc (self: var Transform, basis: Basis) {.noconv, raises: [], gcsafe, tags: [], locks: 0.} - transformGetOrigin: proc (self: Transform): Vector3 + transformGetOrigin: proc (self: Transform): Vector3Data {.noconv, raises: [], gcsafe, tags: [], locks: 0.} transformSetOrigin: proc (self: var Transform, v: Vector3) {.noconv, raises: [], gcsafe, tags: [], locks: 0.} transformAsString: proc (self: Transform): GodotString {.noconv, raises: [], gcsafe, tags: [], locks: 0.} - transformInverse: proc (self: Transform): Transform + transformInverse: proc (self: Transform): TransformData {.noconv, raises: [], gcsafe, tags: [], locks: 0.} - transformAffineInverse: proc (self: Transform): Transform + transformAffineInverse: proc (self: Transform): TransformData {.noconv, raises: [], gcsafe, tags: [], locks: 0.} - transformOrthonormalized: proc (self: Transform): Transform + transformOrthonormalized: proc (self: Transform): TransformData {.noconv, raises: [], gcsafe, tags: [], locks: 0.} transformRotated: proc (self: Transform, axis: Vector3, - phi: float32): Transform + phi: float32): TransformData {.noconv, raises: [], gcsafe, tags: [], locks: 0.} - transformScaled: proc (self: Transform, scale: Vector3): Transform + transformScaled: proc (self: Transform, scale: Vector3): TransformData {.noconv, raises: [], gcsafe, tags: [], locks: 0.} - transformTranslated: proc (self: Transform, offset: Vector3): Transform + transformTranslated: proc (self: Transform, offset: Vector3): TransformData {.noconv, raises: [], gcsafe, tags: [], locks: 0.} - transformLookingAt: proc (self: Transform, target, up: Vector3): Transform + transformLookingAt: proc (self: Transform, target, up: Vector3): TransformData {.noconv, raises: [], gcsafe, tags: [], locks: 0.} - transformXformPlane: proc (self: Transform, plane: Plane): Plane + transformXformPlane: proc (self: Transform, plane: Plane): PlaneData {.noconv, raises: [], gcsafe, tags: [], locks: 0.} - transformXformInvPlane: proc (self: Transform, plane: Plane): Plane + transformXformInvPlane: proc (self: Transform, plane: Plane): PlaneData {.noconv, raises: [], gcsafe, tags: [], locks: 0.} transformNewIdentity: proc (dest: var Transform) @@ -1127,18 +1157,18 @@ type transformOperatorEqual: proc (self, other: Transform): bool {.noconv, raises: [], gcsafe, tags: [], locks: 0.} - transformOperatorMultiply: proc (self, other: Transform): Transform + transformOperatorMultiply: proc (self, other: Transform): TransformData {.noconv, raises: [], gcsafe, tags: [], locks: 0.} - transformXformVector3: proc (self: Transform, v: Vector3): Vector3 + transformXformVector3: proc (self: Transform, v: Vector3): Vector3Data {.noconv, raises: [], gcsafe, tags: [], locks: 0.} - transformXformInvVector3: proc (self: Transform, v: Vector3): Vector3 + transformXformInvVector3: proc (self: Transform, v: Vector3): Vector3Data {.noconv, raises: [], gcsafe, tags: [], locks: 0.} - transformXformAABB: proc (self: Transform, v: AABB): AABB + transformXformAABB: proc (self: Transform, v: AABB): AABBData {.noconv, raises: [], gcsafe, tags: [], locks: 0.} - transformXformInvAABB: proc (self: Transform, v: AABB): AABB + transformXformInvAABB: proc (self: Transform, v: AABB): AABBData {.noconv, raises: [], gcsafe, tags: [], locks: 0.} @@ -1151,58 +1181,58 @@ type locks: 0.} transform2DAsString: proc (self: Transform2D): GodotString {.noconv, raises: [], gcsafe, tags: [], locks: 0.} - transform2DInverse: proc (self: Transform2D): Transform2D + transform2DInverse: proc (self: Transform2D): Transform2DData {.noconv, raises: [], gcsafe, tags: [], locks: 0.} - transform2DAffineInverse: proc (self: Transform2D): Transform2D + transform2DAffineInverse: proc (self: Transform2D): Transform2DData {.noconv, raises: [], gcsafe, tags: [], locks: 0.} transform2DGetRotation: proc (self: Transform2D): float32 {.noconv, raises: [], gcsafe, tags: [], locks: 0.} - transform2DGetOrigin: proc (self: Transform2D): Vector2 + transform2DGetOrigin: proc (self: Transform2D): Vector2Data {.noconv, raises: [], gcsafe, tags: [], locks: 0.} - transform2DGetScale: proc (self: Transform2D): Vector2 + transform2DGetScale: proc (self: Transform2D): Vector2Data {.noconv, raises: [], gcsafe, tags: [], locks: 0.} - transform2DOrthonormalized: proc (self: Transform2D): Transform2D + transform2DOrthonormalized: proc (self: Transform2D): Transform2DData {.noconv, raises: [], gcsafe, tags: [], locks: 0.} - transform2DRotated: proc (self: Transform2D, phi: float32): Transform2D + transform2DRotated: proc (self: Transform2D, phi: float32): Transform2DData {.noconv, raises: [], gcsafe, tags: [], locks: 0.} - transform2DScaled: proc (self: Transform2D, scale: Vector2): Transform2D + transform2DScaled: proc (self: Transform2D, scale: Vector2): Transform2DData {.noconv, raises: [], gcsafe, tags: [], locks: 0.} - transform2DTranslated: proc (self: Transform2D, offset: Vector2): Transform2D + transform2DTranslated: proc (self: Transform2D, offset: Vector2): Transform2DData {.noconv, raises: [], gcsafe, tags: [], locks: 0.} - transform2DXformVector2: proc (self: Transform2D, v: Vector2): Vector2 + transform2DXformVector2: proc (self: Transform2D, v: Vector2): Vector2Data {.noconv, raises: [], gcsafe, tags: [], locks: 0.} - transform2DXformInvVector2: proc (self: Transform2D, v: Vector2): Vector2 + transform2DXformInvVector2: proc (self: Transform2D, v: Vector2): Vector2Data {.noconv, raises: [], gcsafe, tags: [], locks: 0.} - transform2DBasisXformVector2: proc (self: Transform2D, v: Vector2): Vector2 + transform2DBasisXformVector2: proc (self: Transform2D, v: Vector2): Vector2Data {.noconv, raises: [], gcsafe, tags: [], locks: 0.} transform2DBasisXformInvVector2: proc (self: Transform2D, - v: Vector2): Vector2 + v: Vector2): Vector2Data {.noconv, raises: [], gcsafe, tags: [], locks: 0.} transform2DInterpolateWith: proc (self, other: Transform2D, - t: float32): Transform2D + t: float32): Transform2DData {.noconv, raises: [], gcsafe, tags: [], locks: 0.} transform2DOperatorEqual: proc (self, other: Transform2D): bool {.noconv, raises: [], gcsafe, tags: [], locks: 0.} - transform2DOperatorMultiply: proc (self, other: Transform2D): Transform2D + transform2DOperatorMultiply: proc (self, other: Transform2D): Transform2DData {.noconv, raises: [], gcsafe, tags: [], locks: 0.} transform2DNewIdentity: proc (dest: var Transform2D) {.noconv, raises: [], gcsafe, tags: [], locks: 0.} - transform2DXformRect2: proc (self: Transform2D, v: Rect2): Rect2 + transform2DXformRect2: proc (self: Transform2D, v: Rect2): Rect2Data {.noconv, raises: [], gcsafe, tags: [], locks: 0.} - transform2DXformInvRect2: proc (self: Transform2D, v: Rect2): Rect2 + transform2DXformInvRect2: proc (self: Transform2D, v: Rect2): Rect2Data {.noconv, raises: [], gcsafe, tags: [], locks: 0.} @@ -1291,25 +1321,25 @@ type {.noconv, raises: [], gcsafe, tags: [], locks: 0.} variantAsString: proc (self: GodotVariant): GodotString {.noconv, raises: [], gcsafe, tags: [], locks: 0.} - variantAsVector2: proc (self: GodotVariant): Vector2 + variantAsVector2: proc (self: GodotVariant): Vector2Data {.noconv, raises: [], gcsafe, tags: [], locks: 0.} - variantAsRect2: proc (self: GodotVariant): Rect2 + variantAsRect2: proc (self: GodotVariant): Rect2Data {.noconv, raises: [], gcsafe, tags: [], locks: 0.} - variantAsVector3: proc (self: GodotVariant): Vector3 + variantAsVector3: proc (self: GodotVariant): Vector3Data {.noconv, raises: [], gcsafe, tags: [], locks: 0.} - variantAsTransform2D: proc (self: GodotVariant): Transform2D + variantAsTransform2D: proc (self: GodotVariant): Transform2DData {.noconv, raises: [], gcsafe, tags: [], locks: 0.} - variantAsPlane: proc (self: GodotVariant): Plane + variantAsPlane: proc (self: GodotVariant): PlaneData {.noconv, raises: [], gcsafe, tags: [], locks: 0.} - variantAsQuat: proc (self: GodotVariant): Quat + variantAsQuat: proc (self: GodotVariant): QuatData {.noconv, raises: [], gcsafe, tags: [], locks: 0.} - variantAsAABB: proc (self: GodotVariant): AABB + variantAsAABB: proc (self: GodotVariant): AABBData {.noconv, raises: [], gcsafe, tags: [], locks: 0.} - variantAsBasis: proc (self: GodotVariant): Basis + variantAsBasis: proc (self: GodotVariant): BasisData {.noconv, raises: [], gcsafe, tags: [], locks: 0.} - variantAsTransform: proc (self: GodotVariant): Transform + variantAsTransform: proc (self: GodotVariant): TransformData {.noconv, raises: [], gcsafe, tags: [], locks: 0.} - variantAsColor: proc (self: GodotVariant): Color + variantAsColor: proc (self: GodotVariant): ColorData {.noconv, raises: [], gcsafe, tags: [], locks: 0.} variantAsNodePath: proc (self: GodotVariant): GodotNodePath {.noconv, raises: [], gcsafe, tags: [], locks: 0.} @@ -1374,7 +1404,8 @@ type stringNewWithWideString: pointer stringOperatorIndex: pointer stringOperatorIndexConst: pointer - stringWideStr: pointer + stringWideStr: proc (self: GodotString): ptr cwchar_t + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} stringOperatorEqual: proc (self, other: GodotString): bool {.noconv, raises: [], gcsafe, tags: [], locks: 0.} stringOperatorLess: proc (self, other: GodotString): bool @@ -1610,14 +1641,14 @@ type {.noconv, raises: [], gcsafe, tags: [], locks: 0.} colorGray*: proc (self: Color): float32 {.noconv, raises: [], gcsafe, tags: [], locks: 0.} - colorInverted*: proc (self: Color): Color + colorInverted*: proc (self: Color): ColorData {.noconv, raises: [], gcsafe, tags: [], locks: 0.} - colorContrasted*: proc (self: Color): Color + colorContrasted*: proc (self: Color): ColorData {.noconv, raises: [], gcsafe, tags: [], locks: 0.} - colorLinearInterpolate*: proc (self, other: Color, t: float32): Color + colorLinearInterpolate*: proc (self, other: Color, t: float32): ColorData {.noconv, raises: [], gcsafe, tags: [], locks: 0.} - colorBlend*: proc (self, other: Color): Color + colorBlend*: proc (self, other: Color): ColorData {.noconv, raises: [], gcsafe, tags: [], locks: 0.} colorToHtml*: proc (self: Color, withAlpha: bool): GodotString {.noconv, raises: [], gcsafe, tags: [], locks: 0.} @@ -1631,7 +1662,7 @@ type {.noconv, raises: [], gcsafe, tags: [], locks: 0.} vector2AsString*: proc (self: Vector2): GodotString {.noconv, raises: [], gcsafe, tags: [], locks: 0.} - vector2Normalized*: proc (self: Vector2): Vector2 + vector2Normalized*: proc (self: Vector2): Vector2Data {.noconv, raises: [], gcsafe, tags: [], locks: 0.} vector2Length*: proc (self: Vector2): float32 {.noconv, raises: [], gcsafe, tags: [], locks: 0.} @@ -1650,57 +1681,57 @@ type {.noconv, raises: [], gcsafe, tags: [], locks: 0.} vector2AngleToPoint*: proc (self, to: Vector2): float32 {.noconv, raises: [], gcsafe, tags: [], locks: 0.} - vector2LinearInterpolate*: proc (self, b: Vector2, t: float32): Vector2 + vector2LinearInterpolate*: proc (self, b: Vector2, t: float32): Vector2Data {.noconv, raises: [], gcsafe, tags: [], locks: 0.} vector2CubicInterpolate*: proc (self, b, preA, postB: Vector2, - t: float32): Vector2 + t: float32): Vector2Data {.noconv, raises: [], gcsafe, tags: [], locks: 0.} - vector2Rotated*: proc (self: Vector2, phi: float32): Vector2 + vector2Rotated*: proc (self: Vector2, phi: float32): Vector2Data {.noconv, raises: [], gcsafe, tags: [], locks: 0.} - vector2Tangent*: proc (self: Vector2): Vector2 + vector2Tangent*: proc (self: Vector2): Vector2Data {.noconv, raises: [], gcsafe, tags: [], locks: 0.} - vector2Floor*: proc (self: Vector2): Vector2 + vector2Floor*: proc (self: Vector2): Vector2Data {.noconv, raises: [], gcsafe, tags: [], locks: 0.} - vector2Snapped*: proc (self, by: Vector2): Vector2 + vector2Snapped*: proc (self, by: Vector2): Vector2Data {.noconv, raises: [], gcsafe, tags: [], locks: 0.} vector2Aspect*: proc (self: Vector2): float32 {.noconv, raises: [], gcsafe, tags: [], locks: 0.} vector2Dot*: proc (self, other: Vector2): float32 {.noconv, raises: [], gcsafe, tags: [], locks: 0.} - vector2Slide*: proc (self, n: Vector2): Vector2 + vector2Slide*: proc (self, n: Vector2): Vector2Data {.noconv, raises: [], gcsafe, tags: [], locks: 0.} - vector2Bounce*: proc (self, n: Vector2): Vector2 + vector2Bounce*: proc (self, n: Vector2): Vector2Data {.noconv, raises: [], gcsafe, tags: [], locks: 0.} - vector2Reflect*: proc (self, n: Vector2): Vector2 + vector2Reflect*: proc (self, n: Vector2): Vector2Data {.noconv, raises: [], gcsafe, tags: [], locks: 0.} - vector2Abs*: proc (self: Vector2): Vector2 + vector2Abs*: proc (self: Vector2): Vector2Data {.noconv, raises: [], gcsafe, tags: [], locks: 0.} - vector2Clamped*: proc (self: Vector2, length: float32): Vector2 + vector2Clamped*: proc (self: Vector2, length: float32): Vector2Data {.noconv, raises: [], gcsafe, tags: [], locks: 0.} - vector2OperatorAdd*: proc (self, other: Vector2): Vector2 + vector2OperatorAdd*: proc (self, other: Vector2): Vector2Data {.noconv, raises: [], gcsafe, tags: [], locks: 0.} - vector2OperatorSubtract*: proc (self, other: Vector2): Vector2 + vector2OperatorSubtract*: proc (self, other: Vector2): Vector2Data {.noconv, raises: [], gcsafe, tags: [], locks: 0.} - vector2OperatorMultiplyVector*: proc (self, other: Vector2): Vector2 + vector2OperatorMultiplyVector*: proc (self, other: Vector2): Vector2Data {.noconv, raises: [], gcsafe, tags: [], locks: 0.} - vector2OperatorMultiplyScalar*: proc (self: Vector2, scalar: float32): Vector2 + vector2OperatorMultiplyScalar*: proc (self: Vector2, scalar: float32): Vector2Data {.noconv, raises: [], gcsafe, tags: [], locks: 0.} - vector2OperatorDivideVector*: proc (self, other: Vector2): Vector2 + vector2OperatorDivideVector*: proc (self, other: Vector2): Vector2Data {.noconv, raises: [], gcsafe, tags: [], locks: 0.} - vector2OperatorDivideScalar*: proc (self: Vector2, scalar: float32): Vector2 + vector2OperatorDivideScalar*: proc (self: Vector2, scalar: float32): Vector2Data {.noconv, raises: [], gcsafe, tags: [], locks: 0.} vector2OperatorEqual*: proc (self, other: Vector2): bool {.noconv, raises: [], gcsafe, tags: [], locks: 0.} vector2OperatorLess*: proc (self, other: Vector2): bool {.noconv, raises: [], gcsafe, tags: [], locks: 0.} - vector2OperatorNeg*: proc (self: Vector2): Vector2 + vector2OperatorNeg*: proc (self: Vector2): Vector2Data {.noconv, raises: [], gcsafe, tags: [], locks: 0.} # Quat API @@ -1731,33 +1762,33 @@ type {.noconv, raises: [], gcsafe, tags: [], locks: 0.} quatLengthSquared*: proc (self: Quat): float32 {.noconv, raises: [], gcsafe, tags: [], locks: 0.} - quatNormalized*: proc (self: Quat): Quat + quatNormalized*: proc (self: Quat): QuatData {.noconv, raises: [], gcsafe, tags: [], locks: 0.} quatIsNormalized*: proc (self: Quat): bool {.noconv, raises: [], gcsafe, tags: [], locks: 0.} - quatInverse*: proc (self: Quat): Quat + quatInverse*: proc (self: Quat): QuatData {.noconv, raises: [], gcsafe, tags: [], locks: 0.} quatDot*: proc (self, other: Quat): float32 {.noconv, raises: [], gcsafe, tags: [], locks: 0.} - quatXform*: proc (self: Quat, v: Vector3): Vector3 + quatXform*: proc (self: Quat, v: Vector3): Vector3Data {.noconv, raises: [], gcsafe, tags: [], locks: 0.} - quatSlerp*: proc (self, other: Quat, t: float32): Quat + quatSlerp*: proc (self, other: Quat, t: float32): QuatData {.noconv, raises: [], gcsafe, tags: [], locks: 0.} - quatSlerpni*: proc (self, other: Quat, t: float32): Quat + quatSlerpni*: proc (self, other: Quat, t: float32): QuatData {.noconv, raises: [], gcsafe, tags: [], locks: 0.} - quatCubicSlerp*: proc (self, other, preA, postB: Quat, t: float32): Quat + quatCubicSlerp*: proc (self, other, preA, postB: Quat, t: float32): QuatData {.noconv, raises: [], gcsafe, tags: [], locks: 0.} - quatOperatorMultiply*: proc (self: Quat, b: float32): Quat + quatOperatorMultiply*: proc (self: Quat, b: float32): QuatData {.noconv, raises: [], gcsafe, tags: [], locks: 0.} - quatOperatorAdd*: proc (self, other: Quat): Quat + quatOperatorAdd*: proc (self, other: Quat): QuatData {.noconv, raises: [], gcsafe, tags: [], locks: 0.} - quatOperatorSubtract*: proc (self, other: Quat): Quat + quatOperatorSubtract*: proc (self, other: Quat): QuatData {.noconv, raises: [], gcsafe, tags: [], locks: 0.} - quatOperatorDivide*: proc (self: Quat, divider: float32): Quat + quatOperatorDivide*: proc (self: Quat, divider: float32): QuatData {.noconv, raises: [], gcsafe, tags: [], locks: 0.} quatOperatorEqual*: proc (self, other: Quat): bool {.noconv, raises: [], gcsafe, tags: [], locks: 0.} - quatOperatorNeg*: proc (self: Quat): Quat + quatOperatorNeg*: proc (self: Quat): QuatData {.noconv, raises: [], gcsafe, tags: [], locks: 0.} # PoolByteArray API @@ -1976,7 +2007,7 @@ type poolVector2ArraySet*: proc (self: var GodotPoolVector2Array, idx: cint, data: Vector2) {.noconv, raises: [], gcsafe, tags: [], locks: 0.} - poolVector2ArrayGet*: proc (self: GodotPoolVector2Array, idx: cint): Vector2 + poolVector2ArrayGet*: proc (self: GodotPoolVector2Array, idx: cint): Vector2Data {.noconv, raises: [], gcsafe, tags: [], locks: 0.} poolVector2ArraySize*: proc (self: GodotPoolVector2Array): cint {.noconv, raises: [], gcsafe, tags: [], locks: 0.} @@ -2025,7 +2056,7 @@ type poolVector3ArraySet*: proc (self: var GodotPoolVector3Array, idx: cint, data: Vector3) {.noconv, raises: [], gcsafe, tags: [], locks: 0.} - poolVector3ArrayGet*: proc (self: GodotPoolVector3Array, idx: cint): Vector3 + poolVector3ArrayGet*: proc (self: GodotPoolVector3Array, idx: cint): Vector3Data {.noconv, raises: [], gcsafe, tags: [], locks: 0.} poolVector3ArraySize*: proc (self: GodotPoolVector3Array): cint {.noconv, raises: [], gcsafe, tags: [], locks: 0.} @@ -2070,7 +2101,7 @@ type poolColorArraySet*: proc (self: var GodotPoolColorArray, idx: cint, data: Color) {.noconv, raises: [], gcsafe, tags: [], locks: 0.} - poolColorArrayGet*: proc (self: GodotPoolColorArray, idx: cint): Color + poolColorArrayGet*: proc (self: GodotPoolColorArray, idx: cint): ColorData {.noconv, raises: [], gcsafe, tags: [], locks: 0.} poolColorArraySize*: proc (self: GodotPoolColorArray): cint {.noconv, raises: [], gcsafe, tags: [], locks: 0.} @@ -2377,11 +2408,11 @@ type {.noconv, raises: [], gcsafe, tags: [], locks: 0.} planeAsString*: proc (self: Plane): GodotString {.noconv, raises: [], gcsafe, tags: [], locks: 0.} - planeNormalized*: proc (self: Plane): Plane + planeNormalized*: proc (self: Plane): PlaneData {.noconv, raises: [], gcsafe, tags: [], locks: 0.} - planeCenter*: proc (self: Plane): Vector3 + planeCenter*: proc (self: Plane): Vector3Data {.noconv, raises: [], gcsafe, tags: [], locks: 0.} - planeGetAnyPoint*: proc (self: Plane): Vector3 + planeGetAnyPoint*: proc (self: Plane): Vector3Data {.noconv, raises: [], gcsafe, tags: [], locks: 0.} planeIsPointOver*: proc (self: Plane, point: Vector3): bool {.noconv, raises: [], gcsafe, tags: [], locks: 0.} @@ -2389,7 +2420,7 @@ type {.noconv, raises: [], gcsafe, tags: [], locks: 0.} planeHasPoint*: proc (self: Plane, point: Vector3, epsilon: float32): bool {.noconv, raises: [], gcsafe, tags: [], locks: 0.} - planeProject*: proc (self: Plane, point: Vector3): Vector3 + planeProject*: proc (self: Plane, point: Vector3): Vector3Data {.noconv, raises: [], gcsafe, tags: [], locks: 0.} planeIntersect3*: proc (self: Plane, dest: var Vector3, b, c: Plane): bool {.noconv, raises: [], gcsafe, tags: [], locks: 0.} @@ -2400,13 +2431,13 @@ type segmentBegin, segmentEnd: Vector3): bool {.noconv, raises: [], gcsafe, tags: [], locks: 0.} - planeOperatorNeg*: proc (self: Plane): Plane + planeOperatorNeg*: proc (self: Plane): PlaneData {.noconv, raises: [], gcsafe, tags: [], locks: 0.} planeOperatorEqual*: proc (self, other: Plane): bool {.noconv, raises: [], gcsafe, tags: [], locks: 0.} planeSetNormal*: proc (self: var Plane, normal: Vector3) {.noconv, raises: [], gcsafe, tags: [], locks: 0.} - planeGetNormal*: proc (self: Plane): Vector3 + planeGetNormal*: proc (self: Plane): Vector3Data {.noconv, raises: [], gcsafe, tags: [], locks: 0.} planeGetD*: proc (self: Plane): float32 {.noconv, raises: [], gcsafe, tags: [], locks: 0.} @@ -2429,21 +2460,21 @@ type {.noconv, raises: [], gcsafe, tags: [], locks: 0.} rect2HasNoArea*: proc (self: Rect2): bool {.noconv, raises: [], gcsafe, tags: [], locks: 0.} - rect2Clip*: proc (self, other: Rect2): Rect2 + rect2Clip*: proc (self, other: Rect2): Rect2Data {.noconv, raises: [], gcsafe, tags: [], locks: 0.} - rect2Merge*: proc (self, other: Rect2): Rect2 + rect2Merge*: proc (self, other: Rect2): Rect2Data {.noconv, raises: [], gcsafe, tags: [], locks: 0.} rect2HasPoint*: proc (self: Rect2, point: Vector2): bool {.noconv, raises: [], gcsafe, tags: [], locks: 0.} - rect2Grow*: proc (self: Rect2, by: float32): Rect2 + rect2Grow*: proc (self: Rect2, by: float32): Rect2Data {.noconv, raises: [], gcsafe, tags: [], locks: 0.} - rect2Expand*: proc (self: Rect2, to: Vector2): Rect2 + rect2Expand*: proc (self: Rect2, to: Vector2): Rect2Data {.noconv, raises: [], gcsafe, tags: [], locks: 0.} rect2OperatorEqual*: proc (self, other: Rect2): bool {.noconv, raises: [], gcsafe, tags: [], locks: 0.} - rect2GetPosition*: proc (self: Rect2): Vector2 + rect2GetPosition*: proc (self: Rect2): Vector2Data {.noconv, raises: [], gcsafe, tags: [], locks: 0.} - rect2GetSize*: proc (self: Rect2): Vector2 + rect2GetSize*: proc (self: Rect2): Vector2Data {.noconv, raises: [], gcsafe, tags: [], locks: 0.} rect2SetPosition*: proc (self: var Rect2, pos: Vector2) {.noconv, raises: [], gcsafe, tags: [], locks: 0.} @@ -2453,11 +2484,11 @@ type # AABB API aabbNew*: proc (dest: var AABB, pos, size: Vector3) {.noconv, raises: [], gcsafe, tags: [], locks: 0.} - aabbGetPosition*: proc (self: AABB): Vector3 + aabbGetPosition*: proc (self: AABB): Vector3Data {.noconv, raises: [], gcsafe, tags: [], locks: 0.} aabbSetPosition*: proc (self: var AABB, pos: Vector3) {.noconv, raises: [], gcsafe, tags: [], locks: 0.} - aabbGetSize*: proc (self: AABB): Vector3 + aabbGetSize*: proc (self: AABB): Vector3Data {.noconv, raises: [], gcsafe, tags: [], locks: 0.} aabbSetSize*: proc (self: var AABB, pos: Vector3) {.noconv, raises: [], gcsafe, tags: [], locks: 0.} @@ -2473,9 +2504,9 @@ type {.noconv, raises: [], gcsafe, tags: [], locks: 0.} aabbEncloses*: proc (self, other: AABB): bool {.noconv, raises: [], gcsafe, tags: [], locks: 0.} - aabbMerge*: proc (self, other: AABB): AABB + aabbMerge*: proc (self, other: AABB): AABBData {.noconv, raises: [], gcsafe, tags: [], locks: 0.} - aabbIntersection*: proc (self, other: AABB): AABB + aabbIntersection*: proc (self, other: AABB): AABBData {.noconv, raises: [], gcsafe, tags: [], locks: 0.} aabbIntersectsPlane*: proc (self: AABB, plane: Plane): bool {.noconv, raises: [], gcsafe, tags: [], locks: 0.} @@ -2484,9 +2515,9 @@ type locks: 0.} aabbHasPoint*: proc (self: AABB, point: Vector3): bool {.noconv, raises: [], gcsafe, tags: [], locks: 0.} - aabbGetSupport*: proc (self: AABB, dir: Vector3): Vector3 + aabbGetSupport*: proc (self: AABB, dir: Vector3): Vector3Data {.noconv, raises: [], gcsafe, tags: [], locks: 0.} - aabbGetLongestAxis*: proc (self: AABB): Vector3 + aabbGetLongestAxis*: proc (self: AABB): Vector3Data {.noconv, raises: [], gcsafe, tags: [], locks: 0.} aabbGetLongestAxisIndex*: proc (self: AABB): cint {.noconv, raises: [], gcsafe, tags: [], @@ -2494,7 +2525,7 @@ type aabbGetLongestAxisSize*: proc (self: AABB): float32 {.noconv, raises: [], gcsafe, tags: [], locks: 0.} - aabbGetShortestAxis*: proc (self: AABB): Vector3 + aabbGetShortestAxis*: proc (self: AABB): Vector3Data {.noconv, raises: [], gcsafe, tags: [], locks: 0.} aabbGetShortestAxisIndex*: proc (self: AABB): cint {.noconv, raises: [], gcsafe, tags: [], @@ -2502,11 +2533,11 @@ type aabbGetShortestAxisSize*: proc (self: AABB): float32 {.noconv, raises: [], gcsafe, tags: [], locks: 0.} - aabbExpand*: proc (self: AABB, toPoint: Vector3): AABB + aabbExpand*: proc (self: AABB, toPoint: Vector3): AABBData {.noconv, raises: [], gcsafe, tags: [], locks: 0.} - aabbGrow*: proc (self: AABB, by: float32): AABB + aabbGrow*: proc (self: AABB, by: float32): AABBData {.noconv, raises: [], gcsafe, tags: [], locks: 0.} - aabbGetEndpoint*: proc (self: AABB, idx: cint): Vector3 + aabbGetEndpoint*: proc (self: AABB, idx: cint): Vector3Data {.noconv, raises: [], gcsafe, tags: [], locks: 0.} aabbOperatorEqual*: proc (self, other: AABB): bool {.noconv, raises: [], gcsafe, tags: [], locks: 0.} @@ -2530,36 +2561,36 @@ type locks: 0.} transformNew*: proc (dest: var Transform, basis: Basis, origin: Vector3) {.noconv, raises: [], gcsafe, tags: [], locks: 0.} - transformGetBasis*: proc (self: Transform): Basis + transformGetBasis*: proc (self: Transform): BasisData {.noconv, raises: [], gcsafe, tags: [], locks: 0.} transformSetBasis*: proc (self: var Transform, basis: Basis) {.noconv, raises: [], gcsafe, tags: [], locks: 0.} - transformGetOrigin*: proc (self: Transform): Vector3 + transformGetOrigin*: proc (self: Transform): Vector3Data {.noconv, raises: [], gcsafe, tags: [], locks: 0.} transformSetOrigin*: proc (self: var Transform, v: Vector3) {.noconv, raises: [], gcsafe, tags: [], locks: 0.} transformAsString*: proc (self: Transform): GodotString {.noconv, raises: [], gcsafe, tags: [], locks: 0.} - transformInverse*: proc (self: Transform): Transform + transformInverse*: proc (self: Transform): TransformData {.noconv, raises: [], gcsafe, tags: [], locks: 0.} - transformAffineInverse*: proc (self: Transform): Transform + transformAffineInverse*: proc (self: Transform): TransformData {.noconv, raises: [], gcsafe, tags: [], locks: 0.} - transformOrthonormalized*: proc (self: Transform): Transform + transformOrthonormalized*: proc (self: Transform): TransformData {.noconv, raises: [], gcsafe, tags: [], locks: 0.} transformRotated*: proc (self: Transform, axis: Vector3, - phi: float32): Transform + phi: float32): TransformData {.noconv, raises: [], gcsafe, tags: [], locks: 0.} - transformScaled*: proc (self: Transform, scale: Vector3): Transform + transformScaled*: proc (self: Transform, scale: Vector3): TransformData {.noconv, raises: [], gcsafe, tags: [], locks: 0.} - transformTranslated*: proc (self: Transform, offset: Vector3): Transform + transformTranslated*: proc (self: Transform, offset: Vector3): TransformData {.noconv, raises: [], gcsafe, tags: [], locks: 0.} - transformLookingAt*: proc (self: Transform, target, up: Vector3): Transform + transformLookingAt*: proc (self: Transform, target, up: Vector3): TransformData {.noconv, raises: [], gcsafe, tags: [], locks: 0.} - transformXformPlane*: proc (self: Transform, plane: Plane): Plane + transformXformPlane*: proc (self: Transform, plane: Plane): PlaneData {.noconv, raises: [], gcsafe, tags: [], locks: 0.} - transformXformInvPlane*: proc (self: Transform, plane: Plane): Plane + transformXformInvPlane*: proc (self: Transform, plane: Plane): PlaneData {.noconv, raises: [], gcsafe, tags: [], locks: 0.} transformNewIdentity*: proc (dest: var Transform) @@ -2567,18 +2598,18 @@ type transformOperatorEqual*: proc (self, other: Transform): bool {.noconv, raises: [], gcsafe, tags: [], locks: 0.} - transformOperatorMultiply*: proc (self, other: Transform): Transform + transformOperatorMultiply*: proc (self, other: Transform): TransformData {.noconv, raises: [], gcsafe, tags: [], locks: 0.} - transformXformVector3*: proc (self: Transform, v: Vector3): Vector3 + transformXformVector3*: proc (self: Transform, v: Vector3): Vector3Data {.noconv, raises: [], gcsafe, tags: [], locks: 0.} - transformXformInvVector3*: proc (self: Transform, v: Vector3): Vector3 + transformXformInvVector3*: proc (self: Transform, v: Vector3): Vector3Data {.noconv, raises: [], gcsafe, tags: [], locks: 0.} - transformXformAABB*: proc (self: Transform, v: AABB): AABB + transformXformAABB*: proc (self: Transform, v: AABB): AABBData {.noconv, raises: [], gcsafe, tags: [], locks: 0.} - transformXformInvAABB*: proc (self: Transform, v: AABB): AABB + transformXformInvAABB*: proc (self: Transform, v: AABB): AABBData {.noconv, raises: [], gcsafe, tags: [], locks: 0.} @@ -2591,58 +2622,58 @@ type locks: 0.} transform2DAsString*: proc (self: Transform2D): GodotString {.noconv, raises: [], gcsafe, tags: [], locks: 0.} - transform2DInverse*: proc (self: Transform2D): Transform2D + transform2DInverse*: proc (self: Transform2D): Transform2DData {.noconv, raises: [], gcsafe, tags: [], locks: 0.} - transform2DAffineInverse*: proc (self: Transform2D): Transform2D + transform2DAffineInverse*: proc (self: Transform2D): Transform2DData {.noconv, raises: [], gcsafe, tags: [], locks: 0.} transform2DGetRotation*: proc (self: Transform2D): float32 {.noconv, raises: [], gcsafe, tags: [], locks: 0.} - transform2DGetOrigin*: proc (self: Transform2D): Vector2 + transform2DGetOrigin*: proc (self: Transform2D): Vector2Data {.noconv, raises: [], gcsafe, tags: [], locks: 0.} - transform2DGetScale*: proc (self: Transform2D): Vector2 + transform2DGetScale*: proc (self: Transform2D): Vector2Data {.noconv, raises: [], gcsafe, tags: [], locks: 0.} - transform2DOrthonormalized*: proc (self: Transform2D): Transform2D + transform2DOrthonormalized*: proc (self: Transform2D): Transform2DData {.noconv, raises: [], gcsafe, tags: [], locks: 0.} - transform2DRotated*: proc (self: Transform2D, phi: float32): Transform2D + transform2DRotated*: proc (self: Transform2D, phi: float32): Transform2DData {.noconv, raises: [], gcsafe, tags: [], locks: 0.} - transform2DScaled*: proc (self: Transform2D, scale: Vector2): Transform2D + transform2DScaled*: proc (self: Transform2D, scale: Vector2): Transform2DData {.noconv, raises: [], gcsafe, tags: [], locks: 0.} - transform2DTranslated*: proc (self: Transform2D, offset: Vector2): Transform2D + transform2DTranslated*: proc (self: Transform2D, offset: Vector2): Transform2DData {.noconv, raises: [], gcsafe, tags: [], locks: 0.} - transform2DXformVector2*: proc (self: Transform2D, v: Vector2): Vector2 + transform2DXformVector2*: proc (self: Transform2D, v: Vector2): Vector2Data {.noconv, raises: [], gcsafe, tags: [], locks: 0.} - transform2DXformInvVector2*: proc (self: Transform2D, v: Vector2): Vector2 + transform2DXformInvVector2*: proc (self: Transform2D, v: Vector2): Vector2Data {.noconv, raises: [], gcsafe, tags: [], locks: 0.} - transform2DBasisXformVector2*: proc (self: Transform2D, v: Vector2): Vector2 + transform2DBasisXformVector2*: proc (self: Transform2D, v: Vector2): Vector2Data {.noconv, raises: [], gcsafe, tags: [], locks: 0.} transform2DBasisXformInvVector2*: proc (self: Transform2D, - v: Vector2): Vector2 + v: Vector2): Vector2Data {.noconv, raises: [], gcsafe, tags: [], locks: 0.} transform2DInterpolateWith*: proc (self, other: Transform2D, - t: float32): Transform2D + t: float32): Transform2DData {.noconv, raises: [], gcsafe, tags: [], locks: 0.} transform2DOperatorEqual*: proc (self, other: Transform2D): bool {.noconv, raises: [], gcsafe, tags: [], locks: 0.} - transform2DOperatorMultiply*: proc (self, other: Transform2D): Transform2D + transform2DOperatorMultiply*: proc (self, other: Transform2D): Transform2DData {.noconv, raises: [], gcsafe, tags: [], locks: 0.} transform2DNewIdentity*: proc (dest: var Transform2D) {.noconv, raises: [], gcsafe, tags: [], locks: 0.} - transform2DXformRect2*: proc (self: Transform2D, v: Rect2): Rect2 + transform2DXformRect2*: proc (self: Transform2D, v: Rect2): Rect2Data {.noconv, raises: [], gcsafe, tags: [], locks: 0.} - transform2DXformInvRect2*: proc (self: Transform2D, v: Rect2): Rect2 + transform2DXformInvRect2*: proc (self: Transform2D, v: Rect2): Rect2Data {.noconv, raises: [], gcsafe, tags: [], locks: 0.} @@ -2731,25 +2762,25 @@ type {.noconv, raises: [], gcsafe, tags: [], locks: 0.} variantAsString*: proc (self: GodotVariant): GodotString {.noconv, raises: [], gcsafe, tags: [], locks: 0.} - variantAsVector2*: proc (self: GodotVariant): Vector2 + variantAsVector2*: proc (self: GodotVariant): Vector2Data {.noconv, raises: [], gcsafe, tags: [], locks: 0.} - variantAsRect2*: proc (self: GodotVariant): Rect2 + variantAsRect2*: proc (self: GodotVariant): Rect2Data {.noconv, raises: [], gcsafe, tags: [], locks: 0.} - variantAsVector3*: proc (self: GodotVariant): Vector3 + variantAsVector3*: proc (self: GodotVariant): Vector3Data {.noconv, raises: [], gcsafe, tags: [], locks: 0.} - variantAsTransform2D*: proc (self: GodotVariant): Transform2D + variantAsTransform2D*: proc (self: GodotVariant): Transform2DData {.noconv, raises: [], gcsafe, tags: [], locks: 0.} - variantAsPlane*: proc (self: GodotVariant): Plane + variantAsPlane*: proc (self: GodotVariant): PlaneData {.noconv, raises: [], gcsafe, tags: [], locks: 0.} - variantAsQuat*: proc (self: GodotVariant): Quat + variantAsQuat*: proc (self: GodotVariant): QuatData {.noconv, raises: [], gcsafe, tags: [], locks: 0.} - variantAsAABB*: proc (self: GodotVariant): AABB + variantAsAABB*: proc (self: GodotVariant): AABBData {.noconv, raises: [], gcsafe, tags: [], locks: 0.} - variantAsBasis*: proc (self: GodotVariant): Basis + variantAsBasis*: proc (self: GodotVariant): BasisData {.noconv, raises: [], gcsafe, tags: [], locks: 0.} - variantAsTransform*: proc (self: GodotVariant): Transform + variantAsTransform*: proc (self: GodotVariant): TransformData {.noconv, raises: [], gcsafe, tags: [], locks: 0.} - variantAsColor*: proc (self: GodotVariant): Color + variantAsColor*: proc (self: GodotVariant): ColorData {.noconv, raises: [], gcsafe, tags: [], locks: 0.} variantAsNodePath*: proc (self: GodotVariant): GodotNodePath {.noconv, raises: [], gcsafe, tags: [], locks: 0.} @@ -2811,6 +2842,8 @@ type {.noconv, raises: [], gcsafe, tags: [], locks: 0.} stringNewCopy*: proc (dest: var GodotString, src: GodotString) {.noconv, raises: [], gcsafe, tags: [], locks: 0.} + stringWideStr*: proc (self: GodotString): ptr cwchar_t + {.noconv, raises: [], gcsafe, tags: [], locks: 0.} stringOperatorEqual*: proc (self, other: GodotString): bool {.noconv, raises: [], gcsafe, tags: [], locks: 0.} stringOperatorLess*: proc (self, other: GodotString): bool @@ -2895,6 +2928,38 @@ type {.noconv, raises: [], gcsafe, tags: [], locks: 0.} +{.push stackTrace: off.} +proc toColor*(val: ColorData): Color {.inline, noinit.} = + cast[Color](val) + +proc toVector3*(val: Vector3Data): Vector3 {.inline, noinit.} = + cast[Vector3](val) + +proc toVector2*(val: Vector2Data): Vector2 {.inline, noinit.} = + cast[Vector2](val) + +proc toPlane*(val: PlaneData): Plane {.inline, noinit.} = + cast[Plane](val) + +proc toBasis*(val: BasisData): Basis {.inline, noinit.} = + cast[Basis](val) + +proc toQuat*(val: QuatData): Quat {.inline, noinit.} = + cast[Quat](val) + +proc toAABB*(val: AABBData): AABB {.inline, noinit.} = + cast[AABB](val) + +proc toRect2*(val: Rect2Data): Rect2 {.inline, noinit.} = + cast[Rect2](val) + +proc toTransform2D*(val: Transform2DData): Transform2D {.inline, noinit.} = + cast[Transform2D](val) + +proc toTransform*(val: TransformData): Transform {.inline, noinit.} = + cast[Transform](val) +{.pop.} + macro assign(dest, src: typed, values: untyped): typed = result = newStmtList() for val in values: @@ -3481,6 +3546,7 @@ proc setGDNativeAPIInternal(apiStruct: pointer, initOptions: ptr GDNativeInitOpt stringNew stringNewCopy + stringWideStr stringOperatorEqual stringOperatorLess stringOperatorPlus @@ -3527,7 +3593,7 @@ proc setGDNativeAPIInternal(apiStruct: pointer, initOptions: ptr GDNativeInitOpt # Not used discard - if not header.next.isNil: + if not header.next.isNil and header != header.next: setGDNativeAPIInternal(header.next, initOptions, foundCoreApi, foundNativeScriptApi) diff --git a/godot/godot.nim b/godot/godot.nim index f4a9bf8..809f58f 100644 --- a/godot/godot.nim +++ b/godot/godot.nim @@ -1,14 +1,14 @@ # Copyright 2018 Xored Software, Inc. -import core.godotbase, godotinternal -import core.godotcoretypes -import core.vector2, core.rect2, core.vector3, core.transform2d, core.planes, - core.quats -import core.aabb, core.basis, core.transforms, core.colors, core.nodepaths, - core.rids -import core.dictionaries, core.arrays, core.poolarrays, core.variants +import core/godotbase, godotinternal +import core/godotcoretypes +import core/vector2, core/rect2, core/vector3, core/transform2d, core/planes, + core/quats +import core/aabb, core/basis, core/transforms, core/colors, core/nodepaths, + core/rids +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, quats, aabb, basis, transforms, colors, nodepaths, rids, dictionaries, diff --git a/godot/godotapigen.nim b/godot/godotapigen.nim index 7d19d8e..ccbcc6c 100644 --- a/godot/godotapigen.nim +++ b/godot/godotapigen.nim @@ -1,12 +1,31 @@ # 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 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 = - result = newNode(nkIdent) - result.ident = getIdent(ident) + result = PNode(kind: nkIdent, ident: getIdent(ident)) + +proc newPNode(kind: TNodeKind): PNode = + when (NimMajor, NimMinor, NimPatch) < (0, 19, 0): + result = newNode(kind) + else: + result = PNode(kind: kind) + result.info.fileIndex = InvalidFileIdx + result.info.col = int16(-1) + result.info.line = uint16(0) proc addChain(node: PNode, others: varargs[PNode]): PNode {.discardable.} = for other in others: @@ -15,37 +34,37 @@ proc addChain(node: PNode, others: varargs[PNode]): PNode {.discardable.} = proc newIdentDefs(name, typ: PNode, defaultVal: PNode = nil): PNode = - result = newNode(nkIdentDefs) + result = newPNode(nkIdentDefs) result.add(name) result.add(typ) if defaultVal.isNil: - result.add(newNode(nkEmpty)) + result.add(newPNode(nkEmpty)) else: 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 = - result = newNode(procType) + result = newPNode(procType) result.add(name) - result.add(newNode(nkEmpty)) - result.add(newNode(nkEmpty)) - let formalParams = newNode(nkFormalParams) + result.add(newPNode(nkEmpty)) + result.add(newPNode(nkEmpty)) + let formalParams = newPNode(nkFormalParams) for param in params: formalParams.add(param) result.add(formalParams) - result.add(newNode(nkEmpty)) - result.add(newNode(nkEmpty)) + result.add(newPNode(nkEmpty)) + result.add(newPNode(nkEmpty)) result.add(body) proc newIfStmt(condition, body: PNode): PNode = - result = newNode(nkIfStmt) - let branch = newNode(nkElifBranch) + result = newPNode(nkIfStmt) + let branch = newPNode(nkElifBranch) result.add(branch) branch.add(condition) branch.add(body) proc newCall(theProc: PNode, args: varargs[PNode]): PNode = - result = newNode(nkCall) + result = newPNode(nkCall) result.add(theProc) for arg in args: result.add(arg) @@ -54,66 +73,66 @@ proc newCall(theProc: string, args: varargs[PNode]): PNode = newCall(ident(theProc), args) proc newStrLit(s: string): PNode = - result = newNode(nkStrLit) + result = newPNode(nkStrLit) result.strVal = s proc newRStrLit(s: string): PNode = - result = newNode(nkRStrLit) + result = newPNode(nkRStrLit) result.strVal = s proc newCStringLit(s: string): PNode = - newNode(nkCallStrLit).addChain(ident("cstring"), newRStrLit(s)) + newPNode(nkCallStrLit).addChain(ident("cstring"), newRStrLit(s)) proc newIntLit(val: BiggestInt): PNode = - result = newNode(nkIntLit) + result = newPNode(nkIntLit) result.intVal = val proc newInt64Lit(val: BiggestInt): PNode = - result = newNode(nkInt64Lit) + result = newPNode(nkInt64Lit) result.intVal = val proc newFloatLit(val: BiggestFloat): PNode = - result = newNode(nkFloatLit) + result = newPNode(nkFloatLit) result.floatVal = val proc newFloat64Lit(val: BiggestFloat): PNode = - result = newNode(nkFloat64Lit) + result = newPNode(nkFloat64Lit) result.floatVal = val proc newNilLit(): PNode = - result = newNode(nkNilLit) + result = newPNode(nkNilLit) proc newDotExpr(left, right: PNode): PNode = - result = newNode(nkDotExpr) + result = newPNode(nkDotExpr) result.add(left) result.add(right) proc newCommand(left, right: PNode): PNode = - result = newNode(nkCommand) + result = newPNode(nkCommand) result.add(left) result.add(right) proc infix(left, op, right: PNode): PNode = - result = newNode(nkInfix) + result = newPNode(nkInfix) result.add(op) result.add(left) result.add(right) proc postfix(left: PNode, op: string): PNode = - result = newNode(nkPostfix) + result = newPNode(nkPostfix) result.add(ident(op)) result.add(left) proc prefix(op: string, right: PNode): PNode = - result = newNode(nkPrefix) + result = newPNode(nkPrefix) result.add(ident(op)) result.add(right) proc newBracketExpr(first, bracket: PNode): PNode = - newNode(nkBracketExpr).addChain(first, bracket) + newPNode(nkBracketExpr).addChain(first, bracket) proc newEmptyNode(): PNode = - newNode(nkEmpty) + newPNode(nkEmpty) type GodotType = ref object name: string @@ -139,19 +158,19 @@ proc findCommonRoot(typeRegistry: Table[string, GodotType], var idx = 0 while true: - var curType: string + var curType = none(string) var allEqual = true for chain in chains: if idx >= chain.len: allEqual = false break - if curType.isNil: - curType = chain[idx] - elif curType != chain[idx]: + if curType.isNone: + curType = some(chain[idx]) + elif curType.get != chain[idx]: allEqual = false break if allEqual: - result = curType + result = curType.get else: break inc idx @@ -206,42 +225,42 @@ proc toNimStyle(name: string): string = proc newRefTypeNode(typeSection: PNode, typ, base, doc: string, isExported = true) = - let typeDef = newNode(nkTypeDef) + let typeDef = newPNode(nkTypeDef) typeSection.add(typeDef) if isExported: typeDef.add(postfix(ident(typ), "*")) else: typeDef.add(ident(typ)) - typeDef.add(newNode(nkEmpty)) # generic - let objTy = newNode(nkObjectTy) - let refTy = newNode(nkRefTy) + typeDef.add(newPNode(nkEmpty)) # generic + let objTy = newPNode(nkObjectTy) + let refTy = newPNode(nkRefTy) refTy.add(objTy) typeDef.add(refTy) - objTy.add(newNode(nkEmpty)) - let inherit = newNode(nkOfInherit) + objTy.add(newPNode(nkEmpty)) + let inherit = newPNode(nkOfInherit) inherit.add(ident(base)) objTy.add(inherit) - if not doc.isNil: - let recList = newNode(nkRecList) - let docNode = newNode(nkCommentStmt) + if doc.len > 0: + let recList = newPNode(nkRecList) + let docNode = newPNode(nkCommentStmt) docNode.comment = doc recList.add(docNode) objTy.add(recList) else: - objTy.add(newNode(nkEmpty)) + objTy.add(newPNode(nkEmpty)) proc makeConstSection(constObj: JsonNode): PNode = if constObj.len == 0: - return newNode(nkEmpty) + return newPNode(nkEmpty) - result = newNode(nkConstSection) + result = newPNode(nkConstSection) for field, val in constObj: - let def = newNode(nkConstDef) + let def = newPNode(nkConstDef) def.add(postfix(ident(field), "*")) - def.add(newNode(nkEmpty)) # infer type + def.add(newPNode(nkEmpty)) # infer type var valNode: PNode if val.kind == JInt: valNode = newInt64Lit(val.num) @@ -251,7 +270,7 @@ proc makeConstSection(constObj: JsonNode): PNode = elif val.kind == JBool: valNode = ident($val.bval) elif val.kind == JString: - valNode = newNode(nkStrLit) + valNode = newPNode(nkStrLit) valNode.strVal = val.str else: raise newException(ValueError, "Unexpected constant kind: " & $val.kind) @@ -275,40 +294,47 @@ type godotName: string typ: GodotType args: seq[MethodArg] - returnType: string + returnType: Option[string] isVirtual: bool isBase: bool isDiscardable: bool -const standardTypes = toSet( +const standardTypes = toHashSet( ["bool", "cint", "int", "uint8", "int8", "uint16", "int16", "uint32", "int32", - "uint64", + "uint64", "Error", "int64", "float32", "cfloat", "float64", "GodotString", "Vector2", "Rect2", "Vector3", "Transform2D", "Plane", "Quat", "AABB", "Basis", "Transform", "Color", "RID", "NodePath", "Dictionary", "Variant", "Array", "PoolByteArray", "PoolIntArray", "PoolRealArray", "PoolStringArray", "PoolVector2Array", "PoolVector3Array", "PoolColorArray"]) -const smallIntTypes = toSet(["uint8", "int8", "uint16", "int16", "uint32", - "int32", "cint", "int", "Error"]) -const int64Types = toSet(["uint64", "int64"]) +const variantPrimitives = [ + "bool", "cint", "int", "uint8", "int8", "uint16", "int16", "uint32", "int32", + "uint64", "Error", + "int64", "float32", "cfloat", "float64", "GodotString", "Vector2", "Rect2", + "Vector3", "Transform2D", "Plane", "Quat", "AABB", "Basis", "Transform", + "Color", "RID"] + +const smallIntTypes = toHashSet(["uint8", "int8", "uint16", "int16", "uint32", + "int32", "cint", "int", "Error"]) +const int64Types = toHashSet(["uint64", "int64"]) const intTypes = union(smallIntTypes, int64Types) -const float64Types = toSet(["float64", "cdouble"]) -const float32Types = toSet(["float32", "cfloat"]) +const float64Types = toHashSet(["float64", "cdouble"]) +const float32Types = toHashSet(["float32", "cfloat"]) const floatTypes = union(float64Types, float32Types) -const arrayTypes = toSet(["Array", "PoolByteArray", +const arrayTypes = toHashSet(["Array", "PoolByteArray", "PoolIntArray", "PoolRealArray", "PoolStringArray", "PoolVector2Array", "PoolVector3Array", "PoolColorArray"]) const wrapperTypes = union(arrayTypes, - toSet(["NodePath", "Dictionary", "Variant"])) + toHashSet(["NodePath", "Dictionary", "Variant"])) proc getInternalPtr(varName: PNode, typ: string): PNode = - assert(typ in wrapperTypes) + assert(typ in wrapperTypes or typ == "Object") result = newDotExpr(varName, ident("godot" & typ)) proc newNilCheck(ident, toAssign: PNode): PNode = newIfStmt(newCall("isNil", ident), - newNode(nkAsgn).addChain(ident).addChain( + newPNode(nkAsgn).addChain(ident).addChain( toAssign ) ) @@ -319,6 +345,7 @@ proc singletonName(typ: string): PNode = proc makeDefaultValue(arg: MethodArg): PNode = result = newEmptyNode() if not arg.defaultVal.isNil: + var failed = false if arg.typ == "bool": result = ident(arg.defaultVal.str.toLowerAscii()) elif arg.typ in intTypes: @@ -335,15 +362,15 @@ proc makeDefaultValue(arg: MethodArg): PNode = elif arg.typ == "Color": result = newCall("initColor", arg.defaultVal.str.split(',').mapIt(newFloatLit(parseFloat(it)))) - # elif arg.typ in arrayTypes and (arg.defaultVal.str == "[]" or - # arg.defaultVal.str == "[" & arg.typ & "]"): - # result = newCall("init" & arg.typ) elif arg.typ == "RID" and arg.defaultVal.str == "[RID]": result = newCall("initRID") + elif arg.typ in arrayTypes and (arg.defaultVal.str == "[]" or + arg.defaultVal.str == "[" & arg.typ & "]"): + result = newCall("new" & arg.typ) elif arg.typ == "Vector2" or arg.typ == "Vector3" or arg.typ == "Rect2": let parts = arg.defaultVal.str.replace("(", "").replace(")", ""). replace(" ", ""). - split(",").mapIt(newFloatLit(parseFloat(it))) + split(',').mapIt(newFloatLit(parseFloat(it))) if arg.typ.endsWith("r2"): result = newCall("vec2", parts) elif arg.typ.endsWith('3'): @@ -352,11 +379,43 @@ proc makeDefaultValue(arg: MethodArg): PNode = result = newCall("initRect2", parts) elif arg.defaultVal.str == "[Object:null]": result = newNilLit() - elif arg.typ != "Transform" and arg.typ != "Transform2D" and - arg.typ != "Variant" and arg.typ notin arrayTypes: # TODO + elif arg.typ == "Transform": + let transformParts = arg.defaultVal.str.replace(" ", "").split('-') + doAssert(transformParts.len == 2) + let basisParts = transformParts[0].split(',').mapIt( + newFloatLit(parseFloat(it))) + let originParts = transformParts[1].split(',').mapIt( + newFloatLit(parseFloat(it))) + let basis = newCall("initBasis", basisParts) + let origin = newCall("vec3", originParts) + result = newCall("initTransform", basis, origin) + elif arg.typ == "Transform2D": + let parts = arg.defaultVal.str. + replace(" ", ""). + replace(")", ""). + replace("(", ""). + split(',').mapIt(newFloatLit(parseFloat(it))) + doAssert(parts.len == 6) + let xAxis = newCall("vec2", parts[0..1]) + let yAxis = newCall("vec2", parts[2..3]) + let origin = newCall("vec2", parts[4..5]) + result = newCall("initTransform2D", xAxis, yAxis, origin) + elif arg.typ == "Variant": + if arg.defaultVal.str == "0": + result = newCall("newVariant", newIntLit(0)) + elif arg.defaultVal.str == "Null": + result = newCall("newVariant") + else: + failed = true + elif arg.typ == "Dictionary": + result = newCall("newDictionary") + else: + failed = true + + if failed: raise newException( ValueError, - "Cannot build default value from $# ($#)" % + "Cannot build default value from \"$#\" ($#) - please report this at https://github.com/pragmagic/godot-nim/issues" % [$arg.defaultVal, arg.typ]) proc boundArgName(idx: int): string = @@ -366,12 +425,12 @@ proc doGenerateMethod(tree: PNode, methodBindRegistry: var HashSet[string], meth: MethodInfo, withImplementation: bool) = var body: PNode if not withImplementation: - body = newNode(nkEmpty) + body = newPNode(nkEmpty) elif meth.godotName == "_init" and meth.typ.godotName == "Object": # It's not real (calling it crashes) and will be removed later, # but we use init() convention in Nim, so it needs to work. - body = newNode(nkStmtList).addChain( - newNode(nkDiscardStmt).addChain(newNode(nkEmpty))) + body = newPNode(nkStmtList).addChain( + newPNode(nkDiscardStmt).addChain(newPNode(nkEmpty))) else: let methGodotName = if meth.godotName.startsWith('_'): "underscore" & meth.godotName[1..^1] @@ -382,12 +441,12 @@ proc doGenerateMethod(tree: PNode, methodBindRegistry: var HashSet[string], if methodBindName[0].isUpperAscii(): methodBindName[0] = methodBindName[0].toLowerAscii() if methodBindName notin methodBindRegistry: - let methodBindDecl = newNode(nkVarSection).addChain( + let methodBindDecl = newPNode(nkVarSection).addChain( newIdentDefs( - newNode(nkPragmaExpr).addChain( + newPNode(nkPragmaExpr).addChain( ident(methodBindName)).addChain( - newNode(nkPragma).addChain(ident("threadvar"))), - newNode(nkPtrTy).addChain(ident("GodotMethodBind")) + newPNode(nkPragma).addChain(ident("threadvar"))), + newPNode(nkPtrTy).addChain(ident("GodotMethodBind")) )) tree.add(methodBindDecl) methodBindRegistry.incl(methodBindName) @@ -396,8 +455,8 @@ proc doGenerateMethod(tree: PNode, methodBindRegistry: var HashSet[string], newCall("getMethod", newCStringLit(meth.typ.godotName), newCStringLit(meth.godotName)) ) - let vars = newNode(nkVarSection) - var varargsName: string + let vars = newPNode(nkVarSection) + var varargsName = none(string) var isVarargs: bool var staticArgsLen: int var argLenNode = newIntLit(0) @@ -405,75 +464,114 @@ proc doGenerateMethod(tree: PNode, methodBindRegistry: var HashSet[string], if meth.args.len > 0: for idx, arg in meth.args: if arg.kind == ArgKind.VarArgs: - varargsName = arg.name + varargsName = some(arg.name) isVarargs = true vars.add(newIdentDefs(ident("callError"), ident("VariantCallError"))) elif arg.kind == ArgKind.Bound: let argName = boundArgName(idx) vars.add(newIdentDefs( - ident(argName), newNode(nkEmpty), arg.makeDefaultValue())) + ident(argName), newPNode(nkEmpty), arg.makeDefaultValue())) - let argsAlloc = newNode(nkCast).addChain( - newNode(nkPtrTy).addChain( - newNode(nkBracketExpr).addChain( + let argsAlloc = newPNode(nkCast).addChain( + newPNode(nkPtrTy).addChain( + newPNode(nkBracketExpr).addChain( ident("array"), ident("MAX_ARG_COUNT"), - if isVarargs: newNode(nkPtrTy).addChain(ident("GodotVariant")) + if isVarargs: newPNode(nkPtrTy).addChain(ident("GodotVariant")) else: ident("pointer")))) - staticArgsLen = if varargsName.isNil: meth.args.len + staticArgsLen = if varargsName.isNone: meth.args.len else: meth.args.len - 1 - if not varargsName.isNil: + if varargsName.isSome: argLenNode = newCall("cint", infix(newIntLit(staticArgsLen), ident("+"), - newDotExpr(ident(varargsName), ident("len")))) + newDotExpr(ident(varargsName.get), ident("len")))) argsAlloc.add(newCall("godotAlloc", newCall("cint", infix( - newCall("sizeof", ident("Variant")), ident("*"), - newNode(nkPar).addChain(argLenNode)))) + newCall("sizeof", newPNode(nkPtrTy).addChain(ident("GodotVariant"))), ident("*"), + newPNode(nkPar).addChain(argLenNode)))) ) else: argLenNode = newCall("cint", newIntLit(staticArgsLen)) vars.add(newIdentDefs( ident("argsStatic"), - newNode(nkBracketExpr).addChain( + newPNode(nkBracketExpr).addChain( ident("array"), newIntLit(staticArgsLen), ident("pointer")), - newNode(nkEmpty))) + newPNode(nkEmpty))) 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: var argName = if arg.kind == ArgKind.Bound: ident(boundArgName(idx)) else: ident(arg.name) if arg.kind == ArgKind.VarArgs: - argName = newNode(nkBracketExpr).addChain( - ident(varargsName), + argName = newPNode(nkBracketExpr).addChain( + ident(varargsName.get), infix(ident("idx"), ident("-"), newIntLit(staticArgsLen))) let argIdx = if arg.kind == ArgKind.VarArgs: ident("idx") else: newIntLit(idx) let isStandardType = arg.typ in standardTypes let isWrappedType = arg.typ in wrapperTypes - let convArg = if not varargsName.isNil: - getInternalPtr(newCall("toVariant", argName), "Variant") - 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 + let convArg = + if varargsName.isSome: + let isAlreadyVariant = arg.typ == "Variant" + let variantIdent = if isAlreadyVariant: getInternalPtr(argName, "Variant") + else: ident("variant" & $idx) + if not isAlreadyVariant: + argConversions.add(newPNode(nkVarSection).addChain( + newIdentDefs(variantIdent, ident("GodotVariant"), newEmptyNode()) + )) + destructors.add( + newCall("deinit", variantIdent) + ) + if arg.typ in variantPrimitives: + argConversions.add( + newCall("initGodotVariant", variantIdent, argName) + ) + elif arg.typ in wrapperTypes or arg.typ == "Object": + argConversions.add( + newCall("initGodotVariant", variantIdent, getInternalPtr(argName, arg.typ)) + ) + elif arg.typ == "string": + let stringIdent = ident("variantString" & $idx) + argConversions.addChain( + newPNode(nkVarSection).addChain( + newIdentDefs(stringIdent, ident("GodotString"), newCall("toGodotString", argName)) + ) + ).addChain( + newCall("initGodotVariant", variantIdent, stringIdent) + ) + destructors.add(newCall("deinit", stringIdent)) + else: + raise newException(ValueError, + "Non-standard type $# for varargs params of method $# of type $#" % + [arg.typ, meth.godotName, meth.typ.godotName]) + + if isAlreadyVariant: variantIdent + else: newCall("addr", variantIdent) + elif isWrappedType: getInternalPtr(argName, arg.typ) + elif isStandardType: newCall("unsafeAddr", argName) + elif arg.typ == "string": newCall("unsafeAddr", + ident("argToPassToGodot" & $idx)) + else: ident("argToPassToGodot" & $idx) # object if not isStandardType and arg.kind == ArgKind.VarArgs: raise newException(ValueError, "Non-standard type $# for varargs params of method $# of type $#" % [arg.typ, meth.godotName, meth.typ.godotName]) - if not isStandardType and varargsName.isNil: + if not isStandardType and varargsName.isNone: if arg.typ == "string": - argConversions.add(newNode(nkVarSection).addChain( + argConversions.add(newPNode(nkVarSection).addChain( newIdentDefs(ident("argToPassToGodot" & $idx), newEmptyNode(), newCall("toGodotString", argName)))) else: - argConversions.add(newNode(nkLetSection).addChain( - newIdentDefs(ident("argToPassToGodot" & $idx), newEmptyNode(), - newDotExpr(argName, ident("godotObject"))))) - let argAsgn = newNode(nkAsgn).addChain( - newNode(nkBracketExpr).addChain( - newNode(nkBracketExpr).addChain(argsName), argIdx), + let objVal = newIfStmt( + prefix("not", newDotExpr(argName, ident"isNil")), + newDotExpr(argName, ident("godotObject")) + ).addChain(newPNode(nkElse).addChain(newNilLit())) + argConversions.add(newPNode(nkLetSection).addChain( + newIdentDefs(ident("argToPassToGodot" & $idx), newEmptyNode(), objVal))) + let argAsgn = newPNode(nkAsgn).addChain( + newPNode(nkBracketExpr).addChain( + newPNode(nkBracketExpr).addChain(argsName), argIdx), convArg ) if arg.kind != ArgKind.VarArgs: @@ -481,14 +579,14 @@ proc doGenerateMethod(tree: PNode, methodBindRegistry: var HashSet[string], argAsgn ) else: - argConversions.add(newNode(nkVarSection).addChain( - newIdentDefs(ident("idx"), newNode(nkEmpty), + argConversions.add(newPNode(nkVarSection).addChain( + newIdentDefs(ident("idx"), newPNode(nkEmpty), newIntLit(staticArgsLen)))) - let argLoop = newNode(nkWhileStmt) + let argLoop = newPNode(nkWhileStmt) argConversions.add(argLoop) argLoop.add(infix(ident("idx"), ident("<"), argLenNode) ) - argLoop.add(newNode(nkStmtList).addChain( + argLoop.add(newPNode(nkStmtList).addChain( argAsgn, newCommand(ident("inc"), ident("idx")))) @@ -497,26 +595,26 @@ proc doGenerateMethod(tree: PNode, methodBindRegistry: var HashSet[string], newDotExpr(ident(methodBindName), ident(if isVarargs: "call" else: "ptrCall")), newDotExpr(ident("self"), ident("godotObject")), - if meth.args.len > 0: argsName else: newNode(nkNilLit), + if meth.args.len > 0: argsName else: newPNode(nkNilLit), argLenNode, if not isVarargs: ident(retName) else: ident("callError") ) if not isVarargs: theCall.sons.delete(3) let freeCall = newCall("godotFree", argsName) - body = newNode(nkStmtList) + body = newPNode(nkStmtList) if meth.typ.isSingleton: let varName = singletonName(meth.typ.name) body.add(newNilCheck(varName, newCall( newBracketExpr(ident("getSingleton"), ident(meth.typ.name))))) - body.add(newNode(nkLetSection).addChain(newIdentDefs( - ident("self"), newNode(nkEmpty), varName + body.add(newPNode(nkLetSection).addChain(newIdentDefs( + ident("self"), newPNode(nkEmpty), varName ))) body.add(nilCheck) body.add(vars) body.add(argConversions) if not isVarargs: - let retPtrDecl = newNode(nkVarSection).addChain( + let retPtrDecl = newPNode(nkVarSection).addChain( newIdentDefs(ident(retName), ident("pointer"), newEmptyNode()) ) body.add(retPtrDecl) @@ -526,105 +624,109 @@ proc doGenerateMethod(tree: PNode, methodBindRegistry: var HashSet[string], var isStringRet: bool var isWrapperRet: bool 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) - if meth.returnType in smallIntTypes: + if returnType in smallIntTypes: isConversionRet = true - body.add(newNode(nkVarSection).addChain(newIdentDefs( + body.add(newPNode(nkVarSection).addChain(newIdentDefs( retValIdent, ident("int64"), ))) - elif meth.returnType in float32Types: + elif returnType in float32Types: isConversionRet = true - body.add(newNode(nkVarSection).addChain(newIdentDefs( + body.add(newPNode(nkVarSection).addChain(newIdentDefs( retValIdent, ident("float64"), ))) - elif meth.returnType in wrapperTypes: + elif returnType in wrapperTypes: isWrapperRet = true - body.add(newNode(nkVarSection).addChain(newIdentDefs( - retValIdent, ident("Godot" & meth.returnType), + body.add(newPNode(nkVarSection).addChain(newIdentDefs( + 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")) - elif meth.returnType == "string": + elif returnType == "string": isStringRet = true - body.add(newNode(nkVarSection).addChain(newIdentDefs( + body.add(newPNode(nkVarSection).addChain(newIdentDefs( retValIdent, ident("GodotString"), ))) - elif meth.returnType != "void": + elif returnType != "void": isObjRet = true - body.add(newNode(nkVarSection).addChain(newIdentDefs( - retValIdent, newNode(nkPtrTy).addChain(ident("GodotObject")), + body.add(newPNode(nkVarSection).addChain(newIdentDefs( + 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: body.add(theCall) else: - if not meth.returnType.isNil: + if meth.returnType.isSome: isVariantRet = true - let callStmt = newNode(nkLetSection).addChain( + let callStmt = newPNode(nkLetSection).addChain( newIdentDefs( - newNode(nkPragmaExpr).addChain( - ident(retName), newNode(nkPragma).addChain(ident("used"))), - newNode(nkEmpty), theCall)) + newPNode(nkPragmaExpr).addChain( + ident(retName), newPNode(nkPragma).addChain(ident("used"))), + newPNode(nkEmpty), theCall)) body.add(callStmt) - if varargsName.isNil: + if varargsName.isNone: for idx, arg in meth.args: if arg.typ == "string": body.add(newCall("deinit", ident("argToPassToGodot" & $idx))) - if meth.args.len > 0 and not varargsName.isNil: - body.add(freeCall) - if not varargsName.isNil: + if varargsName.isSome: + if meth.args.len > 0: + body.add(freeCall) + body.add(destructors) let errCheck = newIfStmt( infix(newDotExpr(ident("callError"), ident("error")), ident("!="), newDotExpr(ident("VariantCallErrorType"), ident("OK"))), - newNode(nkRaiseStmt).addChain( + newPNode(nkRaiseStmt).addChain( newCall("newCallError", ident("callError"))) ) body.add(errCheck) if isVariantRet: - let convErrDef = newNode(nkLetSection).addChain( - newIdentDefs(ident("convErr"), newNode(nkEmpty), + let convErrDef = newPNode(nkLetSection).addChain( + newIdentDefs(ident("convErr"), newPNode(nkEmpty), newCall("fromVariant", ident("result"), newCall("newVariant", retValIdent)))) let convCheck = newIfStmt( infix(ident("convErr"), ident("!="), newDotExpr(ident("ConversionResult"), ident("OK"))), - newNode(nkRaiseStmt).addChain( + newPNode(nkRaiseStmt).addChain( newCall("newConversionError", ident("convErr"))) ) body.add(convErrDef) body.add(convCheck) if isStringRet: - body.add(newNode(nkAsgn).addChain( + body.add(newPNode(nkAsgn).addChain( ident("result"), prefix("$", retValIdent))) body.add(newCall("deinit", retValIdent)) elif isConversionRet: - body.add(newNode(nkAsgn).addChain( + body.add(newPNode(nkAsgn).addChain( ident("result"), - newCall(meth.returnType, retValIdent))) + newCall(meth.returnType.get, retValIdent))) elif isWrapperRet: - body.add(newNode(nkAsgn).addChain( + body.add(newPNode(nkAsgn).addChain( ident("result"), - newCall("new" & meth.returnType, retValIdent))) + newCall("new" & meth.returnType.get, retValIdent))) elif isObjRet: - body.add(newNode(nkAsgn).addChain(ident("result"), + body.add(newPNode(nkAsgn).addChain(ident("result"), newCall(newBracketExpr(ident("asNimGodotObject"), newCall("type", ident("result"))), retValIdent, ident("false"), ident("true")))) elif isStringRet: - body.add(newNode(nkAsgn).addChain(ident("result"), + body.add(newPNode(nkAsgn).addChain(ident("result"), newCall("$", retValIdent))) let procType = if meth.isVirtual: nkMethodDef else: nkProcDef var params = newSeqOfCap[PNode](meth.args.len + 2) - if not meth.returnType.isNil: - params.add(ident(meth.returnType)) + if meth.returnType.isSome: + params.add(ident(meth.returnType.get)) else: - params.add(newNode(nkEmpty)) + params.add(newPNode(nkEmpty)) if not meth.typ.isSingleton: 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)) of ArgKind.VarArgs: 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: discard @@ -643,14 +745,14 @@ proc doGenerateMethod(tree: PNode, methodBindRegistry: var HashSet[string], else: meth.name, params, body, procType) if not withImplementation: - let pragma = newNode(nkPragma) + let pragma = newPNode(nkPragma) pragma.add(ident("gcsafe")) - pragma.add(newNode(nkExprColonExpr).addChain(ident("locks"), + pragma.add(newPNode(nkExprColonExpr).addChain(ident("locks"), newIntLit(0))) if meth.isVirtual and meth.isBase and meth.typ.name != "PhysicsBody": # Nim doesn't like `base` on PhysicsBody methods - wtf pragma.add(ident("base")) - if meth.isDiscardable and not meth.returnType.isNil: + if meth.isDiscardable and meth.returnType.isSome: pragma.add(ident("discardable")) procDecl.sons[4] = pragma tree.add(procDecl) @@ -695,9 +797,9 @@ proc getMethodInfo(methodObj: JsonNode, types: Table[string, GodotType], nimName = nimName & "Impl" let returnType = if methodObj["return_type"].str != "void": - toNimType(types, methodObj["return_type"].str) - else: nil - const discardableMethods = toSet(["emit_signal"]) + some(toNimType(types, methodObj["return_type"].str)) + else: none(string) + const discardableMethods = toHashSet(["emit_signal"]) result = MethodInfo( name: ident(nimName), typ: typ, @@ -719,19 +821,24 @@ proc makeProperty(types: Table[string, GodotType], tree: PNode, methodBindRegistry: var HashSet[string], typ: GodotType, propertyObj: JsonNode, obj: JsonNode, withImplementation: bool) = + for meth in obj["methods"]: + if meth["name"].str == '_' & propertyObj["name"].str: + # Don't generate properties if there is a name clash - otherwise + # using the property would not compile due to ambiguity. + return let getterNameStr = toNimStyle(propertyObj["name"].str) let getterName = ident(getterNameStr) - let setterName = newNode(nkAccQuoted).addChain(ident(getterNameStr & "=")) + let setterName = newPNode(nkAccQuoted).addChain(ident(getterNameStr & "=")) let getter = findMethod(obj, propertyObj["getter"].str) let nimType = if getter.isNil: toNimType(types, propertyObj["type"].str) - else: getMethodInfo(getter, types, typ).returnType + else: getMethodInfo(getter, types, typ).returnType.get("void") let getterInfo = MethodInfo( name: getterName, typ: typ, godotName: propertyObj["getter"].str, - args: @[], - returnType: nimType + args: newSeq[MethodArg](), + returnType: some(nimType) ) let setterInfo = MethodInfo( name: setterName, @@ -740,10 +847,12 @@ proc makeProperty(types: Table[string, GodotType], tree: PNode, args: @[MethodArg(name: "val", typ: nimType)] ) if "index" in propertyObj and propertyObj["index"] != newJInt(-1): - getterInfo.args = @[MethodArg(defaultVal: newJString($propertyObj["index"]), - typ: "int", kind: ArgKind.Bound)] & getterInfo.args - setterInfo.args = @[MethodArg(defaultVal: newJString($propertyObj["index"]), - typ: "int", kind: ArgKind.Bound)] & setterInfo.args + getterInfo.args = + @[MethodArg(defaultVal: newJString($propertyObj["index"]), + typ: "int", kind: ArgKind.Bound)] & getterInfo.args + setterInfo.args = + @[MethodArg(defaultVal: newJString($propertyObj["index"]), + typ: "int", kind: ArgKind.Bound)] & setterInfo.args generateMethod(tree, methodBindRegistry, getterInfo, withImplementation) generateMethod(tree, methodBindRegistry, setterInfo, withImplementation) @@ -757,8 +866,14 @@ proc makeMethod(types: Table[string, GodotType], tree: PNode, # supposed to be used on an object (have at least 2 params). for prop in typ.jsonNode["properties"]: if prop["getter"].str == methodObj["name"].str or - prop["setter"].str == methodObj["name"].str: - return + prop["setter"].str == methodObj["name"].str: + var hasDuplicateMethod = false + for meth in typ.jsonNode["methods"]: + if meth["name"].str == '_' & prop["name"].str: + hasDuplicateMethod = true + break + if not hasDuplicateMethod: + return let methodInfo = getMethodInfo(methodObj, types, typ) @@ -794,15 +909,15 @@ proc typeNameToModuleName(name: string): string = proc newRegisterClassNode(typ: GodotType): PNode = newCall("registerClass", ident(typ.name), - newCStringLit(typ.godotName), + newStrLit(typ.godotName), ident("true") # isNative ) proc genSingletonDecl(typ: string): PNode = - result = newNode(nkVarSection) + result = newPNode(nkVarSection) let name = singletonName(typ) - let threadvar = newNode(nkPragma).addChain(ident("threadvar")) - result.add(newIdentDefs(newNode(nkPragmaExpr).addChain(name, threadvar), + let threadvar = newPNode(nkPragma).addChain(ident("threadvar")) + result.add(newIdentDefs(newPNode(nkPragmaExpr).addChain(name, threadvar), ident(typ))) proc shouldExport(typ: GodotType, types: Table[string, GodotType]): bool = @@ -819,9 +934,9 @@ proc sortByDerivedCount(types: Table[string, GodotType]): seq[GodotType] = proc genTypeFile(types: Table[string, GodotType], targetDir: string) = let sortedTypes = sortByDerivedCount(types) - let godotApiTypesTree = newNode(nkStmtList) - godotApiTypesTree.add(newNode(nkImportStmt).addChain(ident("godot"))) - let typeSection = newNode(nkTypeSection) + let godotApiTypesTree = newPNode(nkStmtList) + godotApiTypesTree.add(newPNode(nkImportStmt).addChain(ident("godot"))) + let typeSection = newPNode(nkTypeSection) godotApiTypesTree.add(typeSection) for typ in sortedTypes: @@ -832,7 +947,7 @@ proc genTypeFile(types: Table[string, GodotType], targetDir: string) = if not typ.shouldExport(types): continue let regNode = newCall("registerClass", ident(typ.name), - newCStringLit(typ.godotName), + newStrLit(typ.godotName), ident("true") # isNative ) godotApiTypesTree.add(regNode) @@ -843,10 +958,10 @@ proc genSingletonWithDerived(tree: PNode, typ: GodotType, types: Table[string, GodotType]) = let sortedTypes = sortByDerivedCount(types) - var parents = initSet[string]() + var parents = initHashSet[string]() parents.incl(typ.name) - let typeDecl = newNode(nkTypeSection) + let typeDecl = newPNode(nkTypeSection) tree.add(typeDecl) proc genDecl(typ: GodotType) = newRefTypeNode(typeDecl, typ.name, typ.baseName, typ.doc, @@ -875,7 +990,7 @@ proc genApi*(targetDir: string, apiJsonFile: string) = let className = godotClassName.replace("_", "") var baseClassName = obj["base_class"].str baseClassName = toNimType(baseClassName.replace("_", "")) - if baseClassName.isNil or baseClassName.len == 0: + if baseClassName.len == 0: baseClassName = "NimGodotObject" var doc = "" for attr in classAttributes: @@ -896,17 +1011,17 @@ proc genApi*(targetDir: string, apiJsonFile: string) = for typ in types.values(): let moduleName = typeNameToModuleName(typ.name) echo "Generating ", moduleName, ".nim..." - let tree = newNode(nkStmtList) - let importStmt = newNode(nkImportStmt) + let tree = newPNode(nkStmtList) + let importStmt = newPNode(nkImportStmt) importStmt.add(ident("godot")) importStmt.add(ident("godottypes")) importStmt.add(ident("godotinternal")) tree.add(importStmt) - let exportStmt = newNode(nkExportStmt) + let exportStmt = newPNode(nkExportStmt) exportStmt.add(ident("godottypes")) tree.add(exportStmt) - var methodBindRegsitry = initSet[string]() + var methodBindRegsitry = initHashSet[string]() let obj = typ.jsonNode if typ.baseName != "NimGodotObject": let baseModule = typeNameToModuleName(typ.baseName) @@ -967,7 +1082,6 @@ when isMainModule: import os const usage = """Tool for wrapping Godot API into Nim - godotapigen [godot binary path] [target directory]""" proc main() = @@ -998,4 +1112,4 @@ when isMainModule: genApi(targetDir, jsonFile) - main() + main() \ No newline at end of file diff --git a/godot/godotinternal.nim b/godot/godotinternal.nim index 0314624..207d76f 100644 --- a/godot/godotinternal.nim +++ b/godot/godotinternal.nim @@ -1,8 +1,8 @@ # Copyright 2018 Xored Software, Inc. -import internal.godotinternaltypes, internal.godotarrays, - internal.godotnodepaths, internal.godotpoolarrays, internal.godotstrings, - internal.godotvariants, internal.godotdictionaries +import internal/godotinternaltypes, internal/godotarrays, + internal/godotnodepaths, internal/godotpoolarrays, internal/godotstrings, + internal/godotvariants, internal/godotdictionaries import gdnativeapi export godotinternaltypes, godotarrays, godotnodepaths, godotpoolarrays, @@ -93,6 +93,11 @@ proc getClassName*(o: ptr GodotObject): string = # There are physics type not known by ClassDB result = result[0..result.len-3] +proc getClassNameRaw*(o: ptr GodotObject): GodotString = + if getClassMethodBind.isNil: + getClassMethodBind = getMethod(cstring"Object", cstring"get_class") + getClassMethodBind.ptrCall(o, nil, addr result) + proc getGodotSingleton*(name: cstring): ptr GodotObject {.inline.} = getGDNativeAPI().globalGetSingleton(name) diff --git a/godot/internal/backwardcompat.inc.nim b/godot/internal/backwardcompat.inc.nim new file mode 100644 index 0000000..9d31844 --- /dev/null +++ b/godot/internal/backwardcompat.inc.nim @@ -0,0 +1,19 @@ +# Copyright 2019 Xored Software, Inc. + +when (NimMajor, NimMinor, NimPatch) < (0, 19, 0): + import macros, sets + + proc strVal(n: NimNode): string {.used.} = + case n.kind + of nnkIdent: + $n.ident + of nnkSym: + $n.symbol + else: + macros.strVal(n) + + proc toHashSet[A](keys: openArray[A]): HashSet[A] {.inline, used.} = + toSet(keys) + + proc initHashSet[A](): HashSet[A] {.inline, used.} = + initSet[A]() diff --git a/godot/internal/godotarrays.nim b/godot/internal/godotarrays.nim index c0736b5..c7e451d 100644 --- a/godot/internal/godotarrays.nim +++ b/godot/internal/godotarrays.nim @@ -1,6 +1,6 @@ # Copyright (c) 2018 Xored Software, Inc. -import godotinternaltypes, gdnativeapi, core.godotcoretypes +import godotinternaltypes, gdnativeapi, core/godotcoretypes proc len*(self: GodotArray): cint {.inline.} = getGDNativeAPI().arraySize(self) diff --git a/godot/internal/godotinternaltypes.nim b/godot/internal/godotinternaltypes.nim index 192b6cd..a2910c9 100644 --- a/godot/internal/godotinternaltypes.nim +++ b/godot/internal/godotinternaltypes.nim @@ -66,6 +66,8 @@ type GodotString* {.byref.} = object data: array[sizeof(int), byte] + cwchar_t* {.importc: "wchar_t", nodecl.} = object + GodotCharString* {.byref.} = object data: array[sizeof(int), byte] @@ -114,7 +116,8 @@ type expected*: VariantType GodotVariant* {.byref.} = object - data: array[4 + sizeof(int) div 4, float32] + data: array[2, int64] + data2: int type GodotMethodBind* = object @@ -305,3 +308,6 @@ type GodotClassConstructor* = proc (): ptr GodotObject {. noconv, gcsafe, locks: 0, raises: [], tags: [].} + +template offset*[T](p: ptr T, offset: int): ptr T = + cast[ptr T](cast[ByteAddress](p) +% (offset * sizeof(T))) \ No newline at end of file diff --git a/godot/internal/godotpoolarrays.nim b/godot/internal/godotpoolarrays.nim index fb80ad0..119848f 100644 --- a/godot/internal/godotpoolarrays.nim +++ b/godot/internal/godotpoolarrays.nim @@ -1,10 +1,7 @@ # Copyright (c) 2018 Xored Software, Inc. import godotinternaltypes, gdnativeapi -import core.godotcoretypes - -proc offset[T](p: ptr T, offset: int): ptr T {.inline.} = - cast[ptr T](cast[ByteAddress](p) +% (offset * sizeof(T))) +import core/godotcoretypes template genPoolArrayAPI(ArrayT, initIdent, DataT, newProc, newCopyProc, newWithArrayProc, appendProc, @@ -48,7 +45,15 @@ template genPoolArrayAPI(ArrayT, initIdent, DataT, getGDNativeAPI().setProc(self, idx, data) 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.} = getGDNativeAPI().sizeProc(self) diff --git a/godot/internal/godotstrings.nim b/godot/internal/godotstrings.nim index d3eb287..e67acfd 100644 --- a/godot/internal/godotstrings.nim +++ b/godot/internal/godotstrings.nim @@ -22,6 +22,12 @@ proc `&`*(self, b: GodotString): GodotString {.inline.} = proc deinit*(self: var GodotString) {.inline.} = getGDNativeAPI().stringDestroy(self) +proc len*(self: GodotString): cint {.inline.} = + getGDNativeAPI().stringLength(self) + +proc dataPtr*(self: GodotString): ptr cwchar_t {.inline.} = + getGDNativeAPI().stringWideStr(self) + proc `$`*(self: GodotString): string = ## Converts the ``GodotString`` into Nim string var charStr = getGDNativeAPI().stringUtf8(self) @@ -29,14 +35,16 @@ proc `$`*(self: GodotString): string = result = newString(length) copyMem(addr result[0], getGDNativeAPI().charStringGetData(charStr), length) getGDNativeAPI().charStringDestroy(charStr) - assert(result[length] == '\0') proc toGodotString*(s: string): GodotString {.inline.} = ## Converts the Nim string into ``GodotString`` - if s.isNil: - initGodotString(result) + when (NimMajor, NimMinor, NimPatch) < (0, 19, 0): + if s.isNil: + initGodotString(result) + else: + initGodotString(result, cstring(s), cint(s.len + 1)) else: - initGodotString(result, unsafeAddr s[0], cint(s.len + 1)) + initGodotString(result, cstring(s), cint(s.len + 1)) proc toGodotString*(s: cstring): GodotString {.inline.} = ## Converts the cstring into ``GodotString`` diff --git a/godot/internal/godotvariants.nim b/godot/internal/godotvariants.nim index 3f961ca..0a0980f 100644 --- a/godot/internal/godotvariants.nim +++ b/godot/internal/godotvariants.nim @@ -1,6 +1,6 @@ # Copyright 2018 Xored Software, Inc. -import core.godotcoretypes, godotinternaltypes, gdnativeapi +import core/godotcoretypes, godotinternaltypes, gdnativeapi proc getType*(p: GodotVariant): VariantType {.inline.} = getGDNativeAPI().variantGetType(p) @@ -121,34 +121,34 @@ proc asGodotString*(self: GodotVariant): GodotString {.inline.} = getGDNativeAPI().variantAsString(self) proc asVector2*(self: GodotVariant): Vector2 {.inline.} = - getGDNativeAPI().variantAsVector2(self) + getGDNativeAPI().variantAsVector2(self).toVector2() proc asRect2*(self: GodotVariant): Rect2 {.inline.} = - getGDNativeAPI().variantAsRect2(self) + getGDNativeAPI().variantAsRect2(self).toRect2() proc asVector3*(self: GodotVariant): Vector3 {.inline.} = - getGDNativeAPI().variantAsVector3(self) + getGDNativeAPI().variantAsVector3(self).toVector3() proc asTransform2D*(self: GodotVariant): Transform2D {.inline.} = - getGDNativeAPI().variantAsTransform2D(self) + getGDNativeAPI().variantAsTransform2D(self).toTransform2D() proc asPlane*(self: GodotVariant): Plane {.inline.} = - getGDNativeAPI().variantAsPlane(self) + getGDNativeAPI().variantAsPlane(self).toPlane() proc asQuat*(self: GodotVariant): Quat {.inline.} = - getGDNativeAPI().variantAsQuat(self) + getGDNativeAPI().variantAsQuat(self).toQuat() proc asAABB*(self: GodotVariant): AABB {.inline.} = - getGDNativeAPI().variantAsAABB(self) + getGDNativeAPI().variantAsAABB(self).toAABB() proc asBasis*(self: GodotVariant): Basis {.inline.} = - getGDNativeAPI().variantAsBasis(self) + getGDNativeAPI().variantAsBasis(self).toBasis() proc asTransform*(self: GodotVariant): Transform {.inline.} = - getGDNativeAPI().variantAsTransform(self) + getGDNativeAPI().variantAsTransform(self).toTransform() proc asColor*(self: GodotVariant): Color {.inline.} = - getGDNativeAPI().variantAsColor(self) + getGDNativeAPI().variantAsColor(self).toColor() proc asNodePath*(self: GodotVariant): GodotNodePath {.inline.} = getGDNativeAPI().variantAsNodePath(self) diff --git a/godot/nim/godotmacros.nim b/godot/nim/godotmacros.nim index 384aa2b..6b81f7e 100644 --- a/godot/nim/godotmacros.nim +++ b/godot/nim/godotmacros.nim @@ -1,8 +1,8 @@ # Copyright 2018 Xored Software, Inc. -import macros, tables, typetraits -import godotinternal, internal.godotvariants -import godotnim, core.variants +import macros, tables, typetraits, strutils, sets, sequtils, options, algorithm +import godotinternal, internal/godotvariants +import godotnim, core/variants type VarDecl = ref object @@ -10,8 +10,8 @@ type typ: NimNode defaultValue: NimNode isNoGodot: bool - hint: string - hintStr: string + hint: Option[string] + hintStr: Option[string] usage: NimNode isExported: bool @@ -32,6 +32,8 @@ type ParseError = object of Exception +include "internal/backwardcompat.inc.nim" + proc godotToNim[T](val: Variant): (T, ConversionResult) = mixin fromVariant result[1] = fromVariant(result[0], val) @@ -51,15 +53,15 @@ template parseError(node: NimNode, msg: string) = proc extractNames(definition: NimNode): tuple[name, parentName: string] = if definition.kind == nnkIdent: - result.name = $(definition.ident) + result.name = definition.strVal else: if not (definition.kind == nnkInfix and - definition[0].ident == toNimIdent("of")): + definition[0].strVal == "of"): parseError(definition, "invalid type definition") - result.name = $(definition[1].ident) + result.name = definition[1].strVal case definition[2].kind: of nnkIdent: - result.parentName = $definition[2].ident + result.parentName = definition[2].strVal else: parseError(definition[2], "parent type expected") @@ -72,13 +74,13 @@ proc newCStringLit(s: string): NimNode {.compileTime.} = newNimNode(nnkCallStrLit).add(ident("cstring"), newRStrLit(s)) iterator pragmas(node: NimNode): - tuple[key: NimIdent, value: NimNode, index: int] = + tuple[key: string, value: NimNode, index: int] = assert node.kind in {nnkPragma, nnkEmpty} for index in countdown(node.len - 1, 0): if node[index].kind == nnkExprColonExpr: - yield (node[index][0].ident, node[index][1], index) + yield (node[index][0].strVal, node[index][1], index) elif node[index].kind == nnkIdent: - yield (node[index].ident, nil, index) + yield (node[index].strVal, nil, index) proc removePragmaNode(statement: NimNode, pname: string): NimNode {.compileTime.} = @@ -91,9 +93,8 @@ proc removePragmaNode(statement: NimNode, result = nil var pragmas = if RoutineNodes.contains(statement.kind): statement.pragma() else: statement[1] - let pnameIdent = toNimIdent(pname) for ident, val, i in pragmas(pragmas): - if ident == pnameIdent: + if ident.eqIdent(pname): pragmas.del(i) return val @@ -104,19 +105,18 @@ proc removePragma(statement: NimNode, pname: string): bool = return false var pragmas = if RoutineNodes.contains(statement.kind): statement.pragma() else: statement[1] - let pnameIdent = toNimIdent(pname) for ident, val, i in pragmas(pragmas): - if ident == pnameIdent: + if ident.eqIdent(pname): pragmas.del(i) return true 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 ## Works for routine nodes or nnkPragmaExpr let node = removePragmaNode(statement, pname) - result = if node.isNil: nil - else: $node + result = if node.isNil: none(string) + else: some($node) proc isExported(node: NimNode): bool {.compileTime.} = if node.kind == nnkPragmaExpr: @@ -172,10 +172,15 @@ proc parseMethod(meth: NimNode): MethodDecl = proc parseVarSection(decl: NimNode): seq[VarDecl] = assert(decl.kind == nnkVarSection) - result = identDefsToVarDecls(decl[0]) + for i in 0..`_ or by using ## `load `_ or any other way ## that you can find in `Godot API `_. - let typeDef = parseType(definition, callsite()) + let typeDef = parseType(ast) result = genType(typeDef) - -{.push warning[Deprecated]: on.} diff --git a/godot/nim/godotnim.nim b/godot/nim/godotnim.nim index 2d66ebd..7f3ed96 100644 --- a/godot/nim/godotnim.nim +++ b/godot/nim/godotnim.nim @@ -1,14 +1,14 @@ # Copyright 2018 Xored Software, Inc. -import tables, typetraits, macros +import tables, typetraits, macros, unicode, strutils, sets, options import gdnativeapi -import core.godotcoretypes, core.godotbase -import core.vector2, core.rect2, - core.vector3, core.transform2d, - core.planes, core.quats, core.aabb, - core.basis, core.transforms, core.colors, - core.nodepaths, core.rids, core.dictionaries, - core.arrays, core.poolarrays, core.variants +import core/godotcoretypes, core/godotbase +import core/vector2, core/rect2, + core/vector3, core/transform2d, + core/planes, core/quats, core/aabb, + core/basis, core/transforms, core/colors, + core/nodepaths, core/rids, core/dictionaries, + core/arrays, core/poolarrays, core/variants import godotinternal ## This module defines ``NimGodotObject`` and ``toVariant``/``fromVariant`` @@ -31,7 +31,7 @@ type ## The base type all Godot types inherit from. ## Manages lifecycle of the wrapped ``GodotObject``. godotObject: ptr GodotObject - linkedObject: NimGodotObject + linkedObjectPtr: pointer ## Wrapper around native object that is the container of the Nim "script" ## This is needed for `of` checks and `as` conversions to work as ## expected. For example, Nim type may inherit from ``Spatial``, but the @@ -39,6 +39,8 @@ type ## ``Particles`` is valid, but Nim type system is not aware of that. ## This works in both directions - for linked native object this ## reference points to Nim object. + ## This is stored as a raw pointer to avoid reference cycles and therefore + ## improve GC performance. isRef*: bool isFinalized: bool isNative: bool @@ -89,21 +91,71 @@ type ## values. ## See documentation of ``GodotPropertyHint`` for description of formats. + FNV1Hash = uint32 + +include "internal/backwardcompat.inc.nim" + proc isFinalized*(obj: NimGodotObject): bool {.inline.} = obj.isFinalized -var classRegistry {.threadvar.}: TableRef[cstring, ObjectInfo] -var classRegistryStatic* {.compileTime.}: TableRef[cstring, ObjectInfo] +var classRegistry {.threadvar.}: TableRef[FNV1Hash, ObjectInfo] +var classRegistryStatic* {.compileTime.}: TableRef[FNV1Hash, ObjectInfo] ## Compile-time variable used for implementation of several procedures ## and macros static: - classRegistryStatic = newTable[cstring, ObjectInfo]() + classRegistryStatic = newTable[FNV1Hash, ObjectInfo]() -static: - import sets, strutils var nativeClasses {.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: + break + let firstByte = uint8(rune.uint64 and 0xFF'u64) + appendFNV1Hash(result, firstByte) + # We don't really need to calculate hash of other bytes, + # since we only use hashes of ASCII strings + inc i + proc getClassName*(o: NimGodotObject): string = o.godotObject.getClassName() @@ -135,12 +187,15 @@ proc deinit*(obj: NimGodotObject) = obj.godotObject.deinit() obj.godotObject = nil +proc linkedObject(obj: NimGodotObject): NimGodotObject {.inline.} = + cast[NimGodotObject](obj.linkedObjectPtr) + proc nimGodotObjectFinalizer*[T: NimGodotObject](obj: T) = if obj.godotObject.isNil or obj.isNative: return # important to set it before so that ``unreference`` is aware obj.isFinalized = true - if obj.isRef and obj.godotObject.unreference() or - not obj.linkedObject.isNil: + if (obj.isRef or not obj.linkedObject.isNil and obj.linkedObject.isRef) and + obj.godotObject.unreference(): obj.deinit() macro baseNativeType(T: typedesc): cstring = @@ -154,7 +209,7 @@ macro baseNativeType(T: typedesc): cstring = if typeName == "NimGodotObject": break t = getType(t[1][1]) - if baseT.isNil: + if baseT.len == 0: result = newNilLit() else: let rStr = newNimNode(nnkRStrLit) @@ -179,12 +234,12 @@ macro isResource(T: typedesc): bool = result = if inherits(getType(T), "Resource"): ident("true") else: ident("false") -template registerClass*(T: typedesc; godotClassName: cstring, +template registerClass*(T: typedesc; godotClassName: string or cstring, native: bool) = ## Registers the specified Godot type. ## Used by ``gdobj`` macro and `godotapigen `_. if classRegistry.isNil: - classRegistry = newTable[cstring, ObjectInfo]() + classRegistry = newTable[FNV1Hash, ObjectInfo]() let constructor = proc(): NimGodotObject = var t: T new(t, nimGodotObjectFinalizer[T]) @@ -198,14 +253,22 @@ template registerClass*(T: typedesc; godotClassName: cstring, isNative: native, isRef: isRef ) - classRegistry[godotClassName] = objInfo + classRegistry[fnv1Hash($godotClassName)] = objInfo static: let objInfoStatic = ObjectInfo( baseNativeClass: base, isNative: native, 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: static: refClasses.add(T.name) @@ -214,10 +277,10 @@ template registerClass*(T: typedesc; godotClassName: cstring, nativeClasses.add(T.name) 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 godotObject.isNil) - let objInfo = classRegistry.getOrDefault(godotClassName) + let objInfo = classRegistry.getOrDefault(fnv1Hash(godotClassName)) if objInfo.constructor.isNil: printError("Nim constructor not found for class " & $godotClassName) else: @@ -240,9 +303,11 @@ proc asNimGodotObject*[T: NimGodotObject]( # Could be data from other bindings result = nil if result.isNil: + var classNameStr = godotObject.getClassNameRaw() result = newNimGodotObject[T]( - godotObject, cstring(godotObject.getClassName()), + godotObject, classNameStr, forceNativeObject or noRef) + deinit(classNameStr) proc newVariant*(obj: NimGodotObject): Variant {.inline.} = newVariant(obj.godotObject) @@ -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 ## infix notation (``node as Button``). if obj.isNil: return nil - if obj of T: + if system.`of`(obj, T): 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) else: - when not defined(release): - printError("Failed to cast object to " & - T.name & "\n" & getStackTrace()) result = nil -proc `of`*[T: NimGodotObject](obj: NimGodotObject, - t: typedesc[T]): bool {.inline.} = +proc `of`*[T1, T2: NimGodotObject](obj: T1, t: typedesc[T2]): bool {.inline.} = ## 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.} = result = newNimNode(nnkRStrLit) result.strVal = s -static: - import strutils - -macro toGodotName(T: typedesc): string = - var godotName: string +macro toGodotName(T: typedesc): untyped = if T is GodotString or T is string: - godotName = "String" + newStrLitNode"String" elif T is SomeFloat: - godotName = "float" + newStrLitNode"float" elif T is SomeUnsignedInt or T is SomeSignedInt: - godotName = "int" - if godotName.isNil: - let nameStr: string = (($T.getType()[1][1].symbol).split(':')[0]) - godotName = case nameStr: - of "File", "Directory", "Thread", "Mutex", "Semaphore": - "_" & nameStr - else: - nameStr - - result = newLit(godotName) + newStrLitNode"int" + else: + let nameStr = ((T.getType()[1][1].strVal).split(':')[0]) + case nameStr: + of "File", "Directory", "Thread", "Mutex", "Semaphore": + newStrLitNode("_" & nameStr) + else: + newStrLitNode(nameStr) macro asCString(s: static[string]): cstring = result = newNimNode(nnkCallStrLit).add( @@ -364,17 +419,18 @@ proc newOwnObj[T: NimGodotObject](name: cstring): T = proc gdnew*[T: NimGodotObject](): T = ## Instantiates new object of type ``T``. - const godotName = asCString(toGodotName(T)) - const objInfo = classRegistryStatic[godotName] + const godotName = toGodotName(T) + const cGodotName = asCString(godotName) + const objInfo = classRegistryStatic[fnv1Hash(godotName)] when objInfo.isNative: - let godotObject = getClassConstructor(godotName)() + let godotObject = getClassConstructor(cGodotName)() new(result, nimGodotObjectFinalizer[T]) result.godotObject = godotObject when objInfo.isRef: godotObject.initRef() result.isRef = true else: - result = newOwnObj[T](godotName) + result = newOwnObj[T](cGodotName) proc newCallError*(err: VariantCallError): ref CallError = ## Instantiates ``CallError`` from Godot ``err``. @@ -414,14 +470,17 @@ proc setGodotObject*(nimObj: NimGodotObject, obj: ptr GodotObject) {.inline.} = proc setNativeObject*(nimObj: NimGodotObject, nativeObj: NimGodotObject) {.inline.} = ## Used from Godot constructor produced by ``gdobj`` macro. Do not call. - nimObj.linkedObject = nativeObj - nativeObj.linkedObject = nimObj + GC_ref(nativeObj) + nimObj.linkedObjectPtr = cast[pointer](nativeObj) + nativeObj.linkedObjectPtr = cast[pointer](nimObj) nativeObj.isNative = true proc removeGodotObject*(nimObj: NimGodotObject) {.inline.} = ## Used from Godot destructor produced by ``gdobj`` macro. Do not call. + GC_unref(nimObj.linkedObject) nimObj.godotObject = nil nimObj.linkedObject.godotObject = nil + nimObj.linkedObjectPtr = nil proc `==`*(self, other: NimGodotObject): bool {.inline.} = ## Compares objects by referential equality. @@ -553,7 +612,11 @@ proc fromVariant*[T: SomeSignedInt or SomeUnsignedInt]( else: uint64) intVal = when T is SomeSignedInt: val.asInt() else: val.asUint() - if intVal > high(T) or intVal < low(T): + const highT = when T is SomeSignedInt: high(T).int64 + else: high(T).uint64 + const lowT = when T is SomeSignedInt: low(T).int64 + else: low(T).uint64 + if intVal > highT or intVal < lowT: result = ConversionResult.RangeError else: self = T(intVal) @@ -657,7 +720,10 @@ proc fromVariant*(s: var string, val: Variant): ConversionResult = if val.getType() == VariantType.String: s = val.asString() elif val.getType() == VariantType.Nil: - s = nil + when (NimMajor, NimMinor, NimPatch) < (0, 19, 0): + s = nil + else: + s = "" else: result = ConversionResult.TypeError @@ -731,10 +797,31 @@ proc fromVariant*[T: array](s: var T, val: Variant): ConversionResult = else: 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 -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: if t.isNil: return newVariant() @@ -744,7 +831,7 @@ proc toVariant*[T: Table or TableRef](t: T): Variant = dict[toVariant(k)] = toVariant(v) 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 = if val.getType() == VariantType.Nil: when t is ref: @@ -754,8 +841,12 @@ proc fromVariant*[T: Table or TableRef](t: var T, mixin fromVariant when t is Table: t = initTable[type(t.keys()), type(t.values())]() - else: + elif t is TableRef: t = newTable[type(t.keys()), type(t.values())]() + elif t is OrderedTable: + t = initOrderedTable[type(t.keys()), type(t.values())]() + else: + t = newOrderedTable[type(t.keys()), type(t.values())]() for k, v in dict: var nimKey: type(t.keys()) var nimVal: type(t.values()) @@ -773,10 +864,11 @@ proc fromVariant*[T: Table or TableRef](t: var T, else: result = ConversionResult.TypeError -{.emit: """/*TYPESECTION*/ -void NimMain(void); -N_NOINLINE(void, setStackBottom)(void* thestackbottom); -""".} +when (NimMajor, NimMinor, NimPatch) < (0, 19, 0): + {.emit: """/*TYPESECTION*/ + N_LIB_EXPORT N_CDECL(void, NimMain)(void); + N_NOINLINE(void, setStackBottom)(void* thestackbottom); + """.} var nativeLibHandle: pointer proc getNativeLibHandle*(): pointer = @@ -789,10 +881,16 @@ proc godot_nativescript_init(handle: pointer) {. nativeLibHandle = handle var stackBottom {.volatile.}: pointer + stackBottom = addr(stackBottom) {.emit: """ NimMain(); - setStackBottom((void*)(&`stackBottom`)); """.} + when (NimMajor, NimMinor, NimPatch) < (0, 19, 0): + {.emit: """ + setStackBottom((void*)(&`stackBottom`)); + """.} + else: + nimGC_setStackBottom(stackBottom) GC_fullCollect() GC_disable() @@ -803,7 +901,8 @@ proc godot_gdnative_init(options: ptr GDNativeInitOptions) {. proc godot_gdnative_terminate(options: ptr GDNativeTerminateOptions) {. 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 @@ -827,9 +926,13 @@ proc registerFrameCallback*(cb: proc () {.closure.}) = proc godot_nativescript_frame() {.cdecl, exportc, dynlib.} = var stackBottom {.volatile.}: pointer - {.emit: """ - setStackBottom((void*)(&`stackBottom`)); - """.} + stackBottom = addr(stackBottom) + when (NimMajor, NimMinor, NimPatch) < (0, 19, 0): + {.emit: """ + setStackBottom((void*)(&`stackBottom`)); + """.} + else: + nimGC_setStackBottom(stackBottom) for cb in idleCallbacks: cb() GC_step(nimGcStepLengthUs, true, 0) diff --git a/godot/nim/nim.cfg b/godot/nim/nim.cfg index f1fb6a7..add9a4d 100644 --- a/godot/nim/nim.cfg +++ b/godot/nim/nim.cfg @@ -1 +1,2 @@ ---path:"$projectdir/../" \ No newline at end of file +--path:"$projectdir/../" +-d:useRealtimeGc \ No newline at end of file