Fix object property export

This commit is contained in:
Ruslan Mustakov 2017-08-08 17:23:45 +07:00
commit daa56270e5
4 changed files with 58 additions and 41 deletions

View file

@ -14,4 +14,4 @@ export godotbase, vector2, rect2, vector3, transform2d, planes, quats,
poolarrays, variants
export godotmacros, godotnim
export GodotPropertyHint, GodotPropertyUsageFlags
export GodotPropertyHint, GodotPropertyUsage

View file

@ -118,7 +118,7 @@ const
GODOT_PROPERTY_USAGE_STORAGE_VALUE or GODOT_PROPERTY_USAGE_NETWORK_VALUE
type
GodotPropertyUsageFlags* {.size: sizeof(cint), pure.} = enum
GodotPropertyUsage* {.size: sizeof(cint), pure.} = enum
Storage = GODOT_PROPERTY_USAGE_STORAGE_VALUE
Editor = GODOT_PROPERTY_USAGE_EDITOR_VALUE
Network = GODOT_PROPERTY_USAGE_NETWORK_VALUE
@ -151,7 +151,7 @@ type
typ*: cint
hint*: GodotPropertyHint
hintString*: GodotString
usage*: GodotPropertyUsageFlags
usage*: cint
defaultValue*: GodotVariant
GodotInstanceCreateFunc* {.bycopy.} = object
@ -217,7 +217,7 @@ type
typ*: cint
hint*: GodotPropertyHint
hintString*: GodotString
usage*: GodotPropertyUsageFlags
usage*: cint
defaultValue*: GodotVariant
GodotSignal* = object

View file

@ -12,7 +12,7 @@ type
isNoGodot: bool
hint: string
hintStr: string
usage: string
usage: NimNode
isExported: bool
MethodDecl = ref object
@ -71,15 +71,31 @@ proc newCStringLit(s: string): NimNode {.compileTime.} =
newNimNode(nnkCallStrLit).add(ident("cstring"), newRStrLit(s))
iterator pragmas(node: NimNode):
tuple[key: NimIdent, value: string, index: int] =
tuple[key: NimIdent, value: NimNode, index: int] =
assert node.kind in {nnkPragma, nnkEmpty}
for index in countdown(node.len - 1, 0):
if node[index].kind == nnkExprColonExpr:
let val = $(node[index][1])
yield (node[index][0].ident, val, index)
yield (node[index][0].ident, node[index][1], index)
elif node[index].kind == nnkIdent:
yield (node[index].ident, nil, index)
proc removePragmaNode(statement: NimNode,
pname: string): NimNode {.compileTime.} =
## Removes the pragma from the node and returns value of the pragma
## Works for routine nodes or nnkPragmaExpr
if not (RoutineNodes.contains(statement.kind) or
statement.kind == nnkPragmaExpr):
return nil
result = nil
var pragmas = if RoutineNodes.contains(statement.kind): statement.pragma()
else: statement[1]
let pnameIdent = !pname
for ident, val, i in pragmas(pragmas):
if ident == pnameIdent:
pragmas.del(i)
return val
proc removePragma(statement: NimNode, pname: string): bool =
## Removes the pragma from the node and returns whether pragma was removed
if not (RoutineNodes.contains(statement.kind) or
@ -97,18 +113,9 @@ proc removeStrPragma(statement: NimNode,
pname: string): string {.compileTime.} =
## Removes the pragma from the node and returns value of the pragma
## Works for routine nodes or nnkPragmaExpr
if not (RoutineNodes.contains(statement.kind) or
statement.kind == nnkPragmaExpr):
return nil
result = nil
var pragmas = if RoutineNodes.contains(statement.kind): statement.pragma()
else: statement[1]
let pnameIdent = !pname
for ident, val, i in pragmas(pragmas):
if ident == pnameIdent:
pragmas.del(i)
return (if val.isNil: "" else: val)
let node = removePragmaNode(statement, pname)
result = if node.isNil: nil
else: $node
proc isExported(node: NimNode): bool {.compileTime.} =
if node.kind == nnkPragmaExpr:
@ -130,7 +137,7 @@ proc identDefsToVarDecls(identDefs: NimNode): seq[VarDecl] =
let nameNode = identDefs[i].copyNimTree()
let hint = removeStrPragma(nameNode, "hint")
let hintStr = removeStrPragma(nameNode, "hintStr")
let usage = removeStrPragma(nameNode, "usage")
let usage = removePragmaNode(nameNode, "usage")
let isGdExport = removePragma(nameNode, "gdExport")
result.add(VarDecl(
@ -345,7 +352,7 @@ template registerGodotClass(classNameIdent, classNameLit, isRef,
template registerGodotField(classNameLit, classNameIdent, propNameLit,
propNameIdent, propTypeLit, propTypeIdent,
setFuncIdent, getFuncIdent, hintStrLit,
hintIdent, usageIdent, hasDefaultValue,
hintIdent, usageExpr, hasDefaultValue,
defaultValueNode) =
proc setFuncIdent(obj: ptr GodotObject, methData: pointer,
nimPtr: pointer, val: GodotVariant) {.noconv.} =
@ -397,7 +404,7 @@ template registerGodotField(classNameLit, classNameIdent, propNameLit,
typ: ord(variantType),
hint: hint,
hintString: hintStrGodot,
usage: GodotPropertyUsageFlags.usageIdent
usage: usageExpr
)
{.push warning[ProveInit]: on.}
when hasDefaultValue:
@ -504,12 +511,14 @@ proc genType(obj: ObjectDecl): NimNode {.compileTime.} =
else: field.hintStr
let hint = if field.hint.isNil: "NIM"
else: field.hint
let usage = if field.usage.isNil: "Default"
else: field.usage
let usage =
if field.usage.isNil:
newLit(ord(GodotPropertyUsage.Default) or
ord(GodotPropertyUsage.ScriptVariable))
else: field.usage
let hasDefaultValue = not field.defaultValue.isNil and
field.defaultValue.kind != nnkEmpty
let hintIdent = ident(hint)
let usageIdent = ident(usage)
let nimType = repr field.typ
result.add(getAst(
registerGodotField(classNameLit, classNameIdent,
@ -517,7 +526,7 @@ proc genType(obj: ObjectDecl): NimNode {.compileTime.} =
ident(field.name), nimType,
field.typ, genSym(nskProc, "setFunc"),
genSym(nskProc, "getFunc"),
newStrLitNode(hintStr), hintIdent, usageIdent,
newStrLitNode(hintStr), hintIdent, usage,
ident($hasDefaultValue), field.defaultValue)))
# Register methods

View file

@ -168,18 +168,22 @@ macro baseNativeType(T: typedesc): cstring =
rStr.strVal = baseT
result = newNimNode(nnkCallStrLit).add(ident("cstring"), rStr)
macro isReference(T: typedesc): bool =
var isRef = false
var t = getType(T)
proc inherits(t: NimNode, parent: string): bool {.compileTime.} =
var curT = t
while true:
let typeName = ($t[1][1]).split(':')[0]
if typeName == "Reference":
isRef = true
break
let typeName = ($curT[1][1]).split(':')[0]
if typeName == parent:
return true
if typeName == "NimGodotObject":
break
t = getType(t[1][1])
result = if isRef: ident("true")
curT = getType(curT[1][1])
macro isReference(T: typedesc): bool =
result = if inherits(getType(T), "Reference"): ident("true")
else: ident("false")
macro isResource(T: typedesc): bool =
result = if inherits(getType(T), "Resource"): ident("true")
else: ident("false")
template registerClass*(T: typedesc; godotClassName: cstring,
@ -298,7 +302,7 @@ proc newRStrLit(s: string): NimNode {.compileTime.} =
static:
import strutils
macro toGodotName(T: typedesc): cstring =
macro toGodotName(T: typedesc): string =
var godotName: string
if T is GodotString or T is string:
godotName = "String"
@ -314,14 +318,17 @@ macro toGodotName(T: typedesc): cstring =
else:
nameStr
result = newLit(godotName)
macro asCString(s: static[string]): cstring =
result = newNimNode(nnkCallStrLit).add(
ident("cstring"), newRStrLit(godotName))
ident("cstring"), newRStrLit(s))
proc getSingleton*[T: NimGodotObject](): T =
## Returns singleton of type ``T``. Normally, this should not be used,
## because `godotapigen <godotapigen.html>`_ wraps singleton methods so that
## singleton objects don't have to be provided as parameters.
const godotName = toGodotName(T)
const godotName = asCString(toGodotName(T))
let singleton = getGodotSingleton(godotName)
if singleton.isNil:
printError("Tried to get non-existing singleton of type " & $godotName)
@ -366,7 +373,7 @@ proc newOwnObj[T: NimGodotObject](name: cstring): T =
proc gdnew*[T: NimGodotObject](): T =
## Instantiates new object of type ``T``.
const godotName = toGodotName(T)
const godotName = asCString(toGodotName(T))
const objInfo = classRegistryStatic[godotName]
result = when objInfo.isNative:
asNimGodotObject[T](getClassConstructor(godotName)())
@ -432,7 +439,8 @@ proc godotObject*(nimObj: NimGodotObject): ptr GodotObject {.inline.} =
proc godotTypeInfo*(T: typedesc[NimGodotObject]): GodotTypeInfo {.inline.} =
GodotTypeInfo(
variantType: VariantType.Object,
hint: GodotPropertyHint.None,
hint: when isResource(T): GodotPropertyHint.ResourceType
else: GodotPropertyHint.None,
hintStr: toGodotName(T)
)