fixed bug with keyboard

This commit is contained in:
Sergey Chernov 2025-10-13 14:48:21 +04:00
parent 8b68261701
commit c4cf8749fb

View File

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