Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Exception: Calling method on destroyed Scene when Scene is shown and hidden in Compose #444

Closed
wilfredbtan opened this issue Mar 19, 2024 · 2 comments

Comments

@wilfredbtan
Copy link

This exception is being raised when I show and hide a Scene in Compose: java.lang.IllegalStateException: Calling method on destroyed Scene

Code:

val cameraNode = rememberCameraNode(engine) {
    position = Position(z = 4.0f)
}

val centerNode = rememberNode(engine)
    .addChildNode(cameraNode)                // <- 1

// Environment and other parameters omitted for brevity. 
// The exception doesn't seem to be affected by those parameters.

Scene(
    modifier = Modifier
        .fillMaxSize(),
    engine = engine,
    modelLoader = modelLoader,
    // cameraNode = cameraNode,              // Still crashes even after this is commented out
    childNodes = listOf(
        centerNode,                          // <- 2
    ),
    view = view,
    onFrame = {
        // cameraNode.lookAt(centerNode)     // Still crashes even after this is commented out
    },
)

Commenting either 1. or 2. stops the exception from being raised

This is the full stacktrace:

FATAL EXCEPTION: main
Process: com.wilfredbtan.choreographic, PID: 26872
java.lang.IllegalStateException: Calling method on destroyed Scene
     at com.google.android.filament.Scene.getNativeObject(Scene.java:189)
     at com.google.android.filament.Scene.removeEntities(Scene.java:146)
     at io.github.sceneview.SceneView.removeEntities(SceneView.kt:701)
     at io.github.sceneview.SceneView.removeNode$sceneview_release(SceneView.kt:679)
     at io.github.sceneview.SceneView$addNode$2.invoke(SceneView.kt:672)
     at io.github.sceneview.SceneView$addNode$2.invoke(SceneView.kt:672)
     at io.github.sceneview.node.Node.setChildNodes(Node.kt:351)
     at io.github.sceneview.node.Node.setParent(Node.kt:335)
     at io.github.sceneview.node.Node.destroy(Node.kt:1006)
     at io.github.sceneview.node.CameraNode.destroy(CameraNode.kt:328)
     at io.github.sceneview.SceneKt$rememberCameraNode$$inlined$rememberNode$1$1.dispose(Effects.kt:497)
     at androidx.compose.runtime.DisposableEffectImpl.onForgotten(Effects.kt:87)
     at androidx.compose.runtime.CompositionImpl$RememberEventDispatcher.dispatchRememberObservers(Composition.kt:1276)
     at androidx.compose.runtime.CompositionImpl.applyChangesInLocked(Composition.kt:984)
     at androidx.compose.runtime.CompositionImpl.applyChanges(Composition.kt:1005)
     at androidx.compose.runtime.Recomposer$runRecomposeAndApplyChanges$2$1.invoke(Recomposer.kt:639)
     at androidx.compose.runtime.Recomposer$runRecomposeAndApplyChanges$2$1.invoke(Recomposer.kt:551)
     at androidx.compose.ui.platform.AndroidUiFrameClock$withFrameNanos$2$callback$1.doFrame(AndroidUiFrameClock.android.kt:41)
     at androidx.compose.ui.platform.AndroidUiDispatcher.performFrameDispatch(AndroidUiDispatcher.android.kt:109)
     at androidx.compose.ui.platform.AndroidUiDispatcher.access$performFrameDispatch(AndroidUiDispatcher.android.kt:41)
     at androidx.compose.ui.platform.AndroidUiDispatcher$dispatchCallback$1.doFrame(AndroidUiDispatcher.android.kt:69)
     at android.view.Choreographer$CallbackRecord.run(Choreographer.java:1299)
     at android.view.Choreographer$CallbackRecord.run(Choreographer.java:1309)
     at android.view.Choreographer.doCallbacks(Choreographer.java:923)
     at android.view.Choreographer.doFrame(Choreographer.java:847)
     at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:1283)
     at android.os.Handler.handleCallback(Handler.java:942)
     at android.os.Handler.dispatchMessage(Handler.java:99)
     at android.os.Looper.loopOnce(Looper.java:226)
     at android.os.Looper.loop(Looper.java:313)
     at android.app.ActivityThread.main(ActivityThread.java:8757)
     at java.lang.reflect.Method.invoke(Native Method)
     at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:571)
     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1067)

Other info:
SceneView Version: 2.0.4
Android Version: 13
Device: Samsung Galaxy A54

Is anyone able to help me with this? Thanks in advance!

@wilfredbtan
Copy link
Author

Solved by declaring the CameraNode as such:

val cameraNode = remember {
    SceneView.createCameraNode(engine).apply {
        position = Position(z = 4.0f)
    }
}

and moving the Disposable Effect after the Scene is declared.

DisposableEffect(cameraNode) {
    onDispose {
        Log.d(DEBUG_TAG, "Destroy Camera")
        cameraNode.destroy()
    }
}

However, I'm not sure if this may result in memory leaks. Will need someone else to advise.

@ThomasGorisse
Copy link
Contributor

Fixed in v2.2.0

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants