diff --git a/godot/godot.nim b/godot/godot.nim index 3514ea2..eb38a58 100644 --- a/godot/godot.nim +++ b/godot/godot.nim @@ -14,4 +14,4 @@ export godotbase, vector2, rect2, vector3, transform2d, planes, quats, poolarrays, variants export godotmacros, godotnim -export GodotPropertyHint, GodotPropertyUsageFlags \ No newline at end of file +export GodotPropertyHint, GodotPropertyUsage \ No newline at end of file diff --git a/godot/godotinternal.nim b/godot/godotinternal.nim index 754900a..fe253dc 100644 --- a/godot/godotinternal.nim +++ b/godot/godotinternal.nim @@ -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 diff --git a/godot/nim/godotmacros.nim b/godot/nim/godotmacros.nim index 326465f..c96b164 100644 --- a/godot/nim/godotmacros.nim +++ b/godot/nim/godotmacros.nim @@ -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 diff --git a/godot/nim/godotnim.nim b/godot/nim/godotnim.nim index 90c40e5..317abc8 100644 --- a/godot/nim/godotnim.nim +++ b/godot/nim/godotnim.nim @@ -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 `_ 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) )