Add 2D focus positioning, fix rotation tracking, sync preview with effect
2D positioning: - Add positionX parameter to BlurParameters (was only Y before) - Update shader with uPositionX and uPositionY uniforms - Single-finger drag now moves focus center anywhere on screen - Update gradient mask generation for capture Rotation tracking: - Remove dampening from rotation gesture (1:1 tracking) - Rotate gesture now directly tracks finger movement - Preview effect rotates in sync with overlay Overlay and shader sync: - Both now use same positionX, positionY, angle parameters - Preview blur effect matches overlay visualization Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
parent
e3e05af0b8
commit
e53155e8ee
5 changed files with 53 additions and 41 deletions
|
|
@ -33,17 +33,17 @@ import kotlin.math.sin
|
|||
*/
|
||||
private enum class GestureType {
|
||||
NONE,
|
||||
DRAG_POSITION, // Single finger drag to move focus position
|
||||
DRAG_POSITION, // Single finger drag to move focus center
|
||||
ROTATE, // Two-finger rotation
|
||||
PINCH_SIZE, // Pinch near blur edges to resize
|
||||
PINCH_ZOOM // Pinch in center to zoom camera
|
||||
}
|
||||
|
||||
// Sensitivity factors for gesture controls (lower = less sensitive)
|
||||
private const val POSITION_SENSITIVITY = 0.15f // Drag to move focus line
|
||||
private const val ROTATION_SENSITIVITY = 0.2f // Two-finger rotation
|
||||
private const val SIZE_SENSITIVITY = 0.25f // Pinch to resize blur zone
|
||||
private const val ZOOM_SENSITIVITY = 0.4f // Pinch to zoom camera
|
||||
// Rotation uses 1:1 tracking (no dampening) for natural feel
|
||||
private const val POSITION_SENSITIVITY = 0.5f // Drag to move focus center
|
||||
private const val SIZE_SENSITIVITY = 0.3f // Pinch to resize blur zone
|
||||
private const val ZOOM_SENSITIVITY = 0.5f // Pinch to zoom camera
|
||||
|
||||
/**
|
||||
* Overlay that shows tilt-shift effect controls and handles gestures.
|
||||
|
|
@ -56,10 +56,10 @@ fun TiltShiftOverlay(
|
|||
modifier: Modifier = Modifier
|
||||
) {
|
||||
var currentGesture by remember { mutableStateOf(GestureType.NONE) }
|
||||
var initialZoom by remember { mutableFloatStateOf(1f) }
|
||||
var initialAngle by remember { mutableFloatStateOf(0f) }
|
||||
var initialSize by remember { mutableFloatStateOf(0.3f) }
|
||||
var initialPosition by remember { mutableFloatStateOf(0.5f) }
|
||||
var initialPositionX by remember { mutableFloatStateOf(0.5f) }
|
||||
var initialPositionY by remember { mutableFloatStateOf(0.5f) }
|
||||
|
||||
Canvas(
|
||||
modifier = modifier
|
||||
|
|
@ -70,15 +70,15 @@ fun TiltShiftOverlay(
|
|||
currentGesture = GestureType.NONE
|
||||
|
||||
var previousCentroid = firstDown.position
|
||||
var previousPointerCount = 1
|
||||
var accumulatedRotation = 0f
|
||||
var accumulatedZoom = 1f
|
||||
var accumulatedDragX = 0f
|
||||
var accumulatedDragY = 0f
|
||||
|
||||
initialAngle = params.angle
|
||||
initialSize = params.size
|
||||
initialPosition = params.position
|
||||
initialZoom = 1f
|
||||
initialPositionX = params.positionX
|
||||
initialPositionY = params.positionY
|
||||
|
||||
do {
|
||||
val event = awaitPointerEvent()
|
||||
|
|
@ -110,8 +110,8 @@ fun TiltShiftOverlay(
|
|||
|
||||
when (currentGesture) {
|
||||
GestureType.ROTATE -> {
|
||||
// Apply dampening to rotation
|
||||
accumulatedRotation += rotation * ROTATION_SENSITIVITY
|
||||
// 1:1 rotation tracking - no dampening
|
||||
accumulatedRotation += rotation
|
||||
val newAngle = initialAngle + accumulatedRotation
|
||||
onParamsChange(params.copy(angle = newAngle))
|
||||
}
|
||||
|
|
@ -132,24 +132,25 @@ fun TiltShiftOverlay(
|
|||
}
|
||||
}
|
||||
|
||||
// Single finger
|
||||
// Single finger - drag to move focus center (2D)
|
||||
pointers.size == 1 -> {
|
||||
if (currentGesture == GestureType.NONE) {
|
||||
currentGesture = GestureType.DRAG_POSITION
|
||||
}
|
||||
|
||||
if (currentGesture == GestureType.DRAG_POSITION) {
|
||||
// Apply dampening to position drag
|
||||
val deltaX = (centroid.x - previousCentroid.x) / size.width
|
||||
val deltaY = (centroid.y - previousCentroid.y) / size.height
|
||||
accumulatedDragX += deltaX * POSITION_SENSITIVITY
|
||||
accumulatedDragY += deltaY * POSITION_SENSITIVITY
|
||||
val newPosition = (initialPosition + accumulatedDragY).coerceIn(0f, 1f)
|
||||
onParamsChange(params.copy(position = newPosition))
|
||||
val newX = (initialPositionX + accumulatedDragX).coerceIn(0f, 1f)
|
||||
val newY = (initialPositionY + accumulatedDragY).coerceIn(0f, 1f)
|
||||
onParamsChange(params.copy(positionX = newX, positionY = newY))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
previousCentroid = centroid
|
||||
previousPointerCount = pointers.size
|
||||
|
||||
// Consume all pointer changes
|
||||
pointers.forEach { it.consume() }
|
||||
|
|
@ -172,12 +173,13 @@ private fun determineGestureType(
|
|||
height: Float,
|
||||
params: BlurParameters
|
||||
): GestureType {
|
||||
// Calculate distance from focus center line
|
||||
val focusCenterY = height * params.position
|
||||
// Calculate distance from focus center
|
||||
val focusCenterX = width * params.positionX
|
||||
val focusCenterY = height * params.positionY
|
||||
val focusHalfHeight = height * params.size * 0.5f
|
||||
|
||||
// Rotate centroid to align with focus line
|
||||
val dx = centroid.x - width / 2f
|
||||
val dx = centroid.x - focusCenterX
|
||||
val dy = centroid.y - focusCenterY
|
||||
val rotatedY = -dx * sin(params.angle) + dy * cos(params.angle)
|
||||
|
||||
|
|
@ -207,8 +209,8 @@ private fun DrawScope.drawTiltShiftOverlay(params: BlurParameters) {
|
|||
val width = size.width
|
||||
val height = size.height
|
||||
|
||||
val centerX = width / 2f
|
||||
val centerY = height * params.position
|
||||
val centerX = width * params.positionX
|
||||
val centerY = height * params.positionY
|
||||
val focusHalfHeight = height * params.size * 0.5f
|
||||
val angleDegrees = params.angle * (180f / PI.toFloat())
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue