gdnew via creating NativeScript

This commit is contained in:
Ruslan Mustakov 2017-07-28 23:11:59 +07:00
commit 04c97656d8
2 changed files with 58 additions and 9 deletions

View file

@ -34,6 +34,7 @@ type
coreApiHash*: uint64 coreApiHash*: uint64
editorApiHash*: uint64 editorApiHash*: uint64
noApiHash*: uint64 noApiHash*: uint64
gdNativeLibrary*: ptr GodotObject
GodotNativeTerminateOptions* = object GodotNativeTerminateOptions* = object
inEditor*: bool inEditor*: bool
@ -234,8 +235,9 @@ proc godotScriptRegisterSignal*(libHandle: pointer; name: cstring;
proc getUserdata*(instance: ptr GodotObject): pointer {. proc getUserdata*(instance: ptr GodotObject): pointer {.
importc: "godot_nativescript_get_userdata".} importc: "godot_nativescript_get_userdata".}
proc godotNew*(p_classname: cstring): ptr GodotObject {. type ClassConstructor = proc (): ptr GodotObject {.noconv.}
importc: "godot_nativescript_new".} proc getClassConstructor*(className: cstring): ClassConstructor {.
importc: "godot_get_class_constructor".}
proc godotStackBottom*(): pointer {. proc godotStackBottom*(): pointer {.
importc: "godot_get_stack_bottom".} importc: "godot_get_stack_bottom".}
@ -256,7 +258,7 @@ proc godotPrintWarning*(description: cstring; function: cstring;
proc godotPrint*(message: GodotString) {. proc godotPrint*(message: GodotString) {.
importc: "godot_print".} importc: "godot_print".}
var getClassMethodBind {.threadvar.}: ptr GodotMethodBind var getClassMethodBind: ptr GodotMethodBind
proc getClassName*(o: ptr GodotObject): string = proc getClassName*(o: ptr GodotObject): string =
if getClassMethodBind.isNil: if getClassMethodBind.isNil:
getClassMethodBind = getMethod(cstring"Object", cstring"get_class") getClassMethodBind = getMethod(cstring"Object", cstring"get_class")

View file

@ -68,6 +68,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]
static:
classRegistryStatic = newTable[cstring, ObjectInfo]()
static: static:
import sets, strutils import sets, strutils
@ -148,12 +151,20 @@ template registerClass*(T: typedesc; godotClassName: cstring,
const base = baseNativeType(T) const base = baseNativeType(T)
const isRef: bool = isReference(T) const isRef: bool = isReference(T)
classRegistry[godotClassName] = ObjectInfo( let objInfo = ObjectInfo(
constructor: constructor, constructor: constructor,
baseNativeClass: base, baseNativeClass: base,
isNative: isNativeParam, isNative: isNativeParam,
isRef: isRef isRef: isRef
) )
classRegistry[godotClassName] = objInfo
static:
let objInfoStatic = ObjectInfo(
baseNativeClass: base,
isNative: isNativeParam,
isRef: isRef
)
classRegistryStatic[godotClassName] = objInfoStatic
when isRef: when isRef:
static: static:
refClasses.add(T.name) refClasses.add(T.name)
@ -237,12 +248,48 @@ proc getSingleton*[T: NimGodotObject](): T =
else: else:
result = asNimGodotObject[T](singleton) result = asNimGodotObject[T](singleton)
var gdNativeLibraryObj: ptr GodotObject
var setClassNameMethod: ptr GodotMethodBind
var setLibraryMethod: ptr GodotMethodBind
var newMethod: ptr GodotMethodBind
type
PtrCallArgType = ptr array[MAX_ARG_COUNT, pointer]
proc newOwnObj[T: NimGodotObject](name: cstring): T =
let newNativeScript = getClassConstructor(cstring"NativeScript")()
if setClassNameMethod.isNil:
setClassNameMethod =
getMethod(cstring"NativeScript", cstring"set_class_name")
if setLibraryMethod.isNil:
setLibraryMethod =
getMethod(cstring"NativeScript", cstring"set_library")
if newMethod.isNil:
newMethod = getMethod(cstring"NativeScript", cstring"new")
var godotStrName = name.toGodotString()
var argPtr: pointer = addr godotStrName
setClassNameMethod.ptrCall(
newNativeScript, cast[PtrCallArgType](addr argPtr), nil)
deinit(godotStrName)
setLibraryMethod.ptrCall(
newNativeScript, cast[PtrCallArgType](addr gdNativeLibraryObj), nil)
var err: VariantCallError
var ret = newMethod.call(newNativeScript, nil, 0, err)
if err.error != VariantCallErrorType.OK:
printError("Failed to invoke 'new' on NativeScript for " & $name)
elif ret.getType() != VariantType.Object:
printError("Expected that NativeScript::new returns Object, " &
"but it returned: " & $ret.getType())
else:
result = asNimGodotObject[T](ret.asGodotObject())
ret.deinit()
proc gdnew*[T: NimGodotObject](): T = proc gdnew*[T: NimGodotObject](): T =
const godotName = toGodotName(T) const godotName = toGodotName(T)
let obj = godotNew(godotName) const objInfo = classRegistryStatic[godotName]
if obj.isNil: result = when objInfo.isNative:
printError("godot_new returned nil for type " & $godotName) asNimGodotObject[T](getClassConstructor(godotName)())
result = asNimGodotObject[T](obj) else: newOwnObj[T](godotName)
proc newCallError*(err: VariantCallError): ref CallError = proc newCallError*(err: VariantCallError): ref CallError =
let msg = case err.error: let msg = case err.error:
@ -583,7 +630,7 @@ proc godot_nativescript_init(handle: pointer) {.
proc godot_gdnative_init(options: ptr GodotNativeInitOptions) {. proc godot_gdnative_init(options: ptr GodotNativeInitOptions) {.
cdecl, exportc, dynlib.} = cdecl, exportc, dynlib.} =
discard gdNativeLibraryObj = options.gdNativeLibrary
proc godot_gdnative_terminate(options: ptr GodotNativeTerminateOptions) {. proc godot_gdnative_terminate(options: ptr GodotNativeTerminateOptions) {.
cdecl, exportc, dynlib.} = cdecl, exportc, dynlib.} =