diff --git a/.idea/.gitignore b/.idea/.gitignore new file mode 100644 index 0000000..26d3352 --- /dev/null +++ b/.idea/.gitignore @@ -0,0 +1,3 @@ +# Default ignored files +/shelf/ +/workspace.xml diff --git a/app/build.gradle b/app/build.gradle deleted file mode 100644 index 6568da3..0000000 --- a/app/build.gradle +++ /dev/null @@ -1,148 +0,0 @@ -apply plugin: 'com.android.application' - -apply plugin: 'kotlin-android' -apply plugin: 'kotlin-parcelize' -apply plugin: 'kotlin-kapt' - -apply plugin: 'androidx.navigation.safeargs.kotlin' - -android { - compileSdkVersion 31 - buildToolsVersion '30.0.3' - defaultConfig { - applicationId 'com.example.app' - minSdkVersion 26 - targetSdkVersion 31 - versionCode 13 - versionName '0.0.1' - } - buildTypes { - debug { - } - } - compileOptions { - sourceCompatibility JavaVersion.VERSION_1_8 - targetCompatibility JavaVersion.VERSION_1_8 - } - kotlinOptions { - jvmTarget = '1.8' - // kotlinOptions.freeCompilerArgs = ['-Xinline-classes'] - } - buildFeatures.viewBinding = true - // We use the .filamat extension for materials compiled with matc - // Telling aapt to not compress them allows to load them efficiently - aaptOptions { - noCompress 'filamat', 'ktx' - } -} -kapt { - useBuildCache = false -} -dependencies { - implementation(fileTree(dir: "libs", include: ["*.jar"])) - - implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version" - - api 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.5.2' - api 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.5.2' - api 'org.jetbrains.kotlinx:kotlinx-coroutines-play-services:1.5.2' - - api 'androidx.appcompat:appcompat:1.3.1' - - implementation 'androidx.arch.core:core-common:2.1.0' - implementation 'androidx.arch.core:core-runtime:2.1.0' - - implementation 'androidx.vectordrawable:vectordrawable:1.1.0' - implementation 'androidx.vectordrawable:vectordrawable-animated:1.1.0' - - implementation 'androidx.dynamicanimation:dynamicanimation-ktx:1.0.0-alpha03' - - implementation 'androidx.interpolator:interpolator:1.0.0' - - api 'androidx.annotation:annotation:1.3.0' - - implementation 'androidx.palette:palette-ktx:1.0.0' - - api 'androidx.savedstate:savedstate:1.1.0' - - api 'androidx.autofill:autofill:1.1.0' - - api 'androidx.transition:transition:1.4.1' - - api 'androidx.biometric:biometric:1.1.0' - - api 'androidx.lifecycle:lifecycle-extensions:2.2.0' - api 'androidx.lifecycle:lifecycle-common-java8:2.4.0' - api 'androidx.lifecycle:lifecycle-livedata-core-ktx:2.4.0' - api 'androidx.lifecycle:lifecycle-livedata-ktx:2.4.0' - api 'androidx.lifecycle:lifecycle-reactivestreams-ktx:2.4.0' - api 'androidx.lifecycle:lifecycle-runtime-ktx:2.4.0' - api 'androidx.lifecycle:lifecycle-viewmodel-ktx:2.4.0' - - api 'androidx.work:work-runtime-ktx:2.7.0' - api 'androidx.work:work-gcm:2.7.0' - - implementation 'androidx.emoji:emoji:1.1.0' - implementation 'androidx.emoji:emoji-appcompat:1.1.0' - - api 'androidx.room:room-runtime:2.3.0' - api 'androidx.room:room-ktx:2.3.0' - kapt 'androidx.room:room-compiler:2.3.0' - - implementation 'androidx.sqlite:sqlite-ktx:2.1.0' - - implementation 'androidx.legacy:legacy-support-v4:1.0.0' - - api 'androidx.constraintlayout:constraintlayout:2.1.1' - api 'androidx.recyclerview:recyclerview:1.2.1' - api 'androidx.coordinatorlayout:coordinatorlayout:1.1.0' - api 'androidx.drawerlayout:drawerlayout:1.1.1' - api 'androidx.swiperefreshlayout:swiperefreshlayout:1.1.0' - api 'androidx.gridlayout:gridlayout:1.0.0' - api 'androidx.cardview:cardview:1.0.0' - api 'androidx.viewpager:viewpager:1.0.0' - api 'androidx.browser:browser:1.4.0' - - api 'androidx.core:core-ktx:1.7.0' - - api 'androidx.slice:slice-builders:1.1.0-alpha02' - api 'androidx.slice:slice-builders-ktx:1.0.0-alpha6' - - api 'androidx.slice:slice-core:1.1.0-alpha02' - api 'androidx.slice:slice-view:1.1.0-alpha02' - - // KTX Extensions - api 'androidx.core:core-ktx:1.7.0' - - api 'androidx.activity:activity-ktx:1.4.0' - - implementation 'androidx.benchmark:benchmark-junit4:1.0.0' - - implementation 'androidx.collection:collection-ktx:1.1.0' - - api 'androidx.fragment:fragment-ktx:1.4.0' - - api 'androidx.navigation:navigation-runtime-ktx:2.3.5' - api 'androidx.navigation:navigation-fragment-ktx:2.3.5' - api 'androidx.navigation:navigation-ui-ktx:2.3.5' - api 'androidx.navigation:navigation-dynamic-features-fragment:2.3.5' - - api 'androidx.paging:paging-common-ktx:3.1.0' - api 'androidx.paging:paging-runtime-ktx:3.1.0' - - implementation 'androidx.preference:preference-ktx:1.1.1' - - implementation 'com.google.android.play:core-ktx:1.8.1' - - api 'com.google.android.material:material:1.5.0-beta01' - - api 'com.google.ar:core:1.28.0' - - api 'com.google.android.filament:filament-android:1.14.0' - api 'com.google.android.filament:filament-utils-android:1.14.0' - api 'com.google.android.filament:gltfio-android:1.14.0' - - // Third Party Dependencies - - implementation 'io.arrow-kt:arrow-fx:0.12.1' -} diff --git a/app/build.gradle.kts b/app/build.gradle.kts new file mode 100644 index 0000000..82814d6 --- /dev/null +++ b/app/build.gradle.kts @@ -0,0 +1,115 @@ +plugins { + alias(libs.plugins.androidApplication) + alias(libs.plugins.kotlinAndroid) + alias(libs.plugins.kotlinxParcelize) + alias(libs.plugins.kotlinxSerialization) + alias(libs.plugins.ksp) + alias(libs.plugins.hilt) +} + +kotlin { +} + +android { + namespace = "com.example.app" + compileSdk = libs.versions.compileSdk.get().toInt() + buildToolsVersion = libs.versions.buildToolsVersion.get() + + signingConfigs { + } + + defaultConfig { + applicationId = "com.example.app" + minSdk = libs.versions.minSdk.get().toInt() + targetSdk = libs.versions.targetSdk.get().toInt() + versionCode = 1 + versionName = "1.0.0" + + // reduces apk sizes by not including unsupported languages + resourceConfigurations += setOf("en") + + vectorDrawables { + useSupportLibrary = true + } + } + + buildTypes { + debug { + applicationIdSuffix = ".debug" + isMinifyEnabled = false + isShrinkResources = false + isDebuggable = true + } + } + + compileOptions { + isCoreLibraryDesugaringEnabled = true + sourceCompatibility = JavaVersion.VERSION_17 + targetCompatibility = JavaVersion.VERSION_17 + } + + kotlinOptions { + jvmTarget = libs.versions.jvmTarget.get() + + freeCompilerArgs = listOf( + "-opt-in=kotlinx.coroutines.FlowPreview", + "-opt-in=kotlinx.coroutines.ExperimentalCoroutinesApi", +// "-opt-in=androidx.compose.foundation.ExperimentalFoundationApi", +// "-opt-in=androidx.compose.foundation.layout.ExperimentalLayoutApi", +// "-opt-in=androidx.compose.material.ExperimentalMaterialApi", +// "-opt-in=androidx.compose.material3.ExperimentalMaterial3Api", +// "-opt-in=androidx.compose.material3.windowsizeclass.ExperimentalMaterial3WindowSizeClassApi", +// "-opt-in=androidx.compose.animation.ExperimentalAnimationApi", +// "-opt-in=androidx.compose.ui.text.ExperimentalTextApi", +// "-opt-in=androidx.compose.ui.ExperimentalComposeUiApi", +// "-opt-in=com.google.accompanist.navigation.material.ExperimentalMaterialNavigationApi", + ) + } + + buildFeatures { + viewBinding = true + compose = true + } + + composeOptions { + kotlinCompilerExtensionVersion = libs.versions.composeCompiler.get() + } + + packaging { + resources { + excludes += "/META-INF/versions/9/previous-compilation-data.bin" + } + } + + lint { + baseline = file("lint-baseline.xml") + } + + // We use the .filamat extension for materials compiled with matc + // Telling aapt to not compress them allows to load them efficiently + androidResources { + noCompress += listOf("filamat", "ktx") + } +} + +dependencies { + coreLibraryDesugaring(libs.desugarJdkLibs) + implementation(platform(libs.composeBom)) + + implementation(libs.hiltAndroid) + ksp(libs.hiltAndroidCompiler) + + implementation(libs.bundles.kotlinx) + implementation(libs.bundles.google) + implementation(libs.bundles.androidx) + implementation(libs.bundles.androidxApp) + implementation(libs.bundles.androidxCompose) + lintChecks(libs.composeLintChecks) + implementation(libs.bundles.filament) + implementation(libs.slf4jSimple) + + implementation(libs.arCore) + implementation(libs.arrowFx) + + testImplementation(libs.bundles.test) +} diff --git a/app/src/main/assets/materials/depth.filamat b/app/src/main/assets/materials/depth.filamat index 080f7dc..66fb710 100644 Binary files a/app/src/main/assets/materials/depth.filamat and b/app/src/main/assets/materials/depth.filamat differ diff --git a/app/src/main/assets/materials/flat.filamat b/app/src/main/assets/materials/flat.filamat index 61693a6..1564ac4 100644 Binary files a/app/src/main/assets/materials/flat.filamat and b/app/src/main/assets/materials/flat.filamat differ diff --git a/app/src/main/assets/materials/shadow.filamat b/app/src/main/assets/materials/shadow.filamat index f905d9f..55c16dc 100644 Binary files a/app/src/main/assets/materials/shadow.filamat and b/app/src/main/assets/materials/shadow.filamat differ diff --git a/app/src/main/assets/materials/textured.filamat b/app/src/main/assets/materials/textured.filamat index a9467a9..a9ca5bf 100644 Binary files a/app/src/main/assets/materials/textured.filamat and b/app/src/main/assets/materials/textured.filamat differ diff --git a/app/src/main/java/com/example/app/Matrix.kt b/app/src/main/java/com/example/app/Matrix.kt index 253fc0d..1f97ef5 100644 --- a/app/src/main/java/com/example/app/Matrix.kt +++ b/app/src/main/java/com/example/app/Matrix.kt @@ -1,5 +1,3 @@ -@file:Suppress("unused") - package com.example.app import android.app.Activity @@ -15,7 +13,10 @@ import java.nio.ByteOrder import java.nio.FloatBuffer import java.nio.ShortBuffer import java.nio.channels.Channels -import kotlin.math.* +import kotlin.math.PI +import kotlin.math.ceil +import kotlin.math.floor +import kotlin.math.sqrt inline val Float.Companion.size get() = java.lang.Float.BYTES @@ -29,21 +30,88 @@ inline val Float.clampToTau: Float when { this < 0f -> this + ceil(-this / Float.tau) * Float.tau + this >= Float.tau -> this - floor(this / Float.tau) * Float.tau + else -> this } -data class V2A(val floatArray: FloatArray) +data class V2A(val floatArray: FloatArray) { + override fun equals(other: Any?): Boolean { + if (this === other) return true + if (javaClass != other?.javaClass) return false + + other as V2A + + return floatArray.contentEquals(other.floatArray) + } + + override fun hashCode(): Int { + return floatArray.contentHashCode() + } +} + +data class V3(val floatArray: FloatArray) { + override fun equals(other: Any?): Boolean { + if (this === other) return true + if (javaClass != other?.javaClass) return false -data class V3(val floatArray: FloatArray) + other as V3 -data class V3A(val floatArray: FloatArray) + return floatArray.contentEquals(other.floatArray) + } + + override fun hashCode(): Int { + return floatArray.contentHashCode() + } +} + +data class V3A(val floatArray: FloatArray) { + override fun equals(other: Any?): Boolean { + if (this === other) return true + if (javaClass != other?.javaClass) return false -data class V4A(val floatArray: FloatArray) + other as V3A + + return floatArray.contentEquals(other.floatArray) + } + + override fun hashCode(): Int { + return floatArray.contentHashCode() + } +} -data class M4(val floatArray: FloatArray) +data class V4A(val floatArray: FloatArray) { + override fun equals(other: Any?): Boolean { + if (this === other) return true + if (javaClass != other?.javaClass) return false + + other as V4A + + return floatArray.contentEquals(other.floatArray) + } + + override fun hashCode(): Int { + return floatArray.contentHashCode() + } +} + +data class M4(val floatArray: FloatArray) { + override fun equals(other: Any?): Boolean { + if (this === other) return true + if (javaClass != other?.javaClass) return false + + other as M4 + + return floatArray.contentEquals(other.floatArray) + } + + override fun hashCode(): Int { + return floatArray.contentHashCode() + } +} @JvmInline value class TriangleIndexArray(val shortArray: ShortArray) @@ -82,14 +150,17 @@ fun M4.translate(x: Float, y: Float, z: Float): M4 = FloatArray(16) .also { Matrix.translateM(it, 0, floatArray, 0, x, y, z) } .let { M4(it) } +@Suppress("unused") fun M4.multiply(m: M4): M4 = FloatArray(16) .also { Matrix.multiplyMM(it, 0, floatArray, 0, m.floatArray, 0) } .let { M4(it) } +@Suppress("unused") fun M4.invert(): M4 = FloatArray(16) .also { Matrix.invertM(it, 0, floatArray, 0) } .let { M4(it) } +@Suppress("unused") fun m4Rotate(angle: Float, x: Float, y: Float, z: Float): M4 = FloatArray(16) .also { Matrix.setRotateM(it, 0, angle, x, y, z) } .let { M4(it) } @@ -102,7 +173,7 @@ fun FloatArray.toDoubleArray(): DoubleArray = DoubleArray(size) } fun Frame.projectionMatrix(): M4 = FloatArray(16) - .apply { camera.getProjectionMatrix(this, 0, ArCore.near, ArCore.far) } + .apply { camera.getProjectionMatrix(this, 0, ArCore.NEAR, ArCore.FAR) } .let { M4(it) } @Suppress("DEPRECATION") @@ -110,7 +181,7 @@ fun Activity.displayRotation(): Int = (if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) display else windowManager.defaultDisplay)!!.rotation -@Suppress("DEPRECATION") +@Suppress("unused") fun Activity.displayRotationDegrees(): Int = when (displayRotation()) { Surface.ROTATION_0 -> 0 @@ -133,6 +204,8 @@ inline fun v2aCreate(count: Int, x: (Int) -> Float, y: (Int) -> Float): V2A = } const val dimenV2A: Int = 2 + +@Suppress("UnusedReceiverParameter") inline val V2A.dimen: Int get() = dimenV2A fun V2A.count(): Int = floatArray.size / dimen inline val V2A.indices: IntRange get() = IntRange(0, count() - 1) @@ -143,6 +216,8 @@ fun V2A.set(i: Int, x: Float, y: Float) { } const val dimenV3A: Int = 3 + +@Suppress("UnusedReceiverParameter") inline val V3A.dimen: Int get() = dimenV3A fun V3A.set(i: Int, x: Float, y: Float, z: Float) { @@ -158,12 +233,18 @@ fun mulV3(r: FloatArray, ri: Int, v: FloatArray, vi: Int, s: Float) { } const val dimenV4A: Int = 4 + +@Suppress("UnusedReceiverParameter") inline val V4A.dimen: Int get() = dimenV4A inline val V4A.count: Int get() = floatArray.size / dimen fun V4A.getX(i: Int): Float = floatArray[(i * dimen) + 0] + +@Suppress("unused") fun V4A.getY(i: Int): Float = floatArray[(i * dimen) + 1] fun V4A.getZ(i: Int): Float = floatArray[(i * dimen) + 2] + +@Suppress("unused") fun V4A.getW(i: Int): Float = floatArray[(i * dimen) + 3] fun V4A.set(i: Int, x: Float, y: Float, z: Float, w: Float) { @@ -185,8 +266,7 @@ fun V3.neg(): V3 = val v3Origin: V3 = v3(0f, 0f, 0f) -fun v3(x: Float, y: Float, z: Float): V3 = FloatArray(3) - .let { V3(it) } +fun v3(x: Float, y: Float, z: Float): V3 = V3(FloatArray(3)) .also { it.x = x it.y = y diff --git a/app/src/main/java/com/example/app/OpenGL.kt b/app/src/main/java/com/example/app/OpenGL.kt index b39bbad..7bbc207 100644 --- a/app/src/main/java/com/example/app/OpenGL.kt +++ b/app/src/main/java/com/example/app/OpenGL.kt @@ -1,6 +1,12 @@ package com.example.app -import android.opengl.* +import android.opengl.EGL14 +import android.opengl.EGLConfig +import android.opengl.EGLContext +import android.opengl.EGLDisplay +import android.opengl.EGLSurface +import android.opengl.GLES11Ext +import android.opengl.GLES30 import arrow.core.Either import arrow.core.left import arrow.core.right diff --git a/app/src/main/java/com/example/app/aractivity/ArActivity.kt b/app/src/main/java/com/example/app/aractivity/ArActivity.kt index ec04773..7007df1 100644 --- a/app/src/main/java/com/example/app/aractivity/ArActivity.kt +++ b/app/src/main/java/com/example/app/aractivity/ArActivity.kt @@ -6,27 +6,59 @@ import android.content.pm.PackageManager import android.content.res.Configuration import android.os.Build import android.os.Bundle -import android.view.* +import android.view.MotionEvent +import android.view.View +import android.view.WindowInsets +import android.view.WindowInsetsController import androidx.appcompat.app.AlertDialog import androidx.appcompat.app.AppCompatActivity import androidx.core.content.ContextCompat import androidx.core.view.WindowCompat import androidx.core.view.isVisible -import com.example.app.* +import com.example.app.OpenGLVersionNotSupported +import com.example.app.PermissionResultEvent +import com.example.app.R +import com.example.app.UserCanceled import com.example.app.arcore.ArCore +import com.example.app.cameraPermissionRequestCode +import com.example.app.checkIfOpenGlVersionSupported import com.example.app.databinding.ExampleActivityBinding import com.example.app.filament.Filament -import com.example.app.gesture.* +import com.example.app.gesture.DragGesture +import com.example.app.gesture.DragGestureRecognizer +import com.example.app.gesture.PinchGesture +import com.example.app.gesture.PinchGestureRecognizer +import com.example.app.gesture.TransformationSystem +import com.example.app.gesture.TwistGesture +import com.example.app.gesture.TwistGestureRecognizer +import com.example.app.minOpenGlVersion +import com.example.app.renderer.FrameCallback +import com.example.app.renderer.LightRenderer +import com.example.app.renderer.ModelRenderer +import com.example.app.renderer.PlaneRenderer +import com.example.app.showOpenGlNotSupportedDialog import com.example.app.toRadians import com.example.app.x import com.example.app.y -import com.example.app.renderer.* import com.google.ar.core.ArCoreApk import com.google.ar.core.Plane import com.google.ar.core.TrackingState -import kotlinx.coroutines.* +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.awaitCancellation +import kotlinx.coroutines.cancel import kotlinx.coroutines.channels.BufferOverflow -import kotlinx.coroutines.flow.* +import kotlinx.coroutines.coroutineScope +import kotlinx.coroutines.delay +import kotlinx.coroutines.flow.MutableSharedFlow +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.dropWhile +import kotlinx.coroutines.flow.filter +import kotlinx.coroutines.flow.filterNotNull +import kotlinx.coroutines.flow.first +import kotlinx.coroutines.flow.map +import kotlinx.coroutines.launch +import kotlinx.coroutines.suspendCancellableCoroutine import java.util.concurrent.TimeUnit import kotlin.coroutines.coroutineContext import kotlin.coroutines.resume @@ -424,7 +456,7 @@ class ArActivity : AppCompatActivity() { private suspend fun showCameraPermissionDialog(activity: AppCompatActivity) { if (shouldShowRequestPermissionRationale(Manifest.permission.CAMERA)) { - suspendCancellableCoroutine { continuation -> + suspendCancellableCoroutine { continuation -> val alertDialog = AlertDialog .Builder(activity) .setTitle(R.string.camera_permission_title) diff --git a/app/src/main/java/com/example/app/arcore/ArCore.kt b/app/src/main/java/com/example/app/arcore/ArCore.kt index 60f3a92..ff4a77c 100644 --- a/app/src/main/java/com/example/app/arcore/ArCore.kt +++ b/app/src/main/java/com/example/app/arcore/ArCore.kt @@ -2,6 +2,7 @@ package com.example.app.arcore import android.annotation.SuppressLint import android.app.Activity +import android.graphics.SurfaceTexture import android.hardware.camera2.CameraCharacteristics import android.hardware.camera2.CameraManager import android.media.Image @@ -13,13 +14,38 @@ import android.view.View import android.widget.FrameLayout import androidx.core.content.ContextCompat import androidx.core.view.updateLayoutParams -import com.example.app.* +import com.example.app.M4 +import com.example.app.V2A +import com.example.app.count +import com.example.app.createExternalTextureId +import com.example.app.dimenV2A import com.example.app.filament.Filament -import com.google.android.filament.* +import com.example.app.m4Identity +import com.example.app.matrix +import com.example.app.projectionMatrix +import com.example.app.readUncompressedAsset +import com.example.app.rotate +import com.example.app.set +import com.example.app.toDoubleArray +import com.example.app.toFloatBuffer +import com.example.app.toShortBuffer +import com.example.app.translate +import com.google.android.filament.Entity +import com.google.android.filament.EntityManager +import com.google.android.filament.IndexBuffer +import com.google.android.filament.Material +import com.google.android.filament.MaterialInstance +import com.google.android.filament.RenderableManager import com.google.android.filament.RenderableManager.PrimitiveType +import com.google.android.filament.Stream +import com.google.android.filament.Texture +import com.google.android.filament.TextureSampler +import com.google.android.filament.VertexBuffer import com.google.android.filament.VertexBuffer.AttributeType import com.google.android.filament.VertexBuffer.VertexAttribute -import com.google.ar.core.* +import com.google.ar.core.Config +import com.google.ar.core.Frame +import com.google.ar.core.Session import kotlin.math.roundToInt class ModelBuffers(val clipPosition: V2A, val uvs: V2A, val triangleIndices: ShortArray) @@ -27,10 +53,10 @@ class ModelBuffers(val clipPosition: V2A, val uvs: V2A, val triangleIndices: Sho @SuppressLint("MissingPermission") class ArCore(private val activity: Activity, val filament: Filament, private val view: View) { companion object { - const val near: Float = 0.1f - const val far: Float = 30f - private const val positionBufferIndex: Int = 0 - private const val uvBufferIndex: Int = 1 + const val NEAR: Float = 0.1f + const val FAR: Float = 30f + private const val POSITION_BUFFER_INDEX: Int = 0 + private const val UV_BUFFER_INDEX: Int = 1 } private val cameraStreamTextureId: Int = createExternalTextureId() @@ -80,7 +106,7 @@ class ArCore(private val activity: Activity, val filament: Filament, private val session.close() } - var displayRotationDegrees: Int = 0 + private var displayRotationDegrees: Int = 0 fun configurationChange() { if (this::frame.isInitialized.not()) return @@ -127,16 +153,19 @@ class ArCore(private val activity: Activity, val filament: Filament, private val cameraWidth = dimensions[0] cameraHeight = dimensions[1] } + else -> { cameraWidth = dimensions[1] cameraHeight = dimensions[0] } } + else -> when (displayRotation) { Surface.ROTATION_0, Surface.ROTATION_180 -> { cameraWidth = dimensions[1] cameraHeight = dimensions[0] } + else -> { cameraWidth = dimensions[0] cameraHeight = dimensions[1] @@ -168,7 +197,7 @@ class ArCore(private val activity: Activity, val filament: Filament, private val session.setDisplayGeometry(displayRotation, viewWidth, viewHeight) } - var hasDepthImage: Boolean = false + private var hasDepthImage: Boolean = false fun update(frame: Frame, filament: Filament) { val firstFrame = this::frame.isInitialized.not() @@ -184,7 +213,7 @@ class ArCore(private val activity: Activity, val filament: Filament, private val stream = Stream .Builder() - .stream(cameraStreamTextureId.toLong()) + .stream(SurfaceTexture(cameraStreamTextureId)) .width(width) .height(height) .build(filament.engine) @@ -231,7 +260,7 @@ class ArCore(private val activity: Activity, val filament: Filament, private val ?.let { if (hasDepthImage.not()) { try { - val depthImage = frame.acquireDepthImage() as ArImage + val depthImage = frame.acquireDepthImage16Bits() if (depthImage.planes[0].buffer[0] != 0.toByte()) { hasDepthImage = true @@ -293,8 +322,8 @@ class ArCore(private val activity: Activity, val filament: Filament, private val // update camera projection filament.camera.setCustomProjection( frame.projectionMatrix().floatArray.toDoubleArray(), - near.toDouble(), - far.toDouble(), + NEAR.toDouble(), + FAR.toDouble(), ) val cameraTransform = frame.camera.displayOrientedPose.matrix() @@ -320,14 +349,14 @@ class ArCore(private val activity: Activity, val filament: Filament, private val .bufferCount(2) .attribute( VertexAttribute.POSITION, - positionBufferIndex, + POSITION_BUFFER_INDEX, AttributeType.FLOAT2, 0, 0, ) .attribute( VertexAttribute.UV0, - uvBufferIndex, + UV_BUFFER_INDEX, AttributeType.FLOAT2, 0, 0, @@ -336,13 +365,13 @@ class ArCore(private val activity: Activity, val filament: Filament, private val .also { vertexBuffer -> vertexBuffer.setBufferAt( filament.engine, - positionBufferIndex, + POSITION_BUFFER_INDEX, tes.clipPosition.floatArray.toFloatBuffer(), ) vertexBuffer.setBufferAt( filament.engine, - uvBufferIndex, + UV_BUFFER_INDEX, tes.uvs.floatArray.toFloatBuffer(), ) }, @@ -423,14 +452,14 @@ class ArCore(private val activity: Activity, val filament: Filament, private val .bufferCount(2) .attribute( VertexAttribute.POSITION, - positionBufferIndex, + POSITION_BUFFER_INDEX, AttributeType.FLOAT2, 0, 0, ) .attribute( VertexAttribute.UV0, - uvBufferIndex, + UV_BUFFER_INDEX, AttributeType.FLOAT2, 0, 0, @@ -439,13 +468,13 @@ class ArCore(private val activity: Activity, val filament: Filament, private val .also { vertexBuffer -> vertexBuffer.setBufferAt( filament.engine, - positionBufferIndex, + POSITION_BUFFER_INDEX, tes.clipPosition.floatArray.toFloatBuffer() ) vertexBuffer.setBufferAt( filament.engine, - uvBufferIndex, + UV_BUFFER_INDEX, tes.uvs.floatArray.toFloatBuffer() ) }, @@ -460,17 +489,16 @@ class ArCore(private val activity: Activity, val filament: Filament, private val .build(filament.engine, EntityManager.get().create().also { depthRenderable = it }) } + @Suppress("KotlinConstantConditions") private fun tessellation(): ModelBuffers { - val tesWidth: Int = 1 - val tesHeight: Int = 1 + val tesWidth = 1 + val tesHeight = 1 - val clipPosition: V2A = (((tesWidth * tesHeight) + tesWidth + tesHeight + 1) * dimenV2A) - .let { FloatArray(it) } - .let { V2A(it) } + val clipPosition = + V2A(FloatArray((((tesWidth * tesHeight) + tesWidth + tesHeight + 1) * dimenV2A))) - val uvs: V2A = (((tesWidth * tesHeight) + tesWidth + tesHeight + 1) * dimenV2A) - .let { FloatArray(it) } - .let { V2A(it) } + val uvs = + V2A(FloatArray((((tesWidth * tesHeight) + tesWidth + tesHeight + 1) * dimenV2A))) for (k in 0..tesHeight) { val v = k.toFloat() / tesHeight.toFloat() diff --git a/app/src/main/java/com/example/app/filament/Filament.kt b/app/src/main/java/com/example/app/filament/Filament.kt index 3140f9a..35b0425 100644 --- a/app/src/main/java/com/example/app/filament/Filament.kt +++ b/app/src/main/java/com/example/app/filament/Filament.kt @@ -6,12 +6,19 @@ import android.view.Surface import android.view.SurfaceView import com.example.app.createEglContext import com.example.app.destroyEglContext -import com.google.android.filament.* +import com.google.android.filament.Camera +import com.google.android.filament.Engine +import com.google.android.filament.EntityManager +import com.google.android.filament.Renderer +import com.google.android.filament.Scene +import com.google.android.filament.SwapChain +import com.google.android.filament.View +import com.google.android.filament.Viewport import com.google.android.filament.android.DisplayHelper import com.google.android.filament.android.UiHelper import com.google.android.filament.gltfio.AssetLoader import com.google.android.filament.gltfio.ResourceLoader -import com.google.android.filament.gltfio.UbershaderLoader +import com.google.android.filament.gltfio.UbershaderProvider class Filament(context: Context, val surfaceView: SurfaceView) { var timestamp: Long = 0L @@ -37,7 +44,7 @@ class Filament(context: Context, val surfaceView: SurfaceView) { } val assetLoader = - AssetLoader(engine, UbershaderLoader(engine), EntityManager.get()) + AssetLoader(engine, UbershaderProvider(engine), EntityManager.get()) val resourceLoader = ResourceLoader(engine) diff --git a/app/src/main/java/com/example/app/gesture/BaseGestureRecognizer.kt b/app/src/main/java/com/example/app/gesture/BaseGestureRecognizer.kt index 9c3346c..22448ab 100644 --- a/app/src/main/java/com/example/app/gesture/BaseGestureRecognizer.kt +++ b/app/src/main/java/com/example/app/gesture/BaseGestureRecognizer.kt @@ -1,7 +1,6 @@ package com.example.app.gesture import android.view.MotionEvent -import java.util.* // A Gesture recognizer processes touch input to determine if a gesture should start and fires an // event when the gesture is started. @@ -20,6 +19,7 @@ abstract class BaseGestureRecognizer>(val gesturePointersUtil } } + @Suppress("unused") fun removeOnGestureStartedListener(listener: OnGestureStartedListener) { gestureStartedListeners.remove(listener) } diff --git a/app/src/main/java/com/example/app/gesture/DragGesture.kt b/app/src/main/java/com/example/app/gesture/DragGesture.kt index 454d775..33c5a29 100644 --- a/app/src/main/java/com/example/app/gesture/DragGesture.kt +++ b/app/src/main/java/com/example/app/gesture/DragGesture.kt @@ -1,7 +1,11 @@ package com.example.app.gesture import android.view.MotionEvent -import com.example.app.* +import com.example.app.V3 +import com.example.app.eq +import com.example.app.magnitude +import com.example.app.sub +import com.example.app.v3Origin class DragGesture(gesturePointersUtility: GesturePointersUtility, motionEvent: MotionEvent) : BaseGesture(gesturePointersUtility) { diff --git a/app/src/main/java/com/example/app/gesture/GesturePointersUtility.kt b/app/src/main/java/com/example/app/gesture/GesturePointersUtility.kt index 96f8b99..f447a6b 100644 --- a/app/src/main/java/com/example/app/gesture/GesturePointersUtility.kt +++ b/app/src/main/java/com/example/app/gesture/GesturePointersUtility.kt @@ -5,7 +5,6 @@ import android.util.TypedValue import android.view.MotionEvent import com.example.app.V3 import com.example.app.v3 -import java.util.* // Retains/Releases pointer Ids so that each pointer can only be used in one gesture at a time. // Provides helper functions for converting touch coordinates between pixels and inches. diff --git a/app/src/main/java/com/example/app/gesture/PinchGesture.kt b/app/src/main/java/com/example/app/gesture/PinchGesture.kt index 7befa28..50925ee 100644 --- a/app/src/main/java/com/example/app/gesture/PinchGesture.kt +++ b/app/src/main/java/com/example/app/gesture/PinchGesture.kt @@ -1,7 +1,14 @@ package com.example.app.gesture import android.view.MotionEvent -import com.example.app.* +import com.example.app.V3 +import com.example.app.dot +import com.example.app.eq +import com.example.app.magnitude +import com.example.app.neg +import com.example.app.normalize +import com.example.app.sub +import com.example.app.v3Origin import kotlin.math.abs import kotlin.math.cos @@ -28,12 +35,10 @@ class PinchGesture( private var previousPosition1: V3 = startPosition1 private var previousPosition2: V3 = startPosition2 - var gap = 0f - private set - - var gapDelta = 0f - private set + private var gap = 0f + private var gapDelta = 0f + @Suppress("unused") fun gapInches(): Float { return gesturePointersUtility.pixelsToInches(gap) } diff --git a/app/src/main/java/com/example/app/gesture/TwistGesture.kt b/app/src/main/java/com/example/app/gesture/TwistGesture.kt index 7b14157..e8a98b5 100644 --- a/app/src/main/java/com/example/app/gesture/TwistGesture.kt +++ b/app/src/main/java/com/example/app/gesture/TwistGesture.kt @@ -1,7 +1,15 @@ package com.example.app.gesture import android.view.MotionEvent -import com.example.app.* +import com.example.app.V3 +import com.example.app.dot +import com.example.app.eq +import com.example.app.normalize +import com.example.app.sub +import com.example.app.toDegrees +import com.example.app.v3Origin +import com.example.app.x +import com.example.app.y import kotlin.math.abs import kotlin.math.acos import kotlin.math.sign diff --git a/app/src/main/java/com/example/app/renderer/FrameCallback.kt b/app/src/main/java/com/example/app/renderer/FrameCallback.kt index b1e7ee6..02ba123 100644 --- a/app/src/main/java/com/example/app/renderer/FrameCallback.kt +++ b/app/src/main/java/com/example/app/renderer/FrameCallback.kt @@ -10,13 +10,14 @@ class FrameCallback( private val doFrame: (frame: Frame) -> Unit, ) : Choreographer.FrameCallback { companion object { - private const val maxFramesPerSecond: Long = 60 + private const val MAX_FRAMES_PER_SECOND: Long = 60 } - sealed class FrameRate(val factor: Long) { - object Full : FrameRate(1) - object Half : FrameRate(2) - object Third : FrameRate(3) + @Suppress("unused") + enum class FrameRate(val factor: Long) { + Full(1), + Half(2), + Third(3), } private val choreographer: Choreographer = Choreographer.getInstance() @@ -28,7 +29,7 @@ class FrameCallback( // limit to max fps val nanoTime = System.nanoTime() - val tick = nanoTime / (TimeUnit.SECONDS.toNanos(1) / maxFramesPerSecond) + val tick = nanoTime / (TimeUnit.SECONDS.toNanos(1) / MAX_FRAMES_PER_SECOND) if (lastTick / frameRate.factor == tick / frameRate.factor) { return diff --git a/app/src/main/java/com/example/app/renderer/LightRenderer.kt b/app/src/main/java/com/example/app/renderer/LightRenderer.kt index 5493910..6d24e26 100644 --- a/app/src/main/java/com/example/app/renderer/LightRenderer.kt +++ b/app/src/main/java/com/example/app/renderer/LightRenderer.kt @@ -3,9 +3,16 @@ package com.example.app.renderer import android.content.Context import android.content.res.AssetManager import android.graphics.BitmapFactory -import com.example.app.* +import com.example.app.V3 +import com.example.app.div import com.example.app.filament.Filament -import com.google.android.filament.* +import com.example.app.getEnvironmentalHdrSphericalHarmonics +import com.google.android.filament.Engine +import com.google.android.filament.EntityInstance +import com.google.android.filament.EntityManager +import com.google.android.filament.IndirectLight +import com.google.android.filament.LightManager +import com.google.android.filament.Texture import com.google.ar.core.Frame import com.google.ar.core.LightEstimate import java.nio.ByteBuffer @@ -31,7 +38,6 @@ class LightRenderer(context: Context, private val filament: Filament) { filament.engine.lightManager.getInstance(directionalLight) } - fun doFrame(frame: Frame) { // update lighting estimate if (frame.lightEstimate.state != LightEstimate.State.VALID) { @@ -77,6 +83,7 @@ class LightRenderer(context: Context, private val filament: Filament) { } } +@Suppress("SameParameterValue") private fun peekSize(assets: AssetManager, name: String): Pair { assets.open(name).use { input -> val opts = BitmapFactory.Options().apply { inJustDecodeBounds = true } diff --git a/app/src/main/java/com/example/app/renderer/ModelRenderer.kt b/app/src/main/java/com/example/app/renderer/ModelRenderer.kt index 0f5a0ad..e28e33c 100644 --- a/app/src/main/java/com/example/app/renderer/ModelRenderer.kt +++ b/app/src/main/java/com/example/app/renderer/ModelRenderer.kt @@ -1,15 +1,33 @@ package com.example.app.renderer import android.content.Context -import com.example.app.* +import com.example.app.V3 import com.example.app.aractivity.ScreenPosition import com.example.app.arcore.ArCore +import com.example.app.clampToTau import com.example.app.filament.Filament +import com.example.app.m4Identity +import com.example.app.rotate +import com.example.app.scale +import com.example.app.toDegrees +import com.example.app.translate +import com.example.app.v3Origin +import com.example.app.x +import com.example.app.y +import com.example.app.z import com.google.ar.core.Frame import com.google.ar.core.Point -import kotlinx.coroutines.* +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.cancel import kotlinx.coroutines.channels.BufferOverflow -import kotlinx.coroutines.flow.* +import kotlinx.coroutines.flow.MutableSharedFlow +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.filterNotNull +import kotlinx.coroutines.flow.first +import kotlinx.coroutines.flow.mapNotNull +import kotlinx.coroutines.launch +import kotlinx.coroutines.withContext import java.nio.ByteBuffer import java.util.concurrent.TimeUnit @@ -39,13 +57,12 @@ class ModelRenderer(context: Context, private val arCore: ArCore, private val fi coroutineScope.launch { val filamentAsset = withContext(Dispatchers.IO) { - @Suppress("BlockingMethodInNonBlockingContext") context.assets .open("eren-hiphop-dance.glb") .use { input -> val bytes = ByteArray(input.available()) input.read(bytes) - filament.assetLoader.createAssetFromBinary(ByteBuffer.wrap(bytes))!! + filament.assetLoader.createAsset(ByteBuffer.wrap(bytes))!! } } .also { filament.resourceLoader.loadResources(it) } @@ -92,7 +109,7 @@ class ModelRenderer(context: Context, private val arCore: ArCore, private val fi doFrameEvents.collect { frame -> // update animator - val animator = filamentAsset.animator + val animator = filamentAsset.instance.animator if (animator.animationCount > 0) { animator.applyAnimation( diff --git a/app/src/main/java/com/example/app/renderer/PlaneRenderer.kt b/app/src/main/java/com/example/app/renderer/PlaneRenderer.kt index 7d6e668..4f254da 100644 --- a/app/src/main/java/com/example/app/renderer/PlaneRenderer.kt +++ b/app/src/main/java/com/example/app/renderer/PlaneRenderer.kt @@ -1,12 +1,29 @@ package com.example.app.renderer import android.content.Context -import com.example.app.* import com.example.app.R +import com.example.app.count +import com.example.app.dimenV2A +import com.example.app.dimenV4A import com.example.app.filament.Filament -import com.google.android.filament.* -import com.google.android.filament.textured.TextureType -import com.google.android.filament.textured.loadTexture +import com.example.app.horizontalToUV +import com.example.app.matrix +import com.example.app.polygonToUV +import com.example.app.polygonToVertices +import com.example.app.readUncompressedAsset +import com.example.app.size +import com.example.app.triangleIndexArrayCreate +import com.google.android.filament.Box +import com.google.android.filament.Entity +import com.google.android.filament.EntityManager +import com.google.android.filament.IndexBuffer +import com.google.android.filament.Material +import com.google.android.filament.MaterialInstance +import com.google.android.filament.RenderableManager +import com.google.android.filament.TextureSampler +import com.google.android.filament.VertexBuffer +import com.google.android.filament.utils.TextureType +import com.google.android.filament.utils.loadTexture import com.google.ar.core.Frame import com.google.ar.core.Plane import com.google.ar.core.TrackingState @@ -19,8 +36,8 @@ import kotlin.math.min class PlaneRenderer(context: Context, private val filament: Filament) { companion object { - private const val planeVertexBufferSize: Int = 1000 - private const val planeIndexBufferSize: Int = (planeVertexBufferSize - 2) * 3 + private const val PLANE_VERTEX_BUFFER_SIZE: Int = 1000 + private const val PLANE_INDEX_BUFFER_SIZE: Int = (PLANE_VERTEX_BUFFER_SIZE - 2) * 3 } private val textureMaterial: Material = context @@ -41,7 +58,7 @@ class PlaneRenderer(context: Context, private val filament: Filament) { TextureSampler().also { it.anisotropy = 8.0f }, ) - materialInstance.setParameter("alpha", 1f) +// materialInstance.setParameter("alpha", 1f) } private val shadowMaterial: Material = context @@ -54,21 +71,21 @@ class PlaneRenderer(context: Context, private val filament: Filament) { } private val planeVertexFloatBuffer: FloatBuffer = ByteBuffer - .allocateDirect(planeVertexBufferSize * dimenV4A * Float.size) + .allocateDirect(PLANE_VERTEX_BUFFER_SIZE * dimenV4A * Float.size) .order(ByteOrder.nativeOrder()) .asFloatBuffer() private val planeUvFloatBuffer: FloatBuffer = ByteBuffer - .allocateDirect(planeVertexBufferSize * dimenV2A * Float.size) + .allocateDirect(PLANE_VERTEX_BUFFER_SIZE * dimenV2A * Float.size) .order(ByteOrder.nativeOrder()) .asFloatBuffer() private val planeIndexShortBuffer: ShortBuffer = ShortBuffer - .allocate(planeIndexBufferSize) + .allocate(PLANE_INDEX_BUFFER_SIZE) private val planeVertexBuffer: VertexBuffer = VertexBuffer .Builder() - .vertexCount(planeVertexBufferSize) + .vertexCount(PLANE_VERTEX_BUFFER_SIZE) .bufferCount(2) .attribute( VertexBuffer.VertexAttribute.POSITION, @@ -88,7 +105,7 @@ class PlaneRenderer(context: Context, private val filament: Filament) { private val planeIndexBuffer: IndexBuffer = IndexBuffer .Builder() - .indexCount(planeIndexBufferSize) + .indexCount(PLANE_INDEX_BUFFER_SIZE) .bufferType(IndexBuffer.Builder.IndexType.USHORT) .build(filament.engine) @@ -116,8 +133,8 @@ class PlaneRenderer(context: Context, private val filament: Filament) { var zMin = Float.POSITIVE_INFINITY var zMax = Float.NEGATIVE_INFINITY - var vertexBufferOffset: Int = 0 - var indexBufferOffset: Int = 0 + var vertexBufferOffset = 0 + var indexBufferOffset = 0 var indexWithoutShadow: Int? = null @@ -146,8 +163,8 @@ class PlaneRenderer(context: Context, private val filament: Filament) { ) // check for for buffer overflow - if (vertexBufferOffset + planeVertices.count > planeVertexBufferSize || - indexBufferOffset + planeTriangleIndices.shortArray.count() > planeIndexBufferSize + if (vertexBufferOffset + planeVertices.count > PLANE_VERTEX_BUFFER_SIZE || + indexBufferOffset + planeTriangleIndices.shortArray.count() > PLANE_INDEX_BUFFER_SIZE ) { break } diff --git a/build.gradle b/build.gradle deleted file mode 100644 index 232af48..0000000 --- a/build.gradle +++ /dev/null @@ -1,31 +0,0 @@ -buildscript { - ext { - kotlin_version = '1.5.31' - } - repositories { - google() - mavenCentral() - maven { url 'https://plugins.gradle.org/m2/' } - maven { url 'https://dl.bintray.com/arrow-kt/arrow-kt/' } - } - dependencies { - classpath 'com.android.tools.build:gradle:7.0.3' - classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" - classpath "org.jetbrains.kotlin:kotlin-android-extensions:$kotlin_version" - classpath 'com.google.gms:google-services:4.3.10' - classpath 'com.google.firebase:perf-plugin:1.4.0' - classpath 'com.google.firebase:firebase-crashlytics-gradle:2.8.0' - classpath 'androidx.navigation:navigation-safe-args-gradle-plugin:2.3.5' - } -} - -allprojects { - repositories { - google() - mavenCentral() - } -} - -task clean(type: Delete) { - delete rootProject.buildDir -} diff --git a/build.gradle.kts b/build.gradle.kts new file mode 100644 index 0000000..827982b --- /dev/null +++ b/build.gradle.kts @@ -0,0 +1,62 @@ +import org.jetbrains.kotlin.gradle.tasks.KotlinCompile + +plugins { + alias(libs.plugins.kotlinAndroid) apply false + alias(libs.plugins.kotlinxSerialization) apply false + alias(libs.plugins.kotlinxParcelize) apply false + alias(libs.plugins.androidApplication) apply false + alias(libs.plugins.ksp) apply false + alias(libs.plugins.hilt) apply false +} + +tasks.register("clean", Delete::class) { + delete(rootProject.layout.buildDirectory) +} + +subprojects { + tasks.withType().configureEach { + kotlinOptions { + freeCompilerArgs = freeCompilerArgs + "-Xcontext-receivers" + + if (project.findProperty("hackernews.enableComposeCompilerReports") == "true") { + // force tasks to rerun so that metrics are generated + outputs.upToDateWhen { false } + freeCompilerArgs = freeCompilerArgs + + "-P=plugin:androidx.compose.compiler.plugins.kotlin:reportsDestination=${project.projectDir.absolutePath}/build/compose_metrics/" + + "-P=plugin:androidx.compose.compiler.plugins.kotlin:metricsDestination=${project.projectDir.absolutePath}/build/compose_metrics/" + } + } + } +} + +//buildscript { +// ext { +// kotlin_version = "1.5.31" +// } +// repositories { +// google() +// mavenCentral() +// maven { url "https://plugins.gradle.org/m2/" } +// maven { url "https://dl.bintray.com/arrow-kt/arrow-kt/" } +// } +// dependencies { +// classpath "com.android.tools.build:gradle:7.0.3" +// classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" +// classpath "org.jetbrains.kotlin:kotlin-android-extensions:$kotlin_version" +// classpath "com.google.gms:google-services:4.3.10" +// classpath "com.google.firebase:perf-plugin:1.4.0" +// classpath "com.google.firebase:firebase-crashlytics-gradle:2.8.0" +// classpath "androidx.navigation:navigation-safe-args-gradle-plugin:2.3.5" +// } +//} +// +//allprojects { +// repositories { +// google() +// mavenCentral() +// } +//} +// +//task clean(type: Delete) { +// delete rootProject.buildDir +//} diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml new file mode 100644 index 0000000..7211269 --- /dev/null +++ b/gradle/libs.versions.toml @@ -0,0 +1,186 @@ +[versions] +jvmTarget = "17" +compileSdk = "34" +targetSdk = "34" +minSdk = "26" +buildToolsVersion = "34.0.0" +composeCompiler = "1.5.8" +android = "8.3.0-rc01" +kotlin = "1.9.22" +ksp = "1.9.22-1.0.17" +kotlinxCoroutines = "1.7.3" +kotlinxSerialization = "1.6.2" +kotlinxCollectionsImmutable = "0.3.7" +kotlinxDatetime = "0.5.0" +activityKtx = "1.8.2" +fragmentKtx = "1.6.2" +lifecycle = "2.7.0" +navigation = "2.7.6" +hilt = "2.50" +window = "1.2.0" +appcompat = "1.6.1" +coreKtx = "1.12.0" +collectionKtx = "1.4.0" +paletteKtx = "1.0.0" +workRuntimeKtx = "2.9.0" +preferenceKtx = "1.2.1" +hiltNavigationCompose = "1.1.0" +composeLintChecks = "1.3.1" +material3 = "1.2.0-rc01" +composeBom = "2024.01.00" +uiTestJunit4 = "1.6.0" +slf4jSimple = "2.0.11" +junit = "4.13.2" +junitExt = "1.1.5" +desugarJdkLibs = "2.0.4" +arCore = "1.41.0" +filamentAndroid = "1.49.3" +arrowFx = "0.12.1" +coil = "2.5.0" +mockk = "1.13.9" + +[plugins] +kotlinAndroid = { id = "org.jetbrains.kotlin.android", version.ref = "kotlin" } +kotlinxSerialization = { id = "org.jetbrains.kotlin.plugin.serialization", version.ref = "kotlin" } +kotlinxParcelize = { id = "org.jetbrains.kotlin.plugin.parcelize", version.ref = "kotlin" } +androidApplication = { id = "com.android.application", version.ref = "android" } +ksp = { id = "com.google.devtools.ksp", version.ref = "ksp" } +hilt = { id = "com.google.dagger.hilt.android", version.ref = "hilt" } + +[bundles] +kotlinx = [ + "kotlinxCoroutinesAndroid", + "kotlinxSerializationJson", + "kotlinxCollectionsImmutable", + "kotlinxDatetime", +] +google = [ + "kspSymbolProcessingApi", +] +androidx = [ + "coreKtx", + "collectionKtx", + "appcompat", + "window", + "activityKtx", + "activityCompose", + "fragmentKtx", + "paletteKtx", + "workRuntimeKtx", + "preferenceKtx", + "lifecycleProcess", + "lifecycleRuntimeKtx", + "lifecycleRuntimeCompose", + "lifecycleViewModelKtx", + "lifecycleViewModelCompose", + "lifecycleViewModelSavedState", +] +androidxApp = [ + "navigationRuntimeKtx", + "navigationUiKtx", + "navigationCompose", + "composeMaterial", +] +androidxCompose = [ + "ui", + "uiViewBinding", + "uiTooling", + "uiToolingData", + "uiToolingPreview", + "uiUtil", + "material3", + "material3WindowSize", + "materialIconsCore", + "materialIconsExtended", + "foundation", + "uiTextGoogleFonts", + "coilCompose", +] +filament = [ + "filament-android", + "filament-utils-android", + "gltfio-android" +] +test = [ + "kotlinTest", + "kotlinxCoroutinesTest", + "uiTestJunit4", + "junit", + "junitExt", + "mockk", + "uiTestManifest", +] + +[libraries] +kotlinTest = { group = "org.jetbrains.kotlin", name = "kotlin-test", version.ref = "kotlin" } +kotlinxCoroutinesAndroid = { group = "org.jetbrains.kotlinx", name = "kotlinx-coroutines-android", version.ref = "kotlinxCoroutines" } +kotlinxCoroutinesTest = { group = "org.jetbrains.kotlinx", name = "kotlinx-coroutines-test", version.ref = "kotlinxCoroutines" } +kotlinxSerializationJson = { group = "org.jetbrains.kotlinx", name = "kotlinx-serialization-json", version.ref = "kotlinxSerialization" } +kotlinxCollectionsImmutable = { group = "org.jetbrains.kotlinx", name = "kotlinx-collections-immutable", version.ref = "kotlinxCollectionsImmutable" } +kotlinxDatetime = { group = "org.jetbrains.kotlinx", name = "kotlinx-datetime", version.ref = "kotlinxDatetime" } + +desugarJdkLibs = { group = "com.android.tools", name = "desugar_jdk_libs", version.ref = "desugarJdkLibs" } + +kspSymbolProcessingApi = { group = "com.google.devtools.ksp", name = "symbol-processing-api", version.ref = "ksp" } + +window = { group = "androidx.window", name = "window", version.ref = "window" } +appcompat = { group = "androidx.appcompat", name = "appcompat", version.ref = "appcompat" } +coreKtx = { group = "androidx.core", name = "core-ktx", version.ref = "coreKtx" } +collectionKtx = { group = "androidx.collection", name = "collection-ktx", version.ref = "collectionKtx" } +activityKtx = { group = "androidx.activity", name = "activity-ktx", version.ref = "activityKtx" } +activityCompose = { group = "androidx.activity", name = "activity-compose", version.ref = "activityKtx" } +fragmentKtx = { group = "androidx.fragment", name = "fragment-ktx", version.ref = "fragmentKtx" } +paletteKtx = { group = "androidx.palette", name = "palette-ktx", version.ref = "paletteKtx" } +workRuntimeKtx = { group = "androidx.work", name = "work-runtime-ktx", version.ref = "workRuntimeKtx" } +preferenceKtx = { group = "androidx.preference", name = "preference-ktx", version.ref = "preferenceKtx" } + +lifecycleProcess = { group = "androidx.lifecycle", name = "lifecycle-process", version.ref = "lifecycle" } +lifecycleRuntimeKtx = { group = "androidx.lifecycle", name = "lifecycle-runtime-ktx", version.ref = "lifecycle" } +lifecycleViewModelKtx = { group = "androidx.lifecycle", name = "lifecycle-viewmodel-ktx", version.ref = "lifecycle" } +lifecycleRuntimeCompose = { group = "androidx.lifecycle", name = "lifecycle-runtime-compose", version.ref = "lifecycle" } +lifecycleViewModelCompose = { group = "androidx.lifecycle", name = "lifecycle-viewmodel-compose", version.ref = "lifecycle" } +lifecycleViewModelSavedState = { group = "androidx.lifecycle", name = "lifecycle-viewmodel-savedstate", version.ref = "lifecycle" } + +navigationRuntimeKtx = { group = "androidx.navigation", name = "navigation-runtime-ktx", version.ref = "navigation" } + +hiltAndroid = { group = "com.google.dagger", name = "hilt-android", version.ref = "hilt" } +hiltAndroidCompiler = { group = "com.google.dagger", name = "hilt-android-compiler", version.ref = "hilt" } +hiltNavigationCompose = { group = "androidx.hilt", name = "hilt-navigation-compose", version.ref = "hiltNavigationCompose" } + +navigationUiKtx = { group = "androidx.navigation", name = "navigation-ui-ktx", version.ref = "navigation" } +navigationCompose = { group = "androidx.navigation", name = "navigation-compose", version.ref = "navigation" } + +composeLintChecks = { group = "com.slack.lint.compose", name = "compose-lint-checks", version.ref = "composeLintChecks" } + +material3 = { group = "androidx.compose.material3", name = "material3", version.ref = "material3" } + +composeBom = { group = "androidx.compose", name = "compose-bom", version.ref = "composeBom" } +material3WindowSize = { group = "androidx.compose.material3", name = "material3-window-size-class" } +ui = { group = "androidx.compose.ui", name = "ui" } +uiViewBinding = { group = "androidx.compose.ui", name = "ui-viewbinding" } +uiTooling = { group = "androidx.compose.ui", name = "ui-tooling" } +uiToolingData = { group = "androidx.compose.ui", name = "ui-tooling-data" } +uiToolingPreview = { group = "androidx.compose.ui", name = "ui-tooling-preview" } +uiUtil = { group = "androidx.compose.ui", name = "ui-util" } +composeMaterial = { group = "androidx.compose.material", name = "material" } +materialIconsCore = { group = "androidx.compose.material", name = "material-icons-core" } +materialIconsExtended = { group = "androidx.compose.material", name = "material-icons-extended" } +foundation = { group = "androidx.compose.foundation", name = "foundation" } +uiTextGoogleFonts = { group = "androidx.compose.ui", name = "ui-text-google-fonts" } +uiTestJunit4 = { group = "androidx.compose.ui", name = "ui-test-junit4", version.ref = "uiTestJunit4" } +uiTestManifest = { group = "androidx.compose.ui", name = "ui-test-manifest" } + +arCore = { module = "com.google.ar:core", version.ref = "arCore" } +arrowFx = { module = "io.arrow-kt:arrow-fx", version.ref = "arrowFx" } + +slf4jSimple = { group = "org.slf4j", name = "slf4j-simple", version.ref = "slf4jSimple" } +junit = { group = "junit", name = "junit", version.ref = "junit" } +junitExt = { group = "androidx.test.ext", name = "junit", version.ref = "junitExt" } + +coilCompose = { group = "io.coil-kt", name = "coil-compose", version.ref = "coil" } + +filament-android = { module = "com.google.android.filament:filament-android", version.ref = "filamentAndroid" } +filament-utils-android = { module = "com.google.android.filament:filament-utils-android", version.ref = "filamentAndroid" } +gltfio-android = { module = "com.google.android.filament:gltfio-android", version.ref = "filamentAndroid" } + +mockk = { group = "io.mockk", name = "mockk", version.ref = "mockk" } diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index e1efd6d..dd08087 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-7.0.2-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.5-bin.zip diff --git a/settings.gradle b/settings.gradle deleted file mode 100644 index 204a2ca..0000000 --- a/settings.gradle +++ /dev/null @@ -1,2 +0,0 @@ -rootProject.name='AR Core Filament Example App' -include ':app' diff --git a/settings.gradle.kts b/settings.gradle.kts new file mode 100644 index 0000000..73e417d --- /dev/null +++ b/settings.gradle.kts @@ -0,0 +1,21 @@ +@file:Suppress("UnstableApiUsage") + +pluginManagement { + repositories { + google() + mavenCentral() + gradlePluginPortal() + } +} + +dependencyResolutionManagement { + repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS) + + repositories { + google() + mavenCentral() + } +} + +rootProject.name = "AR Core Filament Example App" +include(":app")