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
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<PointerId, String>()
// Карта для отслеживания активных указателей и их текущих нот
val activePointers = mutableMapOf<PointerId, Pair<String, Float>>()
while (true) {
val event = awaitPointerEvent()
// Обрабатываем все изменения в событии
for (change in event.changes) {
// Временный набор для обновления активных клавиш
val newActiveKeys = mutableSetOf<String>()
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,