Provide type hints for standard types

This commit is contained in:
Ruslan Mustakov 2017-08-05 12:43:43 +07:00
commit c1c1852203
2 changed files with 211 additions and 118 deletions

View file

@ -11,7 +11,7 @@ type
defaultValue: NimNode defaultValue: NimNode
isNoGodot: bool isNoGodot: bool
hint: string hint: string
hintTip: string hintStr: string
usage: string usage: string
isExported: bool isExported: bool
@ -122,7 +122,7 @@ proc identDefsToVarDecls(identDefs: NimNode): seq[VarDecl] =
for i in 0..<(identDefs.len - 2): for i in 0..<(identDefs.len - 2):
let nameNode = identDefs[i].copyNimTree() let nameNode = identDefs[i].copyNimTree()
let hint = removeStrPragma(nameNode, "hint") let hint = removeStrPragma(nameNode, "hint")
let hintTip = removeStrPragma(nameNode, "tip") let hintStr = removeStrPragma(nameNode, "hintStr")
let usage = removeStrPragma(nameNode, "usage") let usage = removeStrPragma(nameNode, "usage")
let isGdExport = removePragma(nameNode, "gdExport") let isGdExport = removePragma(nameNode, "gdExport")
if not nameNode.isExported() and isGdExport: if not nameNode.isExported() and isGdExport:
@ -136,7 +136,7 @@ proc identDefsToVarDecls(identDefs: NimNode): seq[VarDecl] =
typ: identDefs[identDefs.len - 2], typ: identDefs[identDefs.len - 2],
defaultValue: identDefs[identDefs.len - 1], defaultValue: identDefs[identDefs.len - 1],
hint: hint, hint: hint,
hintTip: hintTip, hintStr: hintStr,
isNoGodot: isNoGodot, isNoGodot: isNoGodot,
usage: usage, usage: usage,
isExported: nameNode.isExported() isExported: nameNode.isExported()
@ -279,13 +279,13 @@ macro invokeVarArgs(procIdent, objIdent;
result.add(newNimNode(nnkElse).add(getAst( result.add(newNimNode(nnkElse).add(getAst(
printInvokeErr($procIdent.ident, minArgs, maxArgs, numArgsIdent)))) printInvokeErr($procIdent.ident, minArgs, maxArgs, numArgsIdent))))
proc typeError(nimType: cstring, value: string, godotType: VariantType, proc typeError(nimType: string, value: string, godotType: VariantType,
className: cstring, propertyName: cstring): string = className: cstring, propertyName: cstring): string =
result = "Tried to assign incompatible value " & value & " (" & $godotType & result = "Tried to assign incompatible value " & value & " (" & $godotType &
") to field \"" & $propertyName & "\" (" & $nimType & ") of " & ") to field \"" & $propertyName & "\" (" & $nimType & ") of " &
$className $className
proc rangeError(nimType: cstring, value: string, className: cstring, proc rangeError(nimType: string, value: string, className: cstring,
propertyName: cstring): string = propertyName: cstring): string =
result = "Tried to assign the out-of-range value " & value & result = "Tried to assign the out-of-range value " & value &
" to field \"" & $propertyName & "\" (" & $nimType & ") of " & " to field \"" & $propertyName & "\" (" & $nimType & ") of " &
@ -345,7 +345,7 @@ template registerGodotClass(classNameIdent, classNameLit, isRef,
template registerGodotField(classNameLit, classNameIdent, propNameLit, template registerGodotField(classNameLit, classNameIdent, propNameLit,
propNameIdent, propTypeLit, propTypeIdent, propNameIdent, propTypeLit, propTypeIdent,
setFuncIdent, getFuncIdent, hintTipLit, setFuncIdent, getFuncIdent, hintStrLit,
hintIdent, usageIdent, hasDefaultValue, hintIdent, usageIdent, hasDefaultValue,
defaultValueNode) = defaultValueNode) =
proc setFuncIdent(obj: ptr GodotObject, methData: pointer, proc setFuncIdent(obj: ptr GodotObject, methData: pointer,
@ -377,12 +377,27 @@ template registerGodotField(classNameLit, classNameIdent, propNameLit,
let getFunc = GodotPropertyGetFunc( let getFunc = GodotPropertyGetFunc(
getFunc: getFuncIdent getFunc: getFuncIdent
) )
mixin godotTypeInfo
static:
var typeInfo: GodotTypeInfo
when compiles(godotTypeInfo(propTypeIdent)):
typeInfo = godotTypeInfo(propTypeIdent)
const hintStr = when hintStrLit != "NIM":
hintStrLit
else:
typeInfo.hintStr
const hint = when astToStr(hintIdent) != "NIM":
GodotPropertyHint.hintIdent
else:
typeInfo.hint
const variantType = typeInfo.variantType
var hintStrGodot = hintStr.toGodotString()
{.push warning[ProveInit]: off.} # false warning, Nim bug {.push warning[ProveInit]: off.} # false warning, Nim bug
var hintStr = hintTipLit.toGodotString()
let attr = GodotPropertyAttributes( let attr = GodotPropertyAttributes(
typ: ord(variantType(propTypeIdent)), typ: ord(variantType),
hintString: hintStr, hint: hint,
hint: GodotPropertyHint.hintIdent, hintString: hintStrGodot,
usage: GodotPropertyUsageFlags.usageIdent usage: GodotPropertyUsageFlags.usageIdent
) )
{.push warning[ProveInit]: on.} {.push warning[ProveInit]: on.}
@ -390,7 +405,7 @@ template registerGodotField(classNameLit, classNameIdent, propNameLit,
attr.defaultValue = (defaultValueNode).toVariant().godotVariant[] attr.defaultValue = (defaultValueNode).toVariant().godotVariant[]
godotScriptRegisterProperty(getNativeLibHandle(), classNameLit, propNameLit, godotScriptRegisterProperty(getNativeLibHandle(), classNameLit, propNameLit,
unsafeAddr attr, setFunc, getFunc) unsafeAddr attr, setFunc, getFunc)
hintStr.deinit() hintStrGodot.deinit()
static: static:
import strutils, sets, sequtils import strutils, sets, sequtils
@ -466,9 +481,9 @@ proc genType(obj: ObjectDecl): NimNode {.compileTime.} =
# 5. Register fields (properties) # 5. Register fields (properties)
for field in obj.fields: for field in obj.fields:
if field.isNoGodot: continue if field.isNoGodot: continue
let hintTip = if field.hintTip.isNil: "" let hintStr = if field.hintStr.isNil: "NIM"
else: field.hintTip else: field.hintStr
let hint = if field.hint.isNil: "None" let hint = if field.hint.isNil: "NIM"
else: field.hint else: field.hint
let usage = if field.usage.isNil: "Default" let usage = if field.usage.isNil: "Default"
else: field.usage else: field.usage
@ -476,13 +491,14 @@ proc genType(obj: ObjectDecl): NimNode {.compileTime.} =
field.defaultValue.kind != nnkEmpty field.defaultValue.kind != nnkEmpty
let hintIdent = ident(hint) let hintIdent = ident(hint)
let usageIdent = ident(usage) let usageIdent = ident(usage)
let nimType = repr field.typ
result.add(getAst( result.add(getAst(
registerGodotField(classNameLit, classNameIdent, registerGodotField(classNameLit, classNameIdent,
newCStringLit(toGodotStyle($field.name.basename())), newCStringLit(toGodotStyle($field.name.basename())),
ident(field.name), newCStringLit($field.typ), ident(field.name), nimType,
field.typ, genSym(nskProc, "setFunc"), field.typ, genSym(nskProc, "setFunc"),
genSym(nskProc, "getFunc"), genSym(nskProc, "getFunc"),
newStrLitNode(hintTip), hintIdent, usageIdent, newStrLitNode(hintStr), hintIdent, usageIdent,
ident($hasDefaultValue), field.defaultValue))) ident($hasDefaultValue), field.defaultValue)))
# 6. Register methods # 6. Register methods
@ -574,12 +590,12 @@ macro gdobj*(definition: untyped, body: typed): typed {.immediate.} =
## var myField: int ## var myField: int
## ## Not exported to Godot (i.e. editor will not see this field). ## ## Not exported to Godot (i.e. editor will not see this field).
## ##
## var myString* {.gdExport, hint: Length, tip: "20".}: string ## var myString* {.gdExport, hint: Length, hintStr: "20".}: string
## ## Exported to Godot as ``my_string``. ## ## Exported to Godot as ``my_string``.
## ## Editor will limit this string to length 20. ## ## Editor will limit this string to length 20.
## ## ``hint` is a value of ``GodotPropertyHint`` enum. ## ## ``hint` is a value of ``GodotPropertyHint`` enum.
## ## ``tip`` depends on the value of ``hint``, its format is described ## ## ``hintStr`` depends on the value of ``hint``, its format is
## ## in ``GodotPropertyHint`` documentation. ## ## described in ``GodotPropertyHint`` documentation.
## ##
## method ready*() = ## method ready*() =
## ## Exported methods are exported to Godot by default, ## ## Exported methods are exported to Godot by default,

View file

@ -18,9 +18,12 @@ import godotinternal
## You can also allow conversion of any custom type ``MyType`` by implementing: ## You can also allow conversion of any custom type ``MyType`` by implementing:
## ##
## .. code-block:: nim ## .. code-block:: nim
## proc variantType*(T: typedesc[MyType]): VariantType ## proc godotTypeInfo*(T: typedesc[MyType]): GodotTypeInfo
## proc toVariant*(self: MyType): Variant ## proc toVariant*(self: MyType): Variant
## proc fromVariant*(self: var MyType, val: Variant): ConversionResult ## proc fromVariant*(self: var MyType, val: Variant): ConversionResult
##
## Implementing ``godotTypeInfo`` is optional and is necessary only if you want
## the type to be editable from the editor.
type type
NimGodotObject* = ref object of RootObj NimGodotObject* = ref object of RootObj
@ -66,6 +69,16 @@ type
isNative: bool isNative: bool
isRef: bool isRef: bool
GodotTypeInfo* = object
## Type information provided to Godot editor
variantType*: VariantType
hint*: GodotPropertyHint
hintStr*: string
## Format depends on the type and the hint.
## For example, for Enum ``hint`` this is a comma separated list of
## values.
## See documentation of ``GodotPropertyHint`` for description of formats.
template printWarning*(warning: typed) = template printWarning*(warning: typed) =
## Prints ``warning`` to Godot log, adding filename and line information. ## Prints ``warning`` to Godot log, adding filename and line information.
let (filename, line) = instantiationInfo() let (filename, line) = instantiationInfo()
@ -89,7 +102,9 @@ proc print*(message: cstring) {.inline.} =
s.deinit() s.deinit()
var classRegistry {.threadvar.}: TableRef[cstring, ObjectInfo] var classRegistry {.threadvar.}: TableRef[cstring, ObjectInfo]
var classRegistryStatic {.compileTime.}: TableRef[cstring, ObjectInfo] var classRegistryStatic* {.compileTime.}: TableRef[cstring, ObjectInfo]
## Compile-time variable used for implementation of several procedures
## and macros
static: static:
classRegistryStatic = newTable[cstring, ObjectInfo]() classRegistryStatic = newTable[cstring, ObjectInfo]()
@ -261,13 +276,22 @@ proc newRStrLit(s: string): NimNode {.compileTime.} =
static: static:
import strutils import strutils
macro toGodotName(T: typedesc): cstring = macro toGodotName(T: typedesc): cstring =
let nameStr: string = (($T.getType()[1][1].symbol).split(':')[0]) var godotName: string
let godotName = case nameStr: if T is GodotString or T is string:
of "File", "Directory", "Thread", "Mutex", "Semaphore": godotName = "String"
"_" & nameStr elif T is SomeFloat:
else: godotName = "float"
nameStr 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 = newNimNode(nnkCallStrLit).add( result = newNimNode(nnkCallStrLit).add(
ident("cstring"), newRStrLit(godotName)) ident("cstring"), newRStrLit(godotName))
@ -375,14 +399,18 @@ proc godotObject*(nimObj: NimGodotObject): ptr GodotObject {.inline.} =
## you are doing. ## you are doing.
nimObj.godotObject nimObj.godotObject
proc variantType*(T: typedesc[NimGodotObject]): VariantType {.inline.} = proc godotTypeInfo*(T: typedesc[NimGodotObject]): GodotTypeInfo {.inline.} =
VariantType.Object GodotTypeInfo(
variantType: VariantType.Object,
hint: GodotPropertyHint.None,
hintStr: toGodotName(T)
)
proc toVariant*(self: NimGodotObject): Variant {.inline.} = proc toVariant*(self: NimGodotObject): Variant {.inline.} =
newVariant(self.godotObject) newVariant(self.godotObject)
proc fromVariant*[T: NimGodotObject](self: var T, proc fromVariant*[T: NimGodotObject](self: var T,
val: Variant): ConversionResult = val: Variant): ConversionResult =
if val.getType() == VariantType.Object: if val.getType() == VariantType.Object:
let objPtr = val.asGodotObject() let objPtr = val.asGodotObject()
self = asNimGodotObject[T](objPtr) self = asNimGodotObject[T](objPtr)
@ -393,15 +421,25 @@ proc fromVariant*[T: NimGodotObject](self: var T,
else: else:
result = ConversionResult.TypeError result = ConversionResult.TypeError
proc variantType*(T: typedesc[enum]): VariantType {.inline.} = proc godotTypeInfo*(T: typedesc[enum]): GodotTypeInfo =
VariantType.Int result = GodotTypeInfo(
variantType: VariantType.Int,
hint: GodotPropertyHint.Enum,
hintStr: ""
)
for val in T:
if result.hintStr.len > 0:
result.hintStr.add(',')
result.hintStr.add($val)
proc toVariant*[T: enum](self: T): Variant {.inline.} = proc toVariant*[T: enum](self: T): Variant {.inline.} =
newVariant(int64(ord(self))) newVariant(int64(ord(self)))
proc fromVariant*[T: enum](self: var T, proc fromVariant*[T: enum](self: var T,
val: Variant): ConversionResult {.inline.} = val: Variant): ConversionResult {.inline.} =
if val.getType() == VariantType.Int: if val.getType() == VariantType.Nil:
discard
elif val.getType() == VariantType.Int:
self = T(val.asInt()) self = T(val.asInt())
else: else:
result = ConversionResult.TypeError result = ConversionResult.TypeError
@ -410,73 +448,81 @@ proc toVariant*(self: Variant): Variant {.inline.} =
self self
proc fromVariant*(self: var Variant, proc fromVariant*(self: var Variant,
val: Variant): ConversionResult {.inline.} = val: Variant): ConversionResult {.inline.} =
self = newVariant(val) self = newVariant(val)
proc variantType*(T: typedesc[SomeGodotOrNum]): VariantType {.inline.} = proc godotTypeInfo*(T: typedesc[SomeGodotOrNum]): GodotTypeInfo {.inline.} =
when T is SomeSignedInt or T is SomeUnsignedInt: result.variantType =
VariantType.Int when T is SomeSignedInt or T is SomeUnsignedInt:
elif T is bool: VariantType.Int
VariantType.Bool elif T is bool:
elif T is SomeFloat: VariantType.Bool
VariantType.Real elif T is SomeFloat:
elif T is string or T is GodotString: VariantType.Real
VariantType.String elif T is string or T is GodotString:
elif T is Vector2: VariantType.String
VariantType.Vector2 elif T is Vector2:
elif T is Rect2: VariantType.Vector2
VariantType.Rect2 elif T is Rect2:
elif T is Vector3: VariantType.Rect2
VariantType.Vector3 elif T is Vector3:
elif T is Transform2D: VariantType.Vector3
VariantType.Transform2D elif T is Transform2D:
elif T is Plane: VariantType.Transform2D
VariantType.Plane elif T is Plane:
elif T is Quat: VariantType.Plane
VariantType.Quat elif T is Quat:
elif T is Rect3: VariantType.Quat
VariantType.Rect3 elif T is Rect3:
elif T is Basis: VariantType.Rect3
VariantType.Basis elif T is Basis:
elif T is Transform: VariantType.Basis
VariantType.Transform elif T is Transform:
elif T is Color: VariantType.Transform
VariantType.Color elif T is Color:
elif T is RID: VariantType.Color
VariantType.RID elif T is RID:
elif T is ptr GodotObject: VariantType.RID
VariantType.Object elif T is ptr GodotObject:
elif T is NodePath: VariantType.Object
VariantType.NodePath elif T is NodePath:
elif T is Dictionary: VariantType.NodePath
VariantType.Dictionary elif T is Dictionary:
elif T is Array: VariantType.Dictionary
VariantType.Array elif T is Array:
elif T is PoolByteArray: VariantType.Array
VariantType.PoolByteArray elif T is PoolByteArray:
elif T is PoolIntArray: VariantType.PoolByteArray
VariantType.PoolIntArray elif T is PoolIntArray:
elif T is PoolRealArray: VariantType.PoolIntArray
VariantType.PoolRealArray elif T is PoolRealArray:
elif T is PoolStringArray: VariantType.PoolRealArray
VariantType.PoolStringArray elif T is PoolStringArray:
elif T is PoolVector2Array: VariantType.PoolStringArray
VariantType.PoolVector2Array elif T is PoolVector2Array:
elif T is PoolVector3Array: VariantType.PoolVector2Array
VariantType.PoolVector3Array elif T is PoolVector3Array:
elif T is PoolColorArray: VariantType.PoolVector3Array
VariantType.PoolColorArray elif T is PoolColorArray:
else: VariantType.PoolColorArray
VariantType.Nil else:
VariantType.Nil
proc godotTypeInfo*(T: typedesc[range]): VariantType {.inline.} =
GodotTypeInfo(
variantType: VariantType.Int,
hint: GodotPropertyHint.Range,
hintStr: $low(T) & "," & $high(T) & ",1"
)
proc toVariant*[T: SomeGodotOrNum](val: T): Variant {.inline.} = proc toVariant*[T: SomeGodotOrNum](val: T): Variant {.inline.} =
newVariant(val) newVariant(val)
proc fromVariant*[T: SomeSignedInt or SomeUnsignedInt]( proc fromVariant*[T: SomeSignedInt or SomeUnsignedInt](
self: var T, val: Variant): ConversionResult = self: var T, val: Variant): ConversionResult =
if val.getType() != VariantType.Int: if val.getType() == VariantType.Nil:
result = ConversionResult.TypeError self = 0
else: elif val.getType() == VariantType.Int:
var intVal: (when T is SomeSignedInt: int64 var intVal: (when T is SomeSignedInt: int64
else: uint64) else: uint64)
intVal = when T is SomeSignedInt: val.asInt() intVal = when T is SomeSignedInt: val.asInt()
@ -485,9 +531,13 @@ proc fromVariant*[T: SomeSignedInt or SomeUnsignedInt](
result = ConversionResult.RangeError result = ConversionResult.RangeError
else: else:
self = T(intVal) self = T(intVal)
else:
result = ConversionResult.TypeError
proc fromVariant*[T: SomeFloat](self: var T, val: Variant): ConversionResult = proc fromVariant*[T: SomeFloat](self: var T, val: Variant): ConversionResult =
if val.getType() == VariantType.Real: if val.getType() == VariantType.Nil:
self = 0
elif val.getType() == VariantType.Real:
self = T(val.asReal()) self = T(val.asReal())
elif val.getType() == VariantType.Int: elif val.getType() == VariantType.Int:
self = T(val.asInt()) self = T(val.asInt())
@ -495,7 +545,10 @@ proc fromVariant*[T: SomeFloat](self: var T, val: Variant): ConversionResult =
result = ConversionResult.TypeError result = ConversionResult.TypeError
proc fromVariant*[T: SomeGodot](self: var T, val: Variant): ConversionResult = proc fromVariant*[T: SomeGodot](self: var T, val: Variant): ConversionResult =
if variantType(T) != val.getType(): if val.getType() == VariantType.Nil:
return
const typeInfo = godotTypeInfo(T)
if typeInfo.variantType != val.getType():
return ConversionResult.TypeError return ConversionResult.TypeError
when self is bool: when self is bool:
self = val.asBool() self = val.asBool()
@ -549,8 +602,8 @@ proc fromVariant*[T: SomeGodot](self: var T, val: Variant): ConversionResult =
# mustn't reach this # mustn't reach this
result = ConversionError.TypeError result = ConversionError.TypeError
proc variantType*(T: typedesc[string]): VariantType {.inline.} = proc godotTypeInfo*(T: typedesc[string]): GodotTypeInfo {.inline.} =
VariantType.String result.variantType = VariantType.String
proc toVariant*(s: string): Variant {.inline.} = proc toVariant*(s: string): Variant {.inline.} =
newVariant(s) newVariant(s)
@ -563,61 +616,83 @@ proc fromVariant*(s: var string, val: Variant): ConversionResult =
else: else:
result = ConversionResult.TypeError result = ConversionResult.TypeError
proc variantType*(T: typedesc[seq]): VariantType = template arrTypeInfo(T) =
VariantType.Array result.variantType = VariantType.Array
mixin godotTypeInfo
type ItemT = type((
block:
var s: T;
when T is seq: s[0] else: s[low(s)]))
when compiles(godotTypeInfo(ItemT)):
let itemTypeInfo = godotTypeInfo(ItemT)
result.hintStr = $ord(itemTypeInfo.variantType)
result.hintStr.add('/')
result.hintStr.add($ord(itemTypeInfo.hint))
result.hintStr.add(':')
if not itemTypeInfo.hintStr.isNil:
result.hintStr.add(itemTypeInfo.hintStr)
proc variantType*(T: typedesc[array]): VariantType = proc godotTypeInfo*(T: typedesc[seq]): GodotTypeInfo =
VariantType.Array arrTypeInfo(T)
proc godotTypeInfo*(T: typedesc[array]): GodotTypeInfo =
arrTypeInfo(T)
proc toVariant*[T](s: openarray[T]): Variant = proc toVariant*[T](s: openarray[T]): Variant =
var arr = newArray() var arr = newArray()
mixin toGodot mixin toVariant
for item in s: for item in s:
arr.add(toVariant(item)) arr.add(toVariant(item))
result = newVariant(arr) result = newVariant(arr)
proc fromVariant*[T](s: var seq[T], val: Variant): ConversionResult = proc fromVariant*[T](s: var seq[T], val: Variant): ConversionResult =
if val.getType() != VariantType.Array: if val.getType() == VariantType.Nil:
result = ConversionResult.TypeError s = nil
else: elif val.getType() == VariantType.Array:
let arr = val.asArray() let arr = val.asArray()
s = newSeq[T](arr.len) s = newSeq[T](arr.len)
for idx, item in arr: for idx, item in arr:
mixin fromGodot mixin fromVariant
let convResult = fromVariant(s[idx], item) let convResult = fromVariant(s[idx], item)
if convResult != ConversionResult.OK: if convResult != ConversionResult.OK:
s = nil s = nil
return convResult return convResult
else:
result = ConversionResult.TypeError
proc fromVariant*[T: array](s: var T, val: Variant): ConversionResult = proc fromVariant*[T: array](s: var T, val: Variant): ConversionResult =
if val.getType() != VariantType.Array: if val.getType() == VariantType.Nil:
result = ConversionResult.TypeError discard
else: elif val.getType() == VariantType.Array:
let arr = val.asArray() let arr = val.asArray()
if s.len != arr.len: if s.len != arr.len:
return ConversionResult.TypeError return ConversionResult.TypeError
for idx, item in arr: for idx, item in arr:
mixin fromGodot mixin fromVariant
let convResult = fromVariant(s[idx], item) let convResult = fromVariant(s[idx], item)
if convResult != ConversionResult.OK: if convResult != ConversionResult.OK:
return convResult return convResult
else:
result = ConversionResult.TypeError
proc variantType*(T: typedesc[Table|TableRef]): VariantType {.inline.} = proc godotTypeInfo*(T: typedesc[Table|TableRef]): GodotTypeInfo {.inline.} =
VariantType.Dictionary result.variantType = VariantType.Dictionary
proc toVariant*[T: Table or TableRef](t: T): Variant = proc toVariant*[T: Table or TableRef](t: T): Variant =
var dict = newDictionary() var dict = newDictionary()
mixin toGodot mixin toVariant
for k, v in t.pairs(): for k, v in t.pairs():
dict[toVariant(k)] = toVariant(v) dict[toVariant(k)] = toVariant(v)
result = newVariant(dict) result = newVariant(dict)
proc fromVariant*[T: Table or TableRef](t: var T, val: Variant): ConversionResult = proc fromVariant*[T: Table or TableRef](t: var T,
if val.getType() != VariantType.Dictionary: val: Variant): ConversionResult =
result = ConversionResult.TypeError if val.getType() == VariantType.Nil:
else: when t is ref:
t = nil
elif val.getType() == VariantType.Dictionary:
let dict = val.asDictionary() let dict = val.asDictionary()
mixin fromGodot mixin fromVariant
when t is Table: when t is Table:
t = initTable[type(t.keys()), type(t.values())]() t = initTable[type(t.keys()), type(t.values())]()
else: else:
@ -636,6 +711,8 @@ proc fromVariant*[T: Table or TableRef](t: var T, val: Variant): ConversionResul
t = nil t = nil
return valResult return valResult
t[nimKey] = nimVal t[nimKey] = nimVal
else:
result = ConversionResult.TypeError
{.emit: """/*TYPESECTION*/ {.emit: """/*TYPESECTION*/
void NimMain(void); void NimMain(void);