Skip to content

SceneView: add scene viewpoint operation #240

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

Merged
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ package com.arcgismaps.toolkit.geocompose

import androidx.compose.runtime.Composable
import androidx.compose.runtime.DisposableEffect
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalContext
Expand All @@ -34,12 +35,14 @@ import com.arcgismaps.mapping.view.SceneView
*
* @param modifier Modifier to be applied to the composable SceneView
* @param arcGISScene the [ArcGISScene] to be rendered by this composable SceneView
* @param viewpointOperation a [SceneViewpointOperation] that changes this SceneView to a new viewpoint
* @since 200.4.0
*/
@Composable
public fun SceneView(
modifier: Modifier = Modifier,
arcGISScene: ArcGISScene? = null
arcGISScene: ArcGISScene? = null,
viewpointOperation: SceneViewpointOperation? = null,
) {
val lifecycleOwner = LocalLifecycleOwner.current
val context = LocalContext.current
Expand All @@ -59,4 +62,22 @@ public fun SceneView(
sceneView.onDestroy(lifecycleOwner)
}
}

ViewpointUpdater(sceneView = sceneView, viewpointOperation = viewpointOperation)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
ViewpointUpdater(sceneView = sceneView, viewpointOperation = viewpointOperation)
ViewpointUpdater(sceneView, viewpointOperation)

}

/**
* Updates the viewpoint of the provided view-based [sceneView] using the given [viewpointOperation]. This will be
* recomposed when [viewpointOperation] changes.
*
* @since 200.4.0
*/
@Composable
private fun ViewpointUpdater(
sceneView: SceneView,
viewpointOperation: SceneViewpointOperation?
) {
LaunchedEffect(viewpointOperation) {
viewpointOperation?.execute(sceneView)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
package com.arcgismaps.toolkit.geocompose

import androidx.compose.runtime.Stable
import com.arcgismaps.mapping.Bookmark
import com.arcgismaps.mapping.Viewpoint
import com.arcgismaps.mapping.view.Camera
import com.arcgismaps.mapping.view.SceneView
import kotlinx.coroutines.CompletableDeferred
import kotlin.coroutines.cancellation.CancellationException
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
import kotlin.coroutines.cancellation.CancellationException
import kotlinx.coroutines.CancellationException



/**
* Defines operations for setting the viewpoint of a composable [SceneView].
*
* @since 200.4.0
*/
@Stable
public sealed class SceneViewpointOperation {
private val deferred = CompletableDeferred<Result<Boolean>>()

/**
* Awaits the completion of this SceneViewpointOperation.
*
* @return a Result returning a boolean used to indicate if the operation completed successfully or not
* @since 200.4.0
*/
public suspend fun await(): Result<Boolean> = deferred.await()

internal fun complete(result: Result<Boolean>) {
deferred.complete(result)
}

/**
* Changes the scene view to the new viewpoint. The viewpoint is updated instantaneously.
*
* @property viewpoint the new viewpoint
* @since 200.4.0
*/
public class Set(public val viewpoint: Viewpoint) : SceneViewpointOperation()

/**
* Animates the scene view to the new viewpoint, taking the given number of seconds to complete the
* navigation.
*
* @property viewpoint the new viewpoint
* @property durationSeconds the duration of the animation in seconds
* @since 200.4.0
*/
public class Animate(
public val viewpoint: Viewpoint,
public val durationSeconds: Float = 0.25f
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It might be better to use Duration here instead of Float. This would also have to be applied to MapViewpointOperation.

) : SceneViewpointOperation()

/**
* Updates the display to the viewpoint specified by the given camera.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
* Updates the display to the viewpoint specified by the given camera.
* Changes the scene view to the viewpoint specified by the given camera. The viewpoint is updated instantaneously.

*
* @property camera the new camera
* @since 200.4.0
*/
public class SetCamera(public val camera: Camera) : SceneViewpointOperation()

/**
* Animates the display to the viewpoint specified by the given camera using the specified duration
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
* Animates the display to the viewpoint specified by the given camera using the specified duration
* Animates the scene view to the viewpoint specified by the given camera using the specified duration

* to arrive.
*
* @property camera the new camera
* @property duration the duration of the animation in seconds
* @since 200.4.0
*/
public class AnimateCamera(
public val camera: Camera,
public val durationSeconds: Float = 0.25f
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As above, should use Duration instead of Float.

) : SceneViewpointOperation()

/**
* Animates the scene view's viewpoint to the viewpoint of the bookmark.
*
* @property bookmark bookmark to set
* @since 200.4.0
*/
public class SetBookmark(public val bookmark: Bookmark) : SceneViewpointOperation()
}

/**
* Executes the [SceneViewpointOperation] on the given view-based [SceneView]. The operation can be awaited using
* [SceneViewpointOperation.await]. If the coroutine on which the viewpoint operation is executed is cancelled,
* for example due to another viewpoint operation being executed, the [SceneViewpointOperation.await] call
* will return a Result with a boolean set to `false`, indicating that the viewpoint operation failed
* to complete.
*
* @param sceneView the view-based SceneView to execute this operation on
* @since 200.4.0
*/
internal suspend fun SceneViewpointOperation.execute(sceneView: SceneView) {
when (this) {
is SceneViewpointOperation.Set -> {
sceneView.setViewpoint(this.viewpoint)
this.complete(Result.success(true))
}
is SceneViewpointOperation.Animate -> {
try {
val result = sceneView.setViewpointAnimated(this.viewpoint, this.durationSeconds)
this.complete(result)
} catch (e: CancellationException) {
this.complete(Result.success(false))
throw e
}
}
is SceneViewpointOperation.AnimateCamera -> {
try {
val result = sceneView.setViewpointCameraAnimated(this.camera, this.durationSeconds)
this.complete(result)
} catch (e: CancellationException) {
this.complete(Result.success(false))
throw e
}
}
is SceneViewpointOperation.SetBookmark -> {
try {
val result = sceneView.setBookmark(this.bookmark)
this.complete(result)
} catch (e: CancellationException) {
this.complete(Result.success(false))
throw e
}
}
is SceneViewpointOperation.SetCamera -> {
sceneView.setViewpointCamera(this.camera)
this.complete(Result.success(true))
}
}
}