All Downloads are FREE. Search and download functionalities are using the official Maven repository.

godot.core.KtObject.kt Maven / Gradle / Ivy

The newest version!
package godot.core

import godot.core.memory.MemoryManager
import godot.core.memory.TransferContext
import godot.util.VoidPtr
import godot.util.nullObjectID
import godot.util.nullptr
import kotlincompile.definitions.GodotJvmBuildConfig

class GodotNotification internal constructor(val block: Any.(Int) -> Unit)

@Suppress("LeakingThis")
abstract class KtObject {

    /** Used to prevent the new method to be executed when called from instantiateWith
     * Instead we use the values set in that class  */
    internal class InitConfiguration {
        var ptr: VoidPtr = nullptr
        var objectID: ObjectID = ObjectID(-1)

        fun reset() {
            ptr = nullptr
            objectID = ObjectID(-1)
        }
    }

    var rawPtr: VoidPtr = nullptr
        set(value) {
            if (GodotJvmBuildConfig.DEBUG) {
                require(field == nullptr) {
                    "rawPtr should only be set once!"
                }
            }
            field = value
        }

    var objectID: ObjectID = nullObjectID
        set(value) {
            if (GodotJvmBuildConfig.DEBUG) {
                require(field == nullObjectID) {
                    "id should only be set once!"
                }
            }
            field = value
        }

    internal var twin: KtObject? = null

    init {
        val config = initConfig.get()

        if (config.ptr != nullptr) {
            // Native object already exists, so we know the id and ptr without going back to the other side.
            rawPtr = config.ptr
            objectID = config.objectID
            config.reset()
            // We don't need to register the instance to the MemoryManager, it is the responsibility of the caller.
        } else {
            // Branch used when created directly from user code. The native object is going to be created here.
            // If the class is a script, the ScriptInstance is going to be created at the same time.
            new(TypeManager.userTypeToId[this::class] ?: -1)
            MemoryManager.registerNewInstance(this)
        }
    }

    protected abstract fun new(scriptIndex: Int)

    @Suppress("NOTHING_TO_INLINE")
    internal inline fun callConstructor(classIndex: Int, scriptIndex: Int): Unit {
        MemoryManager.createNativeObject(classIndex, this, scriptIndex)
        TransferContext.initializeKtObject(this)
    }

    @Suppress("NOTHING_TO_INLINE")
    internal inline fun getSingleton(classIndex: Int) {
        MemoryManager.getSingleton(classIndex)
        TransferContext.initializeKtObject(this)
    }

    @Suppress("FunctionName")
    open fun _notification(): GodotNotification = godotNotification {}

    @Suppress("UNCHECKED_CAST")
    @JvmName("kotlinNotification")
    protected fun  T.godotNotification(block: T.(Int) -> Unit): GodotNotification = GodotNotification(block as Any.(Int) -> Unit)

    @JvmName("godotNotification")
    protected fun  javaGodotNotification(obj: T, block: T.(Int) -> Unit) = obj.godotNotification(block)

    @Suppress("FunctionName")
    /**
     * Called automatically when the Object is destroyed. Note that this method is not available for RefCounted or any of its child class.
     * By the time a RefCounted counter reaches 0, its JVM instance has already being GCed and can't be used anymore.
     */
    open fun _onDestroy() = Unit

    fun free() {
        MemoryManager.freeObject(rawPtr)
    }

    internal companion object {
        private val initConfig = ThreadLocal.withInitial { InitConfiguration() }

        /** When using this constructor, the newly created instances doesn't register itself to the MemoryManager, the caller must do it.*/
        inline operator fun  invoke(rawPtr: VoidPtr, id: Long, constructor: () -> T) = initConfig.get().run {
            ptr = rawPtr
            objectID = ObjectID(id)
            constructor()
        }

    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy