From e924e697a2bf843fe66deec120f1dfec879ad241 Mon Sep 17 00:00:00 2001 From: NINI Date: Mon, 5 Oct 2026 05:28:49 +0900 Subject: [PATCH] Restore free-play cancellation prompt and map emulator touch coordinates --- .../MagnetismHeroes/Tests/PlayMode/CompositionPlayTests.cs | 2 ++ Assets/MagnetismHeroes/UnityRuntime/Bootstrap/GameApp.cs | 1 + .../MagnetismHeroes/UnityRuntime/Interaction/BoardInput.cs | 5 ----- tools/android/exercise-composition.ps1 | 6 +++--- tools/android/send-composition-touch.ps1 | 2 +- 5 files changed, 7 insertions(+), 9 deletions(-) diff --git a/Assets/MagnetismHeroes/Tests/PlayMode/CompositionPlayTests.cs b/Assets/MagnetismHeroes/Tests/PlayMode/CompositionPlayTests.cs index 71f5fe2..5989464 100644 --- a/Assets/MagnetismHeroes/Tests/PlayMode/CompositionPlayTests.cs +++ b/Assets/MagnetismHeroes/Tests/PlayMode/CompositionPlayTests.cs @@ -91,6 +91,8 @@ namespace MagnetismHeroes.Tests Assert.That(Vector3.Distance(_app.Presenter.Balls[states[0].id].transform.position, _app.Presenter.Balls[states[1].id].transform.position), Is.EqualTo(1).Within(.001f)); Assert.That(_app.Presenter.Balls.Values.All(ball => !ball.ContactCandidate), Is.True); Assert.That(_app.GetComponentsInChildren().Length, Is.EqualTo(1)); + Tap(states[0].id); _app.Input.BeginSplit(); Tap(states[0].id); _app.Input.CancelSplit(); + Assert.That(_app.Instruction, Is.EqualTo("해냈어! 친구와 자유롭게 놀아 보자.")); } [UnityTest] public IEnumerator FourteenDisconnectedSelectionThenMergeIsAcceptedByFinalNumbers() { diff --git a/Assets/MagnetismHeroes/UnityRuntime/Bootstrap/GameApp.cs b/Assets/MagnetismHeroes/UnityRuntime/Bootstrap/GameApp.cs index 2fc35a8..6b1994c 100644 --- a/Assets/MagnetismHeroes/UnityRuntime/Bootstrap/GameApp.cs +++ b/Assets/MagnetismHeroes/UnityRuntime/Bootstrap/GameApp.cs @@ -142,6 +142,7 @@ namespace MagnetismHeroes.UnityRuntime.Bootstrap _cancelSplitButton.gameObject.SetActive(_input.IsSplitting); if (_input.IsSplitting) _instruction.text = $"선택 {_input.SelectedCount} · 구를 골라 끌어내 보자."; else if (Session.Board?.Mode == BoardMode.Composition) _instruction.text = "붙이거나 나누어 목표 친구를 만들어 보자."; + else if (Session.Board?.Mode == BoardMode.FreePlay) _instruction.text = "해냈어! 친구와 자유롭게 놀아 보자."; _presenter.ShowSelection(_input.SelectedIds); } private void OnApplicationPause(bool paused) diff --git a/Assets/MagnetismHeroes/UnityRuntime/Interaction/BoardInput.cs b/Assets/MagnetismHeroes/UnityRuntime/Interaction/BoardInput.cs index d9f9acd..9d42290 100644 --- a/Assets/MagnetismHeroes/UnityRuntime/Interaction/BoardInput.cs +++ b/Assets/MagnetismHeroes/UnityRuntime/Interaction/BoardInput.cs @@ -33,8 +33,6 @@ namespace MagnetismHeroes.UnityRuntime.Interaction private float _pinchDistance; private int _fingerId = -1; private bool _waitForAllTouchesReleased; - private int _diagnosticEvents; - private bool _diagnosticReady; private int _pinchFirstId = -1, _pinchSecondId = -1; private readonly struct TouchContact { @@ -164,7 +162,6 @@ namespace MagnetismHeroes.UnityRuntime.Interaction private void RecordTouch(Finger finger) { - if (AcceptInput && _diagnosticEvents++ < 16) Debug.Log($"[CompositionInput] callback {finger.lastTouch.phase} screen={finger.screen?.name} current={Touchscreen.current?.name} gesture={_gesture}"); if (!AcceptInput || finger.screen != Touchscreen.current) return; // Copy each official history callback before later events overwrite the native touch slot. var touch = finger.lastTouch; @@ -231,7 +228,6 @@ namespace MagnetismHeroes.UnityRuntime.Interaction private void Update() { - if (AcceptInput && !_diagnosticReady) { _diagnosticReady = true; Debug.Log($"[CompositionInput] ready enabled={enabled} touchscreen={Touchscreen.current?.name} enhanced={EnhancedTouchSupport.enabled}"); } if (!AcceptInput) { _touchEvents.Clear(); _touches.Clear(); return; } bool hadTouches = _touchEvents.Count > 0, suppressRestOfFrame = false; while (_touchEvents.Count > 0) @@ -259,7 +255,6 @@ namespace MagnetismHeroes.UnityRuntime.Interaction } private void OnEnable() { - Debug.Log("[CompositionInput] subscribing"); EnhancedTouchSupport.Enable(); UnityEngine.InputSystem.EnhancedTouch.Touch.onFingerDown += RecordTouch; UnityEngine.InputSystem.EnhancedTouch.Touch.onFingerMove += RecordTouch; diff --git a/tools/android/exercise-composition.ps1 b/tools/android/exercise-composition.ps1 index c6e370a..8ab21f1 100644 --- a/tools/android/exercise-composition.ps1 +++ b/tools/android/exercise-composition.ps1 @@ -64,7 +64,7 @@ try { Step 'six-initial-face-number' @('shell','input','tap','480','560') 1200 $sixBefore=Save 'six-before'; Check 'six-real-initial' ((($sixBefore.puzzleStates[0].groups | ForEach-Object {$_.ballIds.Count}) -join ',') -eq '1,1') 'Two initial singleton groups' # Hold real Android touch while observing the contact candidate; no runtime control server. - Touch @(1009,510,401,1); Start-Sleep -Milliseconds 100; Touch @(1291,510,401,1); Step 'six-contact-candidate' + Touch @(1009,510,401,100); Start-Sleep -Milliseconds 100; Touch @(1291,510,401,100); Step 'six-contact-candidate' $preview=Save 'six-preview'; Check 'six-preview-not-saved' (SameJson $preview $sixBefore) 'Preview JSON equals committed initial JSON' Touch @(1291,510,401,0); Step 'six-success-face-number' $six=Save 'six-success'; Check 'six-final-two' ($six.completedStageIds -contains 6 -and $six.puzzleStates.Count -eq 0 -and $six.latestFreePlay.groups.Count -eq 1 -and $six.latestFreePlay.groups[0].ballIds.Count -eq 2) 'Completed6; one2 group; no unfinished' @@ -79,12 +79,12 @@ try { Step 'ten-all-selection-drag' @('shell','input','swipe','1120','510','850','510','500') Check 'ten-all-unchanged' (SameJson $tenBefore (Save 'ten-all-after')) 'Entire selection preserves JSON' Step 'ten-deselect-right' @('shell','input','tap','1280','510'); Step 'ten-selected-count-face-number' - Touch @(1120,510,411,1); Start-Sleep -Milliseconds 100; Touch @(900,510,411,1); Step 'ten-split-preview' + Touch @(1120,510,411,100); Start-Sleep -Milliseconds 100; Touch @(900,510,411,100); Step 'ten-split-preview' # UI cancel is a separate product action; release first restores invalid/outside gesture via a real edge release. Touch @(2500,510,411,0); Step 'ten-outside-cancel' Check 'ten-outside-cancel-unchanged' (SameJson $tenBefore (Save 'ten-outside-after')) 'Off-board release keeps committed JSON' Step 'ten-select-again' @('shell','input','tap','1120','510'); Step 'ten-split-again' @('shell','input','tap','312','832'); Step 'ten-selection-again' @('shell','input','tap','1120','510') - Touch @(1120,510,421,1); Touch @(1030,510,421,1); Touch @(1390,510,422,1) + Touch @(1120,510,421,100); Touch @(1030,510,421,100); Touch @(1390,510,422,100) Touch @(1030,510,421,0,1390,510,422,0); Step 'ten-pinch-switch' $pinch=Save 'ten-pinch-after'; Check 'ten-pinch-no-split' ($pinch.puzzleStates[0].groups.Count -eq 1 -and (SameJson $pinch.puzzleStates[0].balls $tenBefore.puzzleStates[0].balls)) 'Pinch aborts split, all ball positions unchanged' # Return to unchanged committed camera by restarting from the fresh fixture before the successful split. diff --git a/tools/android/send-composition-touch.ps1 b/tools/android/send-composition-touch.ps1 index 0ae3bf1..a613971 100644 --- a/tools/android/send-composition-touch.ps1 +++ b/tools/android/send-composition-touch.ps1 @@ -13,7 +13,7 @@ function Varint([int]$Value) { $message=[Collections.Generic.List[byte]]::new() for ($offset=0; $offset -lt $Contacts.Count; $offset+=4) { # AVD touch injection uses portrait physical coordinates even when the app is landscape-left. - $fields=@(1080-$Contacts[$offset+1],$Contacts[$offset],$Contacts[$offset+2],$Contacts[$offset+3]) + $fields=@((1080-$Contacts[$offset+1]),$Contacts[$offset],$Contacts[$offset+2],$Contacts[$offset+3]) $touch=[Collections.Generic.List[byte]]::new() for ($field=0; $field -lt 4; $field++) { $touch.Add([byte](8*($field+1))); $touch.AddRange([byte[]](Varint $fields[$field])) } $message.Add(10); $message.AddRange([byte[]](Varint $touch.Count)); $message.AddRange($touch.ToArray())