diff --git a/app/src/main/java/net/sergeych/karabass/PianoKeyboard.kt b/app/src/main/java/net/sergeych/karabass/PianoKeyboard.kt index 0bd8679..e302740 100644 --- a/app/src/main/java/net/sergeych/karabass/PianoKeyboard.kt +++ b/app/src/main/java/net/sergeych/karabass/PianoKeyboard.kt @@ -1,12 +1,10 @@ package net.sergeych.karabass - import androidx.compose.foundation.Canvas import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.runtime.* import androidx.compose.ui.Modifier import androidx.compose.ui.geometry.Offset -import androidx.compose.ui.geometry.Rect import androidx.compose.ui.geometry.Size import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.drawscope.DrawScope @@ -44,14 +42,16 @@ fun PianoKeyboard( .fillMaxSize() .pointerInput(synth, whiteKeys, blackKeys, isHorizontal, availableNotes) { awaitPointerEventScope { - // Карта для отслеживания активных указателей и их нот - val activePointers = mutableMapOf() + // Карта для отслеживания активных указателей и их текущих нот + val activePointers = mutableMapOf>() while (true) { val event = awaitPointerEvent() - // Обрабатываем все изменения в событии - for (change in event.changes) { + // Временный набор для обновления активных клавиш + val newActiveKeys = mutableSetOf() + + event.changes.forEach { change -> val pointerId = change.id val position = change.position val canvasSize = Size(size.width.toFloat(), size.height.toFloat()) @@ -70,10 +70,9 @@ fun PianoKeyboard( change.pressed -> { key?.let { (noteName, frequency) -> // Запоминаем связь указатель-нота - activePointers[pointerId] = noteName - activeKeys = activeKeys + noteName + activePointers[pointerId] = noteName to frequency + newActiveKeys.add(noteName) - println("startNote $noteName $frequency") if (synth.isActive()) { // Легато - плавный переход на новую ноту synth.changeNote(frequency) @@ -86,21 +85,16 @@ fun PianoKeyboard( // ОТПУСКАНИЕ - когда указатель отпущен !change.pressed -> { - val releasedNoteName = activePointers.remove(pointerId) - releasedNoteName?.let { noteName -> - activeKeys = activeKeys - noteName - + val releasedNote = activePointers.remove(pointerId) + releasedNote?.let { (noteName, _) -> if (activePointers.isEmpty()) { // Все клавиши отпущены - останавливаем ноту synth.stopNote() } else { // Есть другие активные клавиши - переключаемся на одну из них - val remainingNoteName = activePointers.values.firstOrNull() - remainingNoteName?.let { name -> - val remainingNote = availableNotes.find { it.first == name } - remainingNote?.let { - synth.changeNote(it.second) - } + val remainingNote = activePointers.values.firstOrNull() + remainingNote?.let { + synth.changeNote(it.second) } } } @@ -109,16 +103,12 @@ fun PianoKeyboard( // ПЕРЕМЕЩЕНИЕ - когда указатель переместился change.positionChanged() -> { key?.let { (newNoteName, newFrequency) -> - val currentNoteName = activePointers[pointerId] + val currentNote = activePointers[pointerId] // Если указатель переместился на другую клавишу - if (currentNoteName != newNoteName) { - // Обновляем активные клавиши - currentNoteName?.let { - activeKeys = activeKeys - it - } - activeKeys = activeKeys + newNoteName - activePointers[pointerId] = newNoteName + if (currentNote?.first != newNoteName) { + // Обновляем активную ноту для этого указателя + activePointers[pointerId] = newNoteName to newFrequency // Плавно переключаем ноту if (synth.isActive()) { @@ -132,6 +122,17 @@ fun PianoKeyboard( // Всегда сообщаем, что обработали событие change.consume() } + + // ОБНОВЛЯЕМ АКТИВНЫЕ КЛАВИШИ на основе текущего состояния всех указателей + // Это гарантирует, что визуальное состояние всегда соответствует звуковому + activePointers.values.forEach { (noteName, _) -> + newActiveKeys.add(noteName) + } + + // Применяем обновление активных клавиш + if (activeKeys != newActiveKeys) { + activeKeys = newActiveKeys + } } } } @@ -155,7 +156,7 @@ fun PianoKeyboard( } } -// Вспомогательные функции остаются без изменений: +// Остальные вспомогательные функции остаются без изменений: private fun findKeyAtOffset( offset: Offset, @@ -183,7 +184,7 @@ private fun findKeyAtOffsetHorizontal( blackKeys.forEachIndexed { index, blackKey -> val blackKeyX = (getWhiteKeyIndexForBlackKey(blackKey.first, whiteKeys) * whiteKeyWidth) - (whiteKeyWidth * 0.25f) - val blackKeyRect = Rect( + val blackKeyRect = androidx.compose.ui.geometry.Rect( left = blackKeyX, top = 0f, right = blackKeyX + whiteKeyWidth * 0.5f, @@ -196,7 +197,7 @@ private fun findKeyAtOffsetHorizontal( // Затем проверяем белые клавиши whiteKeys.forEachIndexed { index, whiteKey -> - val whiteKeyRect = Rect( + val whiteKeyRect = androidx.compose.ui.geometry.Rect( left = index * whiteKeyWidth, top = 0f, right = (index + 1) * whiteKeyWidth, @@ -222,7 +223,7 @@ private fun findKeyAtOffsetVertical( blackKeys.forEachIndexed { index, blackKey -> val blackKeyY = (getWhiteKeyIndexForBlackKey(blackKey.first, whiteKeys) * whiteKeyHeight) - (whiteKeyHeight * 0.25f) - val blackKeyRect = Rect( + val blackKeyRect = androidx.compose.ui.geometry.Rect( left = size.width * 0.4f, top = blackKeyY, right = size.width, @@ -235,7 +236,7 @@ private fun findKeyAtOffsetVertical( // Затем проверяем белые клавиши whiteKeys.forEachIndexed { index, whiteKey -> - val whiteKeyRect = Rect( + val whiteKeyRect = androidx.compose.ui.geometry.Rect( left = 0f, top = index * whiteKeyHeight, right = size.width,