a scrappy gimbal that insults you in shakespearean english

skeleton for moving left & right

paytondev 398715b0 9172dfff

Changed files
+52 -2
mobile
composeApp
src
androidMain
kotlin
com
paytondeveloper
myrus_mobile
commonMain
kotlin
com
paytondeveloper
myrus_mobile
+3
mobile/composeApp/src/androidMain/kotlin/com/paytondeveloper/myrus_mobile/MLFace.android.kt
··· 27 27 import com.google.mlkit.vision.face.FaceDetector 28 28 import com.google.mlkit.vision.face.FaceDetectorOptions 29 29 import com.google.mlkit.vision.face.FaceDetectorOptions.LandmarkMode 30 + import com.google.mlkit.vision.face.FaceDetectorOptions.PERFORMANCE_MODE_ACCURATE 30 31 import com.kashif.cameraK.builder.CameraControllerBuilder 31 32 import com.kashif.cameraK.controller.CameraController 32 33 import com.kashif.cameraK.enums.Directory ··· 52 53 // val img = InputImage.fromByteArray(img, options.outWidth, options.outHeight, rotationDegrees, InputImage.IMAGE_FORMAT_NV21) 53 54 val bitmap = BitmapFactory.decodeByteArray(img, 0, img.size) 54 55 val img = InputImage.fromBitmap(bitmap, 0) 56 + val options = FaceDetectorOptions.Builder() 57 + options.setPerformanceMode(PERFORMANCE_MODE_ACCURATE) 55 58 val detector = FaceDetection.getClient() 56 59 if (AppInfo.canDetectFace) { 57 60 AppInfo.canDetectFace = false
+49 -2
mobile/composeApp/src/commonMain/kotlin/com/paytondeveloper/myrus_mobile/App.kt
··· 16 16 import androidx.compose.ui.Alignment 17 17 import androidx.compose.ui.Modifier 18 18 import androidx.compose.ui.draw.drawWithCache 19 + import androidx.compose.ui.draw.scale 19 20 import androidx.compose.ui.geometry.Offset 20 21 import androidx.compose.ui.graphics.Color 21 22 import androidx.compose.ui.graphics.RectangleShape 22 23 import androidx.compose.ui.layout.onSizeChanged 23 24 import androidx.compose.ui.platform.LocalDensity 24 25 import androidx.compose.ui.platform.LocalViewConfiguration 26 + import androidx.compose.ui.text.font.FontWeight 25 27 import androidx.compose.ui.unit.dp 26 28 import androidx.graphics.shapes.RoundedPolygon 27 29 import com.kashif.cameraK.builder.CameraControllerBuilder ··· 54 56 data class Rect(val top: Float, val left: Float, val bottom: Float, val right: Float) 55 57 data class FaceData(val boundingBox: Rect) 56 58 59 + fun Rect.origin(): Size { 60 + val midpointX = (this.left + this.right) / 2 61 + val midpointY = (this.top + this.bottom) / 2 62 + return Size(width = midpointX, height = midpointY) 63 + } 64 + 57 65 expect suspend fun sayText(text: String) 58 66 59 67 val genAI = GenerativeModel( ··· 63 71 64 72 expect fun epochMillis(): Long 65 73 74 + enum class MovingDirection { 75 + RIGHT, LEFT 76 + } 66 77 67 78 @Composable 68 79 @Preview ··· 86 97 var currentThingy by remember { mutableStateOf<Rect?>(Rect(0f,0f,0f,0f)) } 87 98 var delayMillis by remember { mutableStateOf(1000) } 88 99 var analyzing by remember { mutableStateOf(true) } 100 + var moving by remember { mutableStateOf(false) } 89 101 val tts = rememberTextToSpeechOrNull(TextToSpeechEngine.Google) 102 + val movingDirection = remember { mutableStateOf<MovingDirection?>(null) } 90 103 LaunchedEffect(Unit) { 91 104 //not proud of this. 92 105 suspend fun roast(image: ByteArray) { ··· 123 136 124 137 currentThingy = bounds.copy(top = newY, left = newX) 125 138 analyzing = false 126 - CoroutineScope(Dispatchers.IO).launch { 127 - roast(it.byteArray) 139 + val leftCenter = bounds.right - bounds.left 140 + println("BOUNDS: ${bounds.origin().width} SIZE: ${size.width}") 141 + val midpointX = bounds.origin().width 142 + if (midpointX < ((size.width / 2) - (size.width / 12))) { 143 + //move left 144 + println("move left") 145 + movingDirection.value = MovingDirection.LEFT 146 + analyzing = true 147 + } else if (midpointX > ((size.width / 2) + (size.width / 12))) { 148 + //move right 149 + println("move right") 150 + analyzing = true 151 + movingDirection.value = MovingDirection.RIGHT 152 + } else { 153 + movingDirection.value = null 154 + //centered 155 + CoroutineScope(Dispatchers.IO).launch { 156 + roast(it.byteArray) 157 + } 128 158 } 159 + 129 160 }) 130 161 131 162 } ··· 145 176 val leftPx = with(LocalDensity.current) { 146 177 currentThingy!!.left.toDp() 147 178 } 179 + val camSizePx = with(LocalDensity.current) { 180 + camSize?.width?.toDp() ?: 0.dp 181 + } 148 182 println("offset (dp) ${topPx} ${leftPx}") 149 183 150 184 CameraPreview(modifier = Modifier.fillMaxSize().onSizeChanged { ··· 164 198 } 165 199 }) 166 200 Text("Face", modifier = Modifier.offset(x = leftPx, y = topPx)) 201 + // when (movingDirection) { 202 + // null -> {} 203 + // MovingDirection.RIGHT { 204 + // Text(">", fontWeight = FontWeight.Black, color = Color.White) 205 + // } 206 + // } 207 + if (movingDirection.value != null) { 208 + if (movingDirection.value == MovingDirection.RIGHT) { 209 + Text(">", fontWeight = FontWeight.Black, color = Color.White, modifier = Modifier.padding(top = 128.dp, start = camSizePx - 64.dp).scale(20f)) 210 + } else { 211 + Text("<", fontWeight = FontWeight.Black, color = Color.White, modifier = Modifier.padding(top = 128.dp, start = 32.dp).scale(20f)) 212 + } 213 + } 167 214 } 168 215 Slider(modifier = Modifier.padding(top = 64.dp), value = delayMillis.toFloat(), onValueChange = { 169 216 delayMillis = it.toInt()