123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629 |
- // Copyright © 2019 - 2020 Oscar Campos <oscar.campos@thepimpam.com>
- // Copyright © 2017 - William Edwards
- //
- // Licensed under the Apache License, Version 2.0 (the "License");
- // you may not use this file except in compliance with the License.
- // You may obtain a copy of the License at
- //
- // http://www.apache.org/licenses/LICENSE-2.0
- //
- // Unless required by applicable law or agreed to in writing, software
- // distributed under the License is distributed on an "AS IS" BASIS,
- // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- // See the License for the specific language governing permissions and
- // limitations under the License
- // Package gdnative provides a wrapper around Godot's nativescript
- // extension. It exists to provide a way to use Go as an alternative scripting
- // language from GDScript.
- package gdnative
- /*
- #include <nativescript/godot_nativescript.h>
- #include "nativescript.gen.h"
- #include "nativescript.h"
- #include "variant.h"
- */
- import "C"
- import (
- "log"
- "unsafe"
- )
- // PropertyUsageFlags is a Godot C godot_property_usage_flags wrapper
- type PropertyUsageFlags int
- func (p PropertyUsageFlags) getBase() C.godot_property_usage_flags {
- return C.godot_property_usage_flags(p)
- }
- // Property usage flags for bit masks
- const (
- PropertyUsageStorage PropertyUsageFlags = 1
- PropertyUsageEditor PropertyUsageFlags = 2
- PropertyUsageNetwork PropertyUsageFlags = 4
- PropertyUsageEditorHelper PropertyUsageFlags = 8
- PropertyUsageCheckable PropertyUsageFlags = 16 //used for editing global variables
- PropertyUsageChecked PropertyUsageFlags = 32 //used for editing global variables
- PropertyUsageInternationalized PropertyUsageFlags = 64 //hint for internationalized strings
- PropertyUsageGroup PropertyUsageFlags = 128 //used for grouping props in the editor
- PropertyUsageCategory PropertyUsageFlags = 256
- PropertyUsageStoreIfNonZero PropertyUsageFlags = 512 //only store if nonzero
- PropertyUsageStoreIfNonOne PropertyUsageFlags = 1024 //only store if false
- PropertyUsageNoInstanceState PropertyUsageFlags = 2048
- PropertyUsageRestartIfChanged PropertyUsageFlags = 4096
- PropertyUsageScriptVariable PropertyUsageFlags = 8192
- PropertyUsageStoreIfNull PropertyUsageFlags = 16384
- PropertyUsageAnimateAsTrigger PropertyUsageFlags = 32768
- PropertyUsageUpdateAllIfModified PropertyUsageFlags = 65536
- PropertyUsageDefault PropertyUsageFlags = PropertyUsageStorage | PropertyUsageEditor | PropertyUsageNetwork
- PropertyUsageDefaultIntl PropertyUsageFlags = PropertyUsageStorage | PropertyUsageEditor | PropertyUsageNetwork | PropertyUsageInternationalized
- PropertyUsageNoEditor PropertyUsageFlags = PropertyUsageStorage | PropertyUsageNetwork
- )
- // PropertyUsageFlagsLookupMap is a string-based lookup table of constants for PropertyUsageFlags.
- var PropertyUsageFlagsLookupMap = map[string]PropertyUsageFlags{
- "PropertyUsageStorage": PropertyUsageStorage,
- "PropertyUsageEditor": PropertyUsageEditor,
- "PropertyUsageNetwork": PropertyUsageNetwork,
- "PropertyUsageEditorHelper": PropertyUsageEditorHelper,
- "PropertyUsageCheckable": PropertyUsageCheckable,
- "PropertyUsageChecked": PropertyUsageChecked,
- "PropertyUsageInternationalized": PropertyUsageInternationalized,
- "PropertyUsageGroup": PropertyUsageGroup,
- "PropertyUsageCategory": PropertyUsageCategory,
- "PropertyUsageStoreIfNonZero": PropertyUsageStoreIfNonZero,
- "PropertyUsageStoreIfNonOne": PropertyUsageStoreIfNonOne,
- "PropertyUsageNoInstanceState": PropertyUsageNoInstanceState,
- "PropertyUsageRestartIfChanged": PropertyUsageRestartIfChanged,
- "PropertyUsageScriptVariable": PropertyUsageScriptVariable,
- "PropertyUsageStoreIfNull": PropertyUsageStoreIfNull,
- "PropertyUsageAnimateAsTrigger": PropertyUsageAnimateAsTrigger,
- "PropertyUsageUpdateAllIfModified": PropertyUsageUpdateAllIfModified,
- "PropertyUsageDefault": PropertyUsageDefault,
- "PropertyUsageDefaultIntl": PropertyUsageDefaultIntl,
- "PropertyUsageNoEditor": PropertyUsageNoEditor,
- }
- // CreateFunc will be called when we need to create a new instance of a class.
- // When it is called, the Godot object will passed as an argument, as well as the
- // methodData string, which is usually the name of the class to be created.
- type CreateFunc func(Object, string) string
- // CreateFuncRegistry is a mapping of instance creation functions. This map is
- // used whenever a CreateFunc is registered. It is also used to look up a
- // Creation function when Godot asks Go to create a new class instance.
- var CreateFuncRegistry = map[string]CreateFunc{}
- // DestroyFunc will be called when the object is destroyed. Takes the instance
- // object, method data, user data. The method data is generally the class name,
- // and the user data is generally the class instance id to destroy.
- type DestroyFunc func(Object, string, string)
- // DestroyFuncRegistry is a mapping of instance destroy functions. This map is
- // used whenever a DestroyFunc is registered. It is also used to look up a
- // Destroy function when Godot asks Go to destroy a class instance.
- var DestroyFuncRegistry = map[string]DestroyFunc{}
- // FreeFunc will be called when we should free the instance from memory. Takes
- // in method data. The method data is generally the class name to be freed.
- type FreeFunc func(string)
- // SetPropertyFunc will be called when Godot requests to set a property on a given
- // class. When it is called, the Godot object instance will be passed as an argument,
- // as well as the methodData (which is usually the name of the class), the
- // userData (which is generally the instance ID of the object), and the value
- // to set.
- type SetPropertyFunc func(Object, string, string, Variant)
- // SetPropertyFuncRegistry is a mapping of instance property setters. This map is
- // used whenever a SetPropertyFunc is registered. It is also used to look up
- // a property setter function when Godot asks Go to set a property on an object.
- var SetPropertyFuncRegistry = map[string]SetPropertyFunc{}
- // GetPropertyFunc will be called when Godot requests a property on a given class
- // instance. When it is called, Godot will pass the Godot object instance as an
- // argument, as well as the methodData (which is usually the name of the class),
- // and the userData (which is generally the instance ID of the object. You should
- // return the property as a Variant.
- type GetPropertyFunc func(Object, string, string) Variant
- // GetPropertyFuncRegistry is a mapping of instance property getters. This map is
- // used whenever a GetPropertyFunc is registered. It is also used to look up a
- // property getter function when Godot asks Go to get a property on an object.
- var GetPropertyFuncRegistry = map[string]GetPropertyFunc{}
- // FreeFuncRegistry is a mapping of instance free functions. This map is used
- // whenever a FreeFunc is registered. It is also used to look up a Free
- // function when Godot asks Go to free a class instance.
- var FreeFuncRegistry = map[string]FreeFunc{}
- // MethodFunc will be called when a method attached to an instance is called.
- // When it is called, it will be passed the Godot object the method is attached to,
- // the methodData string (which is usually the class and method name that is being called),
- // the userData string (which is usually the class instance ID), the number of
- // arguments being passed to the function, and a list of Variant arguments to pass
- // to the function.
- type MethodFunc func(Object, string, string, int, []Variant) Variant
- // MethodFuncRegistry is a mapping of instance method functions. This map is
- // used whenever a MethodFunc is registered. It is also used to look up a Method
- // function when Godot asks Go to call a class method.
- var MethodFuncRegistry = map[string]MethodFunc{}
- // InstanceCreateFunc is a structure that contains the instance creation function
- // that will be called when Godot asks Go to create a new instance of a class.
- type InstanceCreateFunc struct {
- base C.godot_instance_create_func
- CreateFunc CreateFunc
- MethodData string
- FreeFunc FreeFunc
- }
- func (i *InstanceCreateFunc) getBase() C.godot_instance_create_func {
- return i.base
- }
- // InstanceDestroyFunc is a structure that contains the instance destruction function
- // that will be called when Godot asks Go to destroy a class instance.
- type InstanceDestroyFunc struct {
- base C.godot_instance_destroy_func
- DestroyFunc DestroyFunc
- MethodData string
- FreeFunc FreeFunc
- }
- func (i *InstanceDestroyFunc) getBase() C.godot_instance_destroy_func {
- return i.base
- }
- // InstanceMethod is a structure that contains an instance method function that
- // will be called when Godot asks Go to call a method on a class.
- type InstanceMethod struct {
- base C.godot_instance_method
- Method MethodFunc
- MethodData string
- FreeFunc FreeFunc
- }
- func (i *InstanceMethod) getBase() C.godot_instance_method {
- return i.base
- }
- // MethodAttributes is a Godot C godot_method_attributes wrapper
- type MethodAttributes struct {
- base C.godot_method_attributes
- RPCType MethodRpcMode
- }
- func (m *MethodAttributes) getBase() C.godot_method_attributes {
- return m.base
- }
- // InstancePropertySet is a structure that contains an instance property setter
- // function that will be called when Godot asks Go to set a property on a class.
- type InstancePropertySet struct {
- base C.godot_property_set_func
- SetFunc SetPropertyFunc
- MethodData string
- FreeFunc FreeFunc
- }
- func (i *InstancePropertySet) getBase() C.godot_property_set_func {
- return i.base
- }
- // InstancePropertyGet is a structure that contains an instance property getter
- // function that will be called when Godot asks Go to get a property from a class
- // instance.
- type InstancePropertyGet struct {
- base C.godot_property_get_func
- GetFunc GetPropertyFunc
- MethodData string
- FreeFunc FreeFunc
- }
- func (i *InstancePropertyGet) getBase() C.godot_property_get_func {
- return i.base
- }
- // NativeScript is a wrapper for the NativeScriptAPI.
- var NativeScript = new(nativeScript)
- // nativeScript is a structure that wraps the NativeScriptAPI methods.
- type nativeScript struct {
- api *C.godot_gdnative_ext_nativescript_api_struct
- // Handle is a pointer to the gdnative handler. It must be passed to any
- // Godot nativescript functions. This will be populated when 'godot_nativescript_init'
- // is called by Godot upon script initialization.
- handle unsafe.Pointer
- }
- // RegisterClass will register the given class with Godot. This will make it
- // available to be attached to a Node in Godot. The name of the class that you
- // provide here will be the name that you specify when you attach a NativeScript
- // script to a Node. The base parameter that you specify will be what the class
- // should be inheriting from (e.g. Node2D, Node, etc.).
- //
- // The create and destroy function parameters are C structs that contain
- // function pointers to C methods that will be called when the object is created
- // or destroyed. Because of the pointer passing rules, Go code can not pass a
- // function value directly to C, so a gateway function should be used. More
- // information on using a gateway function can be found here:
- // https://github.com/golang/go/wiki/cgo#function-variables
- func (n *nativeScript) RegisterClass(name, base string, createFunc *InstanceCreateFunc, destroyFunc *InstanceDestroyFunc) {
- // Construct the C struct based on the Go struct wrappers
- createFunc.base.create_func = (C.create_func)(unsafe.Pointer(C.cgo_gateway_create_func))
- createFunc.base.method_data = unsafe.Pointer(C.CString(createFunc.MethodData))
- createFunc.base.free_func = (C.free_func)(unsafe.Pointer(C.cgo_gateway_free_func))
- destroyFunc.base.destroy_func = (C.destroy_func)(unsafe.Pointer(C.cgo_gateway_destroy_func))
- destroyFunc.base.method_data = unsafe.Pointer(C.CString(destroyFunc.MethodData))
- destroyFunc.base.free_func = (C.free_func)(unsafe.Pointer(C.cgo_gateway_free_func))
- // Register our Create and Destroy functions in a Go map, so the correct
- // function can be called when cgo_gateway_<type>_func is called.
- CreateFuncRegistry[createFunc.MethodData] = createFunc.CreateFunc
- FreeFuncRegistry[createFunc.MethodData] = createFunc.FreeFunc
- DestroyFuncRegistry[destroyFunc.MethodData] = destroyFunc.DestroyFunc
- FreeFuncRegistry[destroyFunc.MethodData] = destroyFunc.FreeFunc
- // Register the class with Godot.
- C.go_godot_nativescript_register_class(
- n.api,
- n.handle,
- C.CString(name),
- C.CString(base),
- createFunc.getBase(),
- destroyFunc.getBase(),
- )
- }
- // RegisterToolClass will register the given class with Godot as a tool. Refer to
- // the 'RegisterClass' method for more information on how to use this.
- func (n *nativeScript) RegisterToolClass(name, base string, createFunc *InstanceCreateFunc, destroyFunc *InstanceDestroyFunc) {
- // Construct the C struct based on the Go struct wrappers
- createFunc.base.create_func = (C.create_func)(unsafe.Pointer(C.cgo_gateway_create_func))
- createFunc.base.method_data = unsafe.Pointer(C.CString(createFunc.MethodData))
- createFunc.base.free_func = (C.free_func)(unsafe.Pointer(C.cgo_gateway_free_func))
- destroyFunc.base.destroy_func = (C.destroy_func)(unsafe.Pointer(C.cgo_gateway_destroy_func))
- destroyFunc.base.method_data = unsafe.Pointer(C.CString(destroyFunc.MethodData))
- destroyFunc.base.free_func = (C.free_func)(unsafe.Pointer(C.cgo_gateway_free_func))
- // Register our Create and Destroy functions in a Go map, so the correct
- // function can be called when cgo_gateway_<type>_func is called.
- CreateFuncRegistry[createFunc.MethodData] = createFunc.CreateFunc
- FreeFuncRegistry[createFunc.MethodData] = createFunc.FreeFunc
- DestroyFuncRegistry[destroyFunc.MethodData] = destroyFunc.DestroyFunc
- FreeFuncRegistry[destroyFunc.MethodData] = destroyFunc.FreeFunc
- // Register the class with Godot.
- C.go_godot_nativescript_register_tool_class(
- n.api,
- n.handle,
- C.CString(name),
- C.CString(base),
- createFunc.getBase(),
- destroyFunc.getBase(),
- )
- }
- // RegisterMethod will register the given method with Godot and associate it with
- // the given class name. The name parameter is the name of the class you wish to
- // attach this method to. The funcName parameter is the name of the function you
- // want to register. The attributes and method are what will actually be called
- // when Godot calls the method on the object.
- func (n *nativeScript) RegisterMethod(name, funcName string, attributes *MethodAttributes, method *InstanceMethod) {
- // Construct the C struct based on the Go struct wrappers
- attributes.base.rpc_type = attributes.RPCType.getBase()
- method.base.method = (C.method)(unsafe.Pointer(C.cgo_gateway_method_func))
- method.base.method_data = unsafe.Pointer(C.CString(method.MethodData))
- method.base.free_func = (C.free_func)(unsafe.Pointer(C.cgo_gateway_free_func))
- // Register the Method function in a Go map, so the correct function can
- // be called when cgo_gateway_<type>_func is called.
- MethodFuncRegistry[method.MethodData] = method.Method
- FreeFuncRegistry[method.MethodData] = method.FreeFunc
- // Register the method with Godot.
- C.go_godot_nativescript_register_method(
- n.api,
- n.handle,
- C.CString(name),
- C.CString(funcName),
- attributes.getBase(),
- method.getBase(),
- )
- }
- // RegisterProperty will register the given property with Godot and associate it
- // with the given class name. The name parameter is the name of the class you wish
- // to attach this property to. The path is the name of the property itself. The
- // attributes and setter/getter methods are what will be called when Godot gets
- // or sets this property.
- //func (n *nativeScript) RegisterProperty(name, path string, attributes *C.godot_property_attributes, setFunc C.godot_property_set_func, getFunc C.godot_property_get_func) {
- func (n *nativeScript) RegisterProperty(name, path string, attributes *PropertyAttributes, setFunc *InstancePropertySet, getFunc *InstancePropertyGet) {
- // Construct the C struct based on the attributes Go wrapper
- var attr C.godot_property_attributes
- attributes.base = &attr
- attributes.base.rset_type = attributes.RsetType.getBase()
- attributes.base._type = attributes.Type.getBase()
- attributes.base.hint = attributes.Hint.getBase()
- attributes.base.hint_string = *(attributes.HintString.getBase())
- attributes.base.usage = attributes.Usage.getBase()
- attributes.base.default_value = *(attributes.DefaultValue.getBase())
- // Construct the C struct based on the setFunc Go wrapper
- setFunc.base.set_func = (C.set_property_func)(unsafe.Pointer(C.cgo_gateway_property_set_func))
- setFunc.base.method_data = unsafe.Pointer(C.CString(setFunc.MethodData))
- setFunc.base.free_func = (C.free_func)(unsafe.Pointer(C.cgo_gateway_free_func))
- // Construct the C struct based on the getFunc Go wrapper
- getFunc.base.get_func = (C.get_property_func)(unsafe.Pointer(C.cgo_gateway_property_get_func))
- getFunc.base.method_data = unsafe.Pointer(C.CString(getFunc.MethodData))
- getFunc.base.free_func = (C.free_func)(unsafe.Pointer(C.cgo_gateway_free_func))
- // Register the set/get property functions in a Go map, so the correct function can
- // be called when cgo_gateway_<type>_func is called.
- SetPropertyFuncRegistry[setFunc.MethodData] = setFunc.SetFunc
- GetPropertyFuncRegistry[getFunc.MethodData] = getFunc.GetFunc
- FreeFuncRegistry[setFunc.MethodData] = setFunc.FreeFunc
- FreeFuncRegistry[getFunc.MethodData] = getFunc.FreeFunc
- // Register the property with Godot.
- C.go_godot_nativescript_register_property(
- n.api,
- n.handle,
- C.CString(name),
- C.CString(path),
- attributes.getBase(),
- setFunc.getBase(),
- getFunc.getBase(),
- )
- }
- // RegisterSignal will register the given signal with Godot.
- func (n *nativeScript) RegisterSignal(name string, signal *Signal) {
- // Construct the C struct based on the signal Go wrapper
- var base C.godot_signal
- signal.base = (*C.godot_signal)(unsafe.Pointer(&base))
- signal.base.name = *(signal.Name.getBase())
- signal.base.num_args = signal.NumArgs.getBase()
- signal.base.num_default_args = signal.NumDefaultArgs.getBase()
- // Build the arguments
- // argsArray := C.go_godot_signal_argument_build_array(C.int(signal.NumArgs))
- argsArray := make([]*C.godot_signal_argument, int(signal.NumArgs))
- for i, arg := range signal.Args {
- cArg := C.go_godot_new_signal_argument()
- (*cArg).name = *(arg.Name.getBase())
- (*cArg)._type = arg.Type.getBase()
- (*cArg).default_value = *(arg.DefaultValue.getBase())
- (*cArg).hint = arg.Hint.getBase()
- (*cArg).hint_string = *(arg.HintString.getBase())
- (*cArg).usage = arg.Usage.getBase()
- argsArray[i] = cArg
- }
- signal.base.args = argsArray[0]
- // Build the default arguments
- variantArray := C.go_godot_variant_build_array(C.int(signal.NumDefaultArgs))
- for i, variant := range signal.DefaultArgs {
- C.go_godot_variant_add_element(variantArray, variant.getBase(), C.int(i))
- }
- signal.base.default_args = *(**C.godot_variant)(unsafe.Pointer(&variantArray))
- // Register the signal with Godot.
- C.go_godot_nativescript_register_signal(
- n.api,
- n.handle,
- C.CString(name),
- signal.getBase(),
- )
- }
- // nativeScriptInit will be called when `godot_nativescript_init` is called by
- // Godot. You can use `SetNativeScriptInit` to set the function that will be called
- // when NativeScript initializes.
- var nativeScriptInit = []func(){}
- // SetNativeScriptInit will configure the given function to be called when
- // `godot_nativescript_init` is called by Godot upon NativeScript initialization.
- // This is used so you can define a function that will run to register all of the
- // classes that you want exposed to Godot.
- func SetNativeScriptInit(initFunc ...func()) {
- nativeScriptInit = append(nativeScriptInit, initFunc...)
- }
- /*------------------------------------------------------------------------------
- // Exported C Functions
- //
- // The methods below are special C exported functions. They can be called by
- // Godot directly or by one of the C gateway functions defined in
- // nativescript.c.
- //
- //----------------------------------------------------------------------------*/
- /** Script entry (Registering all the classes and stuff) **/
- // godot_nativescript_init is the script's entrypoint. It is called by Godot
- // when a script is loaded. It is responsible for registering all the classes,
- // etc. The `unsafe.Pointer` type is used to represent a void C pointer.
- //export godot_nativescript_init
- func godot_nativescript_init(hdl unsafe.Pointer) {
- if debug {
- log.Println("Initializing NativeScript")
- }
- NativeScript.handle = hdl
- // Call the user-defined nativeScriptInit function
- if nativeScriptInit == nil {
- err := "NativeScript initialization function was not set! Use `gdnative.SetNativeScriptInit` to define the function that will run to register classes."
- log.Println(err)
- Log.Error(err)
- return
- }
- // Loop through any defined nativeScriptInit methods and execute them.
- for _, init := range nativeScriptInit {
- init()
- }
- }
- // This is a native Go function that is callable from C. It is called by the
- // gateway functions defined in nativescript.c. It will be ultimately called by
- // Godot, where it will pass us the Godot object and the MethodData defined in
- // CreateFunc. We will need to return UserData, which can be used to track the
- // actual instance that was created.
- //export go_create_func
- func go_create_func(godotObject *C.godot_object, methodData unsafe.Pointer) unsafe.Pointer {
- // Convert the method data into a Go string.
- methodDataString := unsafeToGoString(methodData)
- if debug {
- log.Println("Create function called for:", methodDataString)
- }
- // Look up the creation function in our CreateFuncRegistry for the function
- // to call.
- constructor := CreateFuncRegistry[methodDataString]
- // Call the constructor and return the user data string. The user data
- // returned by the create func will be passed to the method function as
- // userData.
- userData := constructor(Object{base: godotObject}, methodDataString)
- return unsafe.Pointer(C.CString(userData))
- }
- // This is a native Go function that is callable from C. It is called by the
- // gateway functions defined in nativescript.c. It will use the userData passed to it,
- // which is a CString of the instance id, which we can use to delete the instance
- // from the instance registry. This will make the instance available to be garbage
- // collected.
- //export go_destroy_func
- func go_destroy_func(godotObject *C.godot_object, methodData unsafe.Pointer, userData unsafe.Pointer) {
- // Convert the method data and user data into a Go string
- methodDataString := unsafeToGoString(methodData)
- userDataString := unsafeToGoString(userData)
- if debug {
- log.Println("Destroy function called for:", methodDataString)
- }
- // Look up the destroy function in our DestroyFuncRegistry for the function
- // to call.
- destructor := DestroyFuncRegistry[methodDataString]
- // Call the destructor function. We pass the methodData and userData to
- // the destructor so it knows which class and instance to destroy.
- destructor(Object{base: godotObject}, methodDataString, userDataString)
- }
- //export go_free_func
- func go_free_func(methodData unsafe.Pointer) {
- // Convert the method data and user data into a Go string
- methodDataString := unsafeToGoString(methodData)
- if debug {
- log.Println("Free function called for:", methodDataString)
- }
- // Look up the free function in our FreeFuncRegistry for the function
- // to call.
- freer := FreeFuncRegistry[methodDataString]
- // Call the free function. We pass the methodData to the free
- // function so it knows which class to free.
- freer(methodDataString)
- }
- // This is a native Go function that is callable from C. It is called by the
- // gateway functions defined in nativescript.c.
- //export go_method_func
- func go_method_func(godotObject *C.godot_object, methodData unsafe.Pointer, userData unsafe.Pointer, numArgs C.int, args **C.godot_variant) C.godot_variant {
- // Convert the method data and user data into a Go string
- methodDataString := unsafeToGoString(methodData)
- userDataString := unsafeToGoString(userData)
- // Create a slice of Variants for the arguments
- variantArgs := []Variant{}
- // Get the size of each godot_variant object pointer.
- if debug {
- log.Println(" Getting size of argument pointer")
- }
- size := unsafe.Sizeof(*args)
- // Panic if something's wrong.
- if int(numArgs) > 50 {
- panic("Too many arguments. Invalid method.")
- }
- // If we have arguments, append the first argument.
- if int(numArgs) > 0 {
- arg := args
- // Loop through all our arguments.
- for i := 0; i < int(numArgs); i++ {
- // Convert the variant into a Go Variant
- variant := Variant{base: *arg}
- // Append the variant to our list of variants
- variantArgs = append(variantArgs, variant)
- // Convert the pointer into a uintptr so we can perform arithmetic on it.
- arrayPtr := uintptr(unsafe.Pointer(arg))
- // Add the size of the godot_variant pointer to our array pointer to get the position
- // of the next argument.
- arg = (**C.godot_variant)(unsafe.Pointer(arrayPtr + size))
- }
- }
- // Look up the method function in our MethodFuncRegistry for the function
- // to call.
- method := MethodFuncRegistry[methodDataString]
- // Call the method
- ret := method(Object{base: godotObject}, methodDataString, userDataString, int(numArgs), variantArgs)
- return *ret.getBase()
- }
- // This is a native Go function that is callable from C. It is called by the
- // gateway functions defined in nativescript.c.
- //export go_set_property_func
- func go_set_property_func(godotObject *C.godot_object, methodData unsafe.Pointer, userData unsafe.Pointer, property *C.godot_variant) {
- // Convert the method data and user data into a Go string
- methodDataString := unsafeToGoString(methodData)
- userDataString := unsafeToGoString(userData)
- // Convert the property into a Go variant
- variant := Variant{base: property}
- // Look up the set property function in our SetPropertyFuncRegistry for
- // the function to call.
- setFunc := SetPropertyFuncRegistry[methodDataString]
- // Call the method
- setFunc(Object{base: godotObject}, methodDataString, userDataString, variant)
- }
- // This is a native Go function that is callable from C. It is called by the
- // gateway functions defined in nativescript.c.
- //export go_get_property_func
- func go_get_property_func(godotObject *C.godot_object, methodData unsafe.Pointer, userData unsafe.Pointer) C.godot_variant {
- // Convert the method data and user data into a Go string
- methodDataString := unsafeToGoString(methodData)
- userDataString := unsafeToGoString(userData)
- // Look up the get property function in our GetPropertyFuncRegistry for
- // the function to call.
- getFunc := GetPropertyFuncRegistry[methodDataString]
- // Call the method
- ret := getFunc(Object{base: godotObject}, methodDataString, userDataString)
- return *ret.getBase()
- }
|