Provide type hints for standard types
This commit is contained in:
parent
afa48455f6
commit
c1c1852203
2 changed files with 211 additions and 118 deletions
|
|
@ -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,
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue