From 883fd8e5e43b96e65e3e3892349089353d3d27ea Mon Sep 17 00:00:00 2001 From: Hermes Agent Date: Tue, 25 Aug 2026 02:15:48 +0300 Subject: [PATCH] =?UTF-8?q?=D0=92=D1=8B=D1=81=D0=BE=D1=82=D0=B0:=20=D0=B2?= =?UTF-8?q?=D0=B8=D0=B4=D0=B5=D0=BE=20=D0=B2=20=D0=BA=D0=BE=D0=BD=D1=82?= =?UTF-8?q?=D0=B5=D0=B9=D0=BD=D0=B5=D1=80=D0=B5=20=D0=BF=D1=80=D0=B8=D0=B6?= =?UTF-8?q?=D0=B8=D0=BC=D0=B0=D0=B5=D1=82=D1=81=D1=8F=20=D0=BA=20=D0=B2?= =?UTF-8?q?=D0=B5=D1=80=D1=85=D1=83/=D0=BD=D0=B8=D0=B7=D1=83=20=D0=BF?= =?UTF-8?q?=D0=BE=20vertical=20(Row-=D1=86=D0=B5=D0=BD=D1=82=D1=80=D0=B8?= =?UTF-8?q?=D1=80=D0=BE=D0=B2=D0=B0=D0=BD=D0=B8=D0=B5=20=D1=81=D1=8A=D0=B5?= =?UTF-8?q?=D0=B4=D0=B0=D0=BB=D0=BE=20=D0=B2=D0=B5=D1=80=D1=82=D0=B8=D0=BA?= =?UTF-8?q?=D0=B0=D0=BB=D1=8C)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../viewmate/glasses/ui/GlassesMovieScreen.kt | 15 ++++++++++- .../binom/viewmate/glasses/ScaleOffsetTest.kt | 26 +++++++++++++++++++ 2 files changed, 40 insertions(+), 1 deletion(-) diff --git a/app-glasses/src/main/kotlin/pw/binom/viewmate/glasses/ui/GlassesMovieScreen.kt b/app-glasses/src/main/kotlin/pw/binom/viewmate/glasses/ui/GlassesMovieScreen.kt index 0cd7a03..834960c 100644 --- a/app-glasses/src/main/kotlin/pw/binom/viewmate/glasses/ui/GlassesMovieScreen.kt +++ b/app-glasses/src/main/kotlin/pw/binom/viewmate/glasses/ui/GlassesMovieScreen.kt @@ -115,6 +115,9 @@ fun GlassesMovieScreen( ) { Row( modifier = Modifier.fillMaxWidth().background(Color.Black), + // Видео в контейнере прижимается к верху (vertical=1) или низу (vertical=0): + // Row-центрирование съедало вертикаль — картинка оставалась «по центру». + verticalAlignment = Alignment.Top, horizontalArrangement = if (side == Side.LEFT) Arrangement.End else Arrangement.Start, ) { if (SCALE_DEBUG_SQUARE) { @@ -125,7 +128,9 @@ fun GlassesMovieScreen( BinocularVideoPlayer( player = player, renderer = renderer, - modifier = Modifier.size(playerWidth.px, playerHeight.px), + modifier = Modifier + .size(playerWidth.px, playerHeight.px) + .offset(y = videoOffsetY(containerH, playerHeight, vertical).px), ) } } @@ -155,6 +160,14 @@ fun scaleOffsetX(side: Side, screenWidthPx: Int, scale: Float): Int = fun verticalOffsetY(screenHeightPx: Int, scale: Float, vertical: Float): Int = ((1f - vertical) * screenHeightPx * (1f - scale)).toInt() +/** + * Смещение видео внутри контейнера глаза: vertical=1.0 — у верха контейнера, + * 0.0 — у низа (нижняя кромка видео прижата к низу контейнера, который сам + * у низа экрана при vertical=0). Row-центрирование иначе съедало вертикаль. + */ +fun videoOffsetY(containerHeightPx: Int, videoHeightPx: Int, vertical: Float): Int = + ((1f - vertical) * (containerHeightPx - videoHeightPx).coerceAtLeast(0)).toInt() + /** Отладочный режим: красный квадрат вместо видео (проверка масштаба/позиций скрином). Перед финалом — false. */ private const val SCALE_DEBUG_SQUARE = false diff --git a/app-glasses/src/test/kotlin/pw/binom/viewmate/glasses/ScaleOffsetTest.kt b/app-glasses/src/test/kotlin/pw/binom/viewmate/glasses/ScaleOffsetTest.kt index 292a1d5..07f37f1 100644 --- a/app-glasses/src/test/kotlin/pw/binom/viewmate/glasses/ScaleOffsetTest.kt +++ b/app-glasses/src/test/kotlin/pw/binom/viewmate/glasses/ScaleOffsetTest.kt @@ -5,6 +5,7 @@ import kotlin.test.assertEquals import pw.binom.viewmate.glasses.ui.Side import pw.binom.viewmate.glasses.ui.scaleOffsetX import pw.binom.viewmate.glasses.ui.verticalOffsetY +import pw.binom.viewmate.glasses.ui.videoOffsetY /** * scaleOffsetX — смещение контейнера глаза к центру (к носу): @@ -62,4 +63,29 @@ class ScaleOffsetTest { assertEquals(72, verticalOffsetY(480, 0.7f, 0.5f)) assertEquals(0, verticalOffsetY(480, 1f, 0.5f)) } + + /* + * videoOffsetY — видео внутри контейнера: верх при vertical=1, низ при 0. + */ + + @Test + fun videoTop_zero() { + assertEquals(0, videoOffsetY(432, 268, 1f)) + } + + @Test + fun videoBottom_pushedToContainerBottom() { + // 432 контейнер, 268 видео: ход = 164 + assertEquals(164, videoOffsetY(432, 268, 0f)) + } + + @Test + fun videoMiddle_halfOfRun() { + assertEquals(82, videoOffsetY(432, 268, 0.5f)) + } + + @Test + fun videoLargerThanContainer_noNegativeOffset() { + assertEquals(0, videoOffsetY(200, 268, 0f), "видео выше контейнера — хода нет") + } }