chore(unity): 固定Unity CLI Loop本地包并移除UnitySkills依赖

This commit is contained in:
Liubing\LB
2026-09-28 18:14:59 +08:00
parent 0eb43b2b40
commit c4ae02def9
952 changed files with 70137 additions and 11 deletions

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: ab4c098822c5e40d0b384302c39f65da
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,31 @@
#if UNITY_EDITOR
using UnityEngine;
namespace io.github.hatayama.uLoopMCP
{
// Orchestrator that owns the shared Canvas and holds references to all input visualization overlays.
public class InputVisualizationCanvas : MonoBehaviour
{
[SerializeField] private SimulateKeyboardOverlay _keyboardOverlay = null!;
[SerializeField] private SimulateMouseUiOverlay _mouseUiOverlay = null!;
[SerializeField] private SimulateMouseInputOverlay _mouseInputOverlay = null!;
[SerializeField] private RecordInputOverlayPresenter _recordInputOverlayPresenter = null!;
[SerializeField] private ReplayInputOverlay _replayInputOverlay = null!;
public SimulateKeyboardOverlay KeyboardOverlay => _keyboardOverlay;
public SimulateMouseUiOverlay MouseUiOverlay => _mouseUiOverlay;
public SimulateMouseInputOverlay MouseInputOverlay => _mouseInputOverlay;
public RecordInputOverlayPresenter RecordInputOverlayPresenter => _recordInputOverlayPresenter;
public ReplayInputOverlay ReplayInputOverlay => _replayInputOverlay;
private void Awake()
{
Debug.Assert(_keyboardOverlay != null, "_keyboardOverlay must be assigned in prefab");
Debug.Assert(_mouseUiOverlay != null, "_mouseUiOverlay must be assigned in prefab");
Debug.Assert(_mouseInputOverlay != null, "_mouseInputOverlay must be assigned in prefab");
Debug.Assert(_recordInputOverlayPresenter != null, "_recordInputOverlayPresenter must be assigned in prefab");
Debug.Assert(_replayInputOverlay != null, "_replayInputOverlay must be assigned in prefab");
}
}
}
#endif

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: abc797fe786864ddab9e872d087723eb
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: 040b130e95b7a4d379927e0aa2534364
PrefabImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,9 @@
namespace io.github.hatayama.uLoopMCP
{
public enum MouseButton
{
Left = 0,
Right = 1,
Middle = 2
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 71af0a970da6c4ae2ba68a415a87b3e7
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 00ecf84e5e6c94d098a71f88a0a52b82
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,502 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!1 &22181428640489494
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 3582369045929623476}
- component: {fileID: 3614889816338958305}
- component: {fileID: 2719428274581312071}
- component: {fileID: 7892078462694320466}
m_Layer: 0
m_Name: RecordingGroup
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!224 &3582369045929623476
RectTransform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 22181428640489494}
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children:
- {fileID: 3621534349862372398}
- {fileID: 5117071643518484791}
m_Father: {fileID: 6520280533638980191}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0.5, y: 1}
m_AnchorMax: {x: 0.5, y: 1}
m_AnchoredPosition: {x: 0, y: 0}
m_SizeDelta: {x: 308.3724, y: 37.9532}
m_Pivot: {x: 0.5, y: 1}
--- !u!222 &3614889816338958305
CanvasRenderer:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 22181428640489494}
m_CullTransparentMesh: 1
--- !u!114 &2719428274581312071
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 22181428640489494}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3}
m_Name:
m_EditorClassIdentifier:
m_Material: {fileID: 0}
m_Color: {r: 0, g: 0, b: 0, a: 0.6}
m_RaycastTarget: 1
m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
m_Maskable: 1
m_OnCullStateChanged:
m_PersistentCalls:
m_Calls: []
m_Sprite: {fileID: 0}
m_Type: 0
m_PreserveAspect: 0
m_FillCenter: 1
m_FillMethod: 4
m_FillAmount: 1
m_FillClockwise: 1
m_FillOrigin: 0
m_UseSpriteMesh: 0
m_PixelsPerUnitMultiplier: 1
--- !u!114 &7892078462694320466
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 22181428640489494}
m_Enabled: 0
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 30649d3a9faa99c48a7b1166b86bf2a0, type: 3}
m_Name:
m_EditorClassIdentifier:
m_Padding:
m_Left: 10
m_Right: 10
m_Top: 4
m_Bottom: 4
m_ChildAlignment: 4
m_Spacing: 6
m_ChildForceExpandWidth: 0
m_ChildForceExpandHeight: 0
m_ChildControlWidth: 0
m_ChildControlHeight: 0
m_ChildScaleWidth: 0
m_ChildScaleHeight: 0
m_ReverseArrangement: 0
--- !u!1 &5910659660082971454
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 6520280533638980191}
- component: {fileID: 1629439249830669379}
- component: {fileID: 7672979299455549903}
- component: {fileID: 7304014939787943379}
m_Layer: 0
m_Name: RecordInputOverlay
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!224 &6520280533638980191
RectTransform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 5910659660082971454}
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children:
- {fileID: 8858599889832361986}
- {fileID: 3582369045929623476}
m_Father: {fileID: 0}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0.5, y: 1}
m_AnchorMax: {x: 0.5, y: 1}
m_AnchoredPosition: {x: 0, y: -10}
m_SizeDelta: {x: 400, y: 120}
m_Pivot: {x: 0.5, y: 1}
--- !u!225 &1629439249830669379
CanvasGroup:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 5910659660082971454}
m_Enabled: 1
m_Alpha: 1
m_Interactable: 0
m_BlocksRaycasts: 0
m_IgnoreParentGroups: 0
--- !u!114 &7672979299455549903
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 5910659660082971454}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 626f611c789dd4febbff8920eeb25837, type: 3}
m_Name:
m_EditorClassIdentifier:
_canvasGroup: {fileID: 1629439249830669379}
_countdownGroup: {fileID: 8747864644649913744}
_countdownText: {fileID: 5505213563100565343}
_recordingGroup: {fileID: 22181428640489494}
_recDotText: {fileID: 8821962787790114429}
_statusText: {fileID: 681519330149296984}
--- !u!114 &7304014939787943379
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 5910659660082971454}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 55b9e485125e14c979260f3aa7816f9c, type: 3}
m_Name:
m_EditorClassIdentifier:
_view: {fileID: 7672979299455549903}
--- !u!1 &7302841544564334857
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 5117071643518484791}
- component: {fileID: 4639771590543201793}
- component: {fileID: 681519330149296984}
m_Layer: 0
m_Name: StatusText
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!224 &5117071643518484791
RectTransform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 7302841544564334857}
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 3582369045929623476}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0, y: 1}
m_AnchorMax: {x: 0, y: 1}
m_AnchoredPosition: {x: 152.7, y: -18.25}
m_SizeDelta: {x: 100, y: 100}
m_Pivot: {x: 0.5, y: 0.5}
--- !u!222 &4639771590543201793
CanvasRenderer:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 7302841544564334857}
m_CullTransparentMesh: 1
--- !u!114 &681519330149296984
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 7302841544564334857}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 5f7201a12d95ffc409449d95f23cf332, type: 3}
m_Name:
m_EditorClassIdentifier:
m_Material: {fileID: 0}
m_Color: {r: 1, g: 0.267, b: 0.267, a: 1}
m_RaycastTarget: 1
m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
m_Maskable: 1
m_OnCullStateChanged:
m_PersistentCalls:
m_Calls: []
m_FontData:
m_Font: {fileID: 10102, guid: 0000000000000000e000000000000000, type: 0}
m_FontSize: 34
m_FontStyle: 1
m_BestFit: 0
m_MinSize: 2
m_MaxSize: 40
m_Alignment: 4
m_AlignByGeometry: 0
m_RichText: 1
m_HorizontalOverflow: 1
m_VerticalOverflow: 0
m_LineSpacing: 1
m_Text: REC 00:00
--- !u!1 &8311708416284801602
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 3621534349862372398}
- component: {fileID: 754498044577037662}
- component: {fileID: 8821962787790114429}
m_Layer: 0
m_Name: RecDot
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!224 &3621534349862372398
RectTransform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 8311708416284801602}
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 3582369045929623476}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0.5, y: 0.5}
m_AnchorMax: {x: 0.5, y: 0.5}
m_AnchoredPosition: {x: -115, y: 3.71}
m_SizeDelta: {x: 100, y: 100}
m_Pivot: {x: 0.5, y: 0.5}
--- !u!222 &754498044577037662
CanvasRenderer:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 8311708416284801602}
m_CullTransparentMesh: 1
--- !u!114 &8821962787790114429
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 8311708416284801602}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 5f7201a12d95ffc409449d95f23cf332, type: 3}
m_Name:
m_EditorClassIdentifier:
m_Material: {fileID: 0}
m_Color: {r: 1, g: 0.267, b: 0.267, a: 1}
m_RaycastTarget: 1
m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
m_Maskable: 1
m_OnCullStateChanged:
m_PersistentCalls:
m_Calls: []
m_FontData:
m_Font: {fileID: 10102, guid: 0000000000000000e000000000000000, type: 0}
m_FontSize: 43
m_FontStyle: 0
m_BestFit: 0
m_MinSize: 2
m_MaxSize: 69
m_Alignment: 4
m_AlignByGeometry: 0
m_RichText: 1
m_HorizontalOverflow: 1
m_VerticalOverflow: 0
m_LineSpacing: 0.41
m_Text: "\u25CF"
--- !u!1 &8406836639261979753
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 3888244186547671568}
- component: {fileID: 1083919491349555004}
- component: {fileID: 5505213563100565343}
m_Layer: 0
m_Name: CountdownText
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!224 &3888244186547671568
RectTransform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 8406836639261979753}
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 8858599889832361986}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0.5, y: 0.5}
m_AnchorMax: {x: 0.5, y: 0.5}
m_AnchoredPosition: {x: 0, y: 0.2}
m_SizeDelta: {x: 400, y: 70}
m_Pivot: {x: 0.5, y: 0.5}
--- !u!222 &1083919491349555004
CanvasRenderer:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 8406836639261979753}
m_CullTransparentMesh: 1
--- !u!114 &5505213563100565343
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 8406836639261979753}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 5f7201a12d95ffc409449d95f23cf332, type: 3}
m_Name:
m_EditorClassIdentifier:
m_Material: {fileID: 0}
m_Color: {r: 1, g: 0.267, b: 0.267, a: 1}
m_RaycastTarget: 1
m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
m_Maskable: 1
m_OnCullStateChanged:
m_PersistentCalls:
m_Calls: []
m_FontData:
m_Font: {fileID: 10102, guid: 0000000000000000e000000000000000, type: 0}
m_FontSize: 48
m_FontStyle: 0
m_BestFit: 0
m_MinSize: 10
m_MaxSize: 48
m_Alignment: 4
m_AlignByGeometry: 0
m_RichText: 1
m_HorizontalOverflow: 1
m_VerticalOverflow: 1
m_LineSpacing: 1
m_Text: REC in 3...
--- !u!1 &8747864644649913744
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 8858599889832361986}
- component: {fileID: 8837628031120365172}
- component: {fileID: 2701087203241486620}
m_Layer: 0
m_Name: CountdownGroup
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!224 &8858599889832361986
RectTransform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 8747864644649913744}
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children:
- {fileID: 3888244186547671568}
m_Father: {fileID: 6520280533638980191}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0, y: 0}
m_AnchorMax: {x: 1, y: 1}
m_AnchoredPosition: {x: 0, y: -25.460205}
m_SizeDelta: {x: 0, y: -50.9205}
m_Pivot: {x: 0.5, y: 0.5}
--- !u!222 &8837628031120365172
CanvasRenderer:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 8747864644649913744}
m_CullTransparentMesh: 1
--- !u!114 &2701087203241486620
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 8747864644649913744}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3}
m_Name:
m_EditorClassIdentifier:
m_Material: {fileID: 0}
m_Color: {r: 0, g: 0, b: 0, a: 0.6}
m_RaycastTarget: 1
m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
m_Maskable: 1
m_OnCullStateChanged:
m_PersistentCalls:
m_Calls: []
m_Sprite: {fileID: 0}
m_Type: 0
m_PreserveAspect: 0
m_FillCenter: 1
m_FillMethod: 4
m_FillAmount: 1
m_FillClockwise: 1
m_FillOrigin: 0
m_UseSpriteMesh: 0
m_PixelsPerUnitMultiplier: 1

View File

@@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: 62ec688be40ba465a8653a8437b9a739
PrefabImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,91 @@
#if UNITY_EDITOR
using System.Globalization;
using UnityEngine;
namespace io.github.hatayama.uLoopMCP
{
public class RecordInputOverlayPresenter : MonoBehaviour
{
private const float FADE_OUT_DURATION = 0.5f;
private const float DOT_BLINK_SPEED = 2f;
[SerializeField] private RecordInputOverlayView _view;
private bool _wasActive;
private float _deactivatedTime;
private int _lastMinutes = -1;
private int _lastSecs = -1;
private string _cachedStatusText = "";
private void Awake()
{
Debug.Assert(_view != null, "_view must be assigned in prefab");
}
private void LateUpdate()
{
RecordInputOverlayPhase phase = RecordInputOverlayState.Phase;
if (phase != RecordInputOverlayPhase.None)
{
_wasActive = true;
_deactivatedTime = 0f;
switch (phase)
{
case RecordInputOverlayPhase.Countdown:
int remaining = Mathf.CeilToInt(RecordInputOverlayState.RemainingSeconds);
_view.ShowCountdown(remaining);
break;
case RecordInputOverlayPhase.Recording:
string statusText = FormatStatusText(RecordInputOverlayState.ElapsedSeconds);
float dotAlpha = Mathf.PingPong(Time.realtimeSinceStartup * DOT_BLINK_SPEED, 1f);
_view.ShowRecording(statusText, dotAlpha);
break;
}
return;
}
if (!_wasActive)
{
return;
}
if (_deactivatedTime <= 0f)
{
_deactivatedTime = Time.realtimeSinceStartup;
_view.ShowStopped();
return;
}
float fadingElapsed = Time.realtimeSinceStartup - _deactivatedTime;
if (fadingElapsed > FADE_OUT_DURATION)
{
_view.Hide();
_wasActive = false;
_deactivatedTime = 0f;
return;
}
float alpha = 1f - (fadingElapsed / FADE_OUT_DURATION);
_view.SetAlpha(alpha);
}
private string FormatStatusText(float seconds)
{
int minutes = (int)(seconds / 60f);
int secs = (int)(seconds % 60f);
if (minutes == _lastMinutes && secs == _lastSecs)
{
return _cachedStatusText;
}
_lastMinutes = minutes;
_lastSecs = secs;
_cachedStatusText = string.Format(CultureInfo.InvariantCulture, "REC {0:D2}:{1:D2}", minutes, secs);
return _cachedStatusText;
}
}
}
#endif

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 55b9e485125e14c979260f3aa7816f9c
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,64 @@
using UnityEngine;
namespace io.github.hatayama.uLoopMCP
{
public enum RecordInputOverlayPhase
{
None,
Countdown,
Recording
}
public static class RecordInputOverlayState
{
private static RecordInputOverlayPhase _phase;
private static float _countdownEndTime;
private static float _recordingStartTime;
public static RecordInputOverlayPhase Phase => _phase;
public static float RemainingSeconds
{
get
{
if (_phase != RecordInputOverlayPhase.Countdown)
{
return 0f;
}
float remaining = _countdownEndTime - Time.realtimeSinceStartup;
return remaining > 0f ? remaining : 0f;
}
}
public static float ElapsedSeconds
{
get
{
if (_phase != RecordInputOverlayPhase.Recording)
{
return 0f;
}
return Time.realtimeSinceStartup - _recordingStartTime;
}
}
public static void StartCountdown(float durationSeconds)
{
_phase = RecordInputOverlayPhase.Countdown;
_countdownEndTime = Time.realtimeSinceStartup + durationSeconds;
}
public static void StartRecording()
{
_phase = RecordInputOverlayPhase.Recording;
_recordingStartTime = Time.realtimeSinceStartup;
}
public static void Clear()
{
_phase = RecordInputOverlayPhase.None;
_countdownEndTime = 0f;
_recordingStartTime = 0f;
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: a506fd4ae8f6b46c294dca15e5da34fd
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,75 @@
#if UNITY_EDITOR
using UnityEngine;
using UnityEngine.UI;
namespace io.github.hatayama.uLoopMCP
{
public class RecordInputOverlayView : MonoBehaviour
{
[SerializeField] private CanvasGroup _canvasGroup;
[SerializeField] private GameObject _countdownGroup;
[SerializeField] private Text _countdownText;
[SerializeField] private GameObject _recordingGroup;
[SerializeField] private Text _recDotText;
[SerializeField] private Text _statusText;
private void Awake()
{
Debug.Assert(_canvasGroup != null, "_canvasGroup must be assigned in prefab");
Debug.Assert(_countdownGroup != null, "_countdownGroup must be assigned in prefab");
Debug.Assert(_countdownText != null, "_countdownText must be assigned in prefab");
Debug.Assert(_recordingGroup != null, "_recordingGroup must be assigned in prefab");
Debug.Assert(_recDotText != null, "_recDotText must be assigned in prefab");
Debug.Assert(_statusText != null, "_statusText must be assigned in prefab");
_canvasGroup.interactable = false;
_canvasGroup.blocksRaycasts = false;
Hide();
}
public void ShowCountdown(int remainingSeconds)
{
_countdownGroup.SetActive(true);
_recordingGroup.SetActive(false);
_countdownText.text = $"REC in {remainingSeconds}...";
_canvasGroup.alpha = 1f;
}
public void ShowRecording(string statusText, float dotAlpha)
{
_countdownGroup.SetActive(false);
_recordingGroup.SetActive(true);
_statusText.text = statusText;
SetDotAlpha(dotAlpha);
_canvasGroup.alpha = 1f;
}
public void ShowStopped()
{
_countdownGroup.SetActive(false);
_recordingGroup.SetActive(true);
_statusText.text = "REC STOPPED";
SetDotAlpha(1f);
}
private void SetDotAlpha(float alpha)
{
Color dotColor = _recDotText.color;
dotColor.a = alpha;
_recDotText.color = dotColor;
}
public void SetAlpha(float alpha)
{
_canvasGroup.alpha = alpha;
}
public void Hide()
{
_canvasGroup.alpha = 0f;
_countdownGroup.SetActive(false);
_recordingGroup.SetActive(false);
}
}
}
#endif

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 626f611c789dd4febbff8920eeb25837
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 4317370db4e1f4059a36b24c7d7d28ec
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,109 @@
#if UNITY_EDITOR
#nullable enable
using UnityEngine;
using UnityEngine.UI;
namespace io.github.hatayama.uLoopMCP
{
// Overlay that displays replay progress (frame counter and progress bar)
// during input replay. Keyboard/mouse visualization is handled by existing
// SimulateKeyboardOverlay and SimulateMouseInputOverlay.
public class ReplayInputOverlay : MonoBehaviour
{
private const float FADE_OUT_DURATION = 0.5f;
[SerializeField] private Text? _statusText;
[SerializeField] private Image? _progressBarFill;
[SerializeField] private GameObject? _loopIcon;
private CanvasGroup _canvasGroup = null!;
private bool _wasActive;
private float _deactivatedTime;
private void Awake()
{
_canvasGroup = GetComponent<CanvasGroup>();
if (_canvasGroup == null)
{
_canvasGroup = gameObject.AddComponent<CanvasGroup>();
}
_canvasGroup.interactable = false;
_canvasGroup.blocksRaycasts = false;
SetVisible(false);
}
private void LateUpdate()
{
if (ReplayInputOverlayState.IsActive)
{
_wasActive = true;
_deactivatedTime = 0f;
SetVisible(true);
UpdateDisplay();
return;
}
if (!_wasActive)
{
return;
}
float elapsed = Time.realtimeSinceStartup - _deactivatedTime;
if (_deactivatedTime <= 0f)
{
_deactivatedTime = Time.realtimeSinceStartup;
UpdateStatusText("REPLAY COMPLETE");
return;
}
if (elapsed > FADE_OUT_DURATION)
{
SetVisible(false);
_wasActive = false;
_deactivatedTime = 0f;
return;
}
float alpha = 1f - (elapsed / FADE_OUT_DURATION);
_canvasGroup.alpha = alpha;
}
private void UpdateDisplay()
{
int currentFrame = ReplayInputOverlayState.CurrentFrame;
int totalFrames = ReplayInputOverlayState.TotalFrames;
bool isLooping = ReplayInputOverlayState.IsLooping;
string loopLabel = isLooping ? " \u21BB" : "";
UpdateStatusText($"REPLAY {currentFrame} / {totalFrames}{loopLabel}");
if (_progressBarFill != null)
{
Vector3 scale = _progressBarFill.rectTransform.localScale;
scale.x = ReplayInputOverlayState.Progress;
_progressBarFill.rectTransform.localScale = scale;
}
if (_loopIcon != null)
{
_loopIcon.SetActive(isLooping);
}
}
private void UpdateStatusText(string text)
{
if (_statusText != null)
{
_statusText.text = text;
}
}
private void SetVisible(bool visible)
{
_canvasGroup.alpha = visible ? 1f : 0f;
}
}
}
#endif

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 7d029ac853dd64fdab15fa5c78ced267
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,338 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!1 &3143306149169442488
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 4495645932648773490}
- component: {fileID: 8257633976371616988}
- component: {fileID: 7305657527396605225}
m_Layer: 0
m_Name: StatusText
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!224 &4495645932648773490
RectTransform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 3143306149169442488}
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 1866048660558847936}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0, y: 0.5}
m_AnchorMax: {x: 1, y: 1}
m_AnchoredPosition: {x: 0, y: 0}
m_SizeDelta: {x: -20, y: 0}
m_Pivot: {x: 0.5, y: 0.5}
--- !u!222 &8257633976371616988
CanvasRenderer:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 3143306149169442488}
m_CullTransparentMesh: 1
--- !u!114 &7305657527396605225
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 3143306149169442488}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 5f7201a12d95ffc409449d95f23cf332, type: 3}
m_Name:
m_EditorClassIdentifier:
m_Material: {fileID: 0}
m_Color: {r: 0.3, g: 1, b: 0.5, a: 1}
m_RaycastTarget: 1
m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
m_Maskable: 1
m_OnCullStateChanged:
m_PersistentCalls:
m_Calls: []
m_FontData:
m_Font: {fileID: 10102, guid: 0000000000000000e000000000000000, type: 0}
m_FontSize: 24
m_FontStyle: 1
m_BestFit: 0
m_MinSize: 10
m_MaxSize: 42
m_Alignment: 4
m_AlignByGeometry: 0
m_RichText: 1
m_HorizontalOverflow: 0
m_VerticalOverflow: 0
m_LineSpacing: 1
m_Text: REPLAY 0 / 0
--- !u!1 &4291754732258876827
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 1866048660558847936}
- component: {fileID: 8861507738235532311}
- component: {fileID: 6556589926453698892}
- component: {fileID: 7623582385403064619}
- component: {fileID: 750881311793061267}
m_Layer: 0
m_Name: ReplayInputOverlay
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!224 &1866048660558847936
RectTransform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 4291754732258876827}
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children:
- {fileID: 4495645932648773490}
- {fileID: 8766924675270495938}
m_Father: {fileID: 0}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0.5, y: 0}
m_AnchorMax: {x: 0.5, y: 0}
m_AnchoredPosition: {x: 0, y: 10}
m_SizeDelta: {x: 300, y: 40}
m_Pivot: {x: 0.5, y: 0}
--- !u!225 &8861507738235532311
CanvasGroup:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 4291754732258876827}
m_Enabled: 1
m_Alpha: 1
m_Interactable: 0
m_BlocksRaycasts: 0
m_IgnoreParentGroups: 0
--- !u!222 &6556589926453698892
CanvasRenderer:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 4291754732258876827}
m_CullTransparentMesh: 1
--- !u!114 &7623582385403064619
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 4291754732258876827}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3}
m_Name:
m_EditorClassIdentifier:
m_Material: {fileID: 0}
m_Color: {r: 0, g: 0, b: 0, a: 0.6}
m_RaycastTarget: 1
m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
m_Maskable: 1
m_OnCullStateChanged:
m_PersistentCalls:
m_Calls: []
m_Sprite: {fileID: 0}
m_Type: 0
m_PreserveAspect: 0
m_FillCenter: 1
m_FillMethod: 4
m_FillAmount: 1
m_FillClockwise: 1
m_FillOrigin: 0
m_UseSpriteMesh: 0
m_PixelsPerUnitMultiplier: 1
--- !u!114 &750881311793061267
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 4291754732258876827}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 7d029ac853dd64fdab15fa5c78ced267, type: 3}
m_Name:
m_EditorClassIdentifier:
_statusText: {fileID: 7305657527396605225}
_progressBarFill: {fileID: 5900655728717313438}
_loopIcon: {fileID: 0}
--- !u!1 &5842103157894414940
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 8766924675270495938}
- component: {fileID: 5317892433336956793}
- component: {fileID: 699221967987577222}
m_Layer: 0
m_Name: ProgressBarBg
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!224 &8766924675270495938
RectTransform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 5842103157894414940}
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children:
- {fileID: 3633262302885763002}
m_Father: {fileID: 1866048660558847936}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0, y: 0}
m_AnchorMax: {x: 1, y: 0.4}
m_AnchoredPosition: {x: 0, y: 10}
m_SizeDelta: {x: -20, y: 3.9999}
m_Pivot: {x: 0.5, y: 0.5}
--- !u!222 &5317892433336956793
CanvasRenderer:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 5842103157894414940}
m_CullTransparentMesh: 1
--- !u!114 &699221967987577222
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 5842103157894414940}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3}
m_Name:
m_EditorClassIdentifier:
m_Material: {fileID: 0}
m_Color: {r: 0.2, g: 0.2, b: 0.2, a: 0.8}
m_RaycastTarget: 1
m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
m_Maskable: 1
m_OnCullStateChanged:
m_PersistentCalls:
m_Calls: []
m_Sprite: {fileID: 0}
m_Type: 0
m_PreserveAspect: 0
m_FillCenter: 1
m_FillMethod: 4
m_FillAmount: 1
m_FillClockwise: 1
m_FillOrigin: 0
m_UseSpriteMesh: 0
m_PixelsPerUnitMultiplier: 1
--- !u!1 &8320914726685114482
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 3633262302885763002}
- component: {fileID: 3929436855382297907}
- component: {fileID: 5900655728717313438}
m_Layer: 0
m_Name: ProgressBarFill
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!224 &3633262302885763002
RectTransform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 8320914726685114482}
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 8766924675270495938}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0, y: 0}
m_AnchorMax: {x: 1, y: 1}
m_AnchoredPosition: {x: 0, y: 0}
m_SizeDelta: {x: 0, y: 0}
m_Pivot: {x: 0, y: 0.5}
--- !u!222 &3929436855382297907
CanvasRenderer:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 8320914726685114482}
m_CullTransparentMesh: 1
--- !u!114 &5900655728717313438
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 8320914726685114482}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3}
m_Name:
m_EditorClassIdentifier:
m_Material: {fileID: 0}
m_Color: {r: 0.3, g: 1, b: 0.5, a: 0.9}
m_RaycastTarget: 1
m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
m_Maskable: 1
m_OnCullStateChanged:
m_PersistentCalls:
m_Calls: []
m_Sprite: {fileID: 0}
m_Type: 0
m_PreserveAspect: 0
m_FillCenter: 1
m_FillMethod: 0
m_FillAmount: 0
m_FillClockwise: 1
m_FillOrigin: 0
m_UseSpriteMesh: 0
m_PixelsPerUnitMultiplier: 1

View File

@@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: 6ddbcdb56af1c46719cf4fa1b302f1b4
PrefabImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,41 @@
#nullable enable
namespace io.github.hatayama.uLoopMCP
{
public static class ReplayInputOverlayState
{
private static bool _isActive;
private static int _currentFrame;
private static int _totalFrames;
private static bool _isLooping;
public static bool IsActive => _isActive;
public static int CurrentFrame => _currentFrame;
public static int TotalFrames => _totalFrames;
public static bool IsLooping => _isLooping;
public static float Progress
{
get
{
return _totalFrames > 0 ? (float)_currentFrame / _totalFrames : 0f;
}
}
public static void Update(int currentFrame, int totalFrames, bool isLooping)
{
_isActive = true;
_currentFrame = currentFrame;
_totalFrames = totalFrames;
_isLooping = isLooping;
}
public static void Clear()
{
_isActive = false;
_currentFrame = 0;
_totalFrames = 0;
_isLooping = false;
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: bfa984fc0e10b4e1ab8957a3a37d725a
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 9108cec3040b34078b0c5c96221baf9f
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,77 @@
#nullable enable
using System.Collections.Generic;
using UnityEngine;
namespace io.github.hatayama.uLoopMCP
{
public static class KeySymbolMap
{
private static readonly Dictionary<string, string> Symbols = new()
{
{ "Space", "\u2423" }, // ␣
{ "Enter", "\u23CE" }, // ⏎
{ "UpArrow", "\u2191" }, // ↑
{ "DownArrow", "\u2193" }, // ↓
{ "LeftArrow", "\u2190" }, // ←
{ "RightArrow", "\u2192" }, // →
{ "Tab", "\u21E5" }, // ⇥
{ "Escape", "Esc" },
{ "ContextMenu", "Menu" },
{ "PrintScreen", "PrtSc" },
{ "ScrollLock", "ScrLk" },
};
// Meta key maps to ⌘ on macOS, ⊞ on Windows/Linux
private static bool IsMac =>
Application.platform == RuntimePlatform.OSXEditor ||
Application.platform == RuntimePlatform.OSXPlayer;
public static string GetSymbol(string keyName)
{
// Key.LeftMeta.ToString() returns "LeftWindows" in Input System
if (keyName == "LeftMeta" || keyName == "RightMeta" ||
keyName == "LeftWindows" || keyName == "RightWindows")
{
return IsMac ? "\u2318" : "\u229E"; // ⌘ or ⊞
}
if (keyName == "LeftCtrl" || keyName == "RightCtrl")
{
return IsMac ? "\u2303" : "Ctrl"; // ⌃ or Ctrl
}
if (keyName == "LeftAlt" || keyName == "RightAlt")
{
return IsMac ? "\u2325" : "Alt"; // ⌥ or Alt
}
if (keyName == "LeftShift" || keyName == "RightShift")
{
return IsMac ? "\u21E7" : "Shift"; // ⇧ or Shift
}
if (keyName == "Backspace")
{
return IsMac ? "\u232B" : "BS"; // ⌫ or BS
}
if (keyName == "Delete")
{
return IsMac ? "\u2326" : "Del"; // ⌦ or Del
}
if (Symbols.TryGetValue(keyName, out string symbol))
{
return symbol;
}
return keyName;
}
// Single non-ASCII characters render smaller than text in most fonts
public static bool IsGlyphSymbol(string symbol)
{
return symbol.Length == 1 && symbol[0] > 127;
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 3f8551e9ac39140f2a1eb0e3ce81ec15
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,9 @@
namespace io.github.hatayama.uLoopMCP
{
public enum KeyboardAction
{
Press = 0,
KeyDown = 1,
KeyUp = 2
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 95c39d99bda824fd2b7aedf25ddcd2b1
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,140 @@
fileFormatVersion: 2
guid: 8de76314d55f142d687ee8b477288bae
TextureImporter:
internalIDToNameTable: []
externalObjects: {}
serializedVersion: 13
mipmaps:
mipMapMode: 0
enableMipMap: 0
sRGBTexture: 1
linearTexture: 0
fadeOut: 0
borderMipMap: 0
mipMapsPreserveCoverage: 0
alphaTestReferenceValue: 0.5
mipMapFadeDistanceStart: 1
mipMapFadeDistanceEnd: 3
bumpmap:
convertToNormalMap: 0
externalNormalMap: 0
heightScale: 0.25
normalMapFilter: 0
flipGreenChannel: 0
isReadable: 0
streamingMipmaps: 0
streamingMipmapsPriority: 0
vTOnly: 0
ignoreMipmapLimit: 0
grayScaleToAlpha: 0
generateCubemap: 6
cubemapConvolution: 0
seamlessCubemap: 0
textureFormat: 1
maxTextureSize: 2048
textureSettings:
serializedVersion: 2
filterMode: 1
aniso: 1
mipBias: 0
wrapU: 1
wrapV: 1
wrapW: 1
nPOTScale: 0
lightmap: 0
compressionQuality: 50
spriteMode: 1
spriteExtrude: 1
spriteMeshType: 1
alignment: 0
spritePivot: {x: 0.5, y: 0.5}
spritePixelsToUnits: 100
spriteBorder: {x: 16, y: 16, z: 16, w: 16}
spriteGenerateFallbackPhysicsShape: 1
alphaUsage: 1
alphaIsTransparency: 1
spriteTessellationDetail: -1
textureType: 8
textureShape: 1
singleChannelComponent: 0
flipbookRows: 1
flipbookColumns: 1
maxTextureSizeSet: 0
compressionQualitySet: 0
textureFormatSet: 0
ignorePngGamma: 0
applyGammaDecoding: 0
swizzle: 50462976
cookieLightType: 0
platformSettings:
- serializedVersion: 3
buildTarget: DefaultTexturePlatform
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 0
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
- serializedVersion: 3
buildTarget: Standalone
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
- serializedVersion: 3
buildTarget: iPhone
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
- serializedVersion: 3
buildTarget: Android
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
spriteSheet:
serializedVersion: 2
sprites: []
outline: []
physicsShape: []
bones: []
spriteID: 5e97eb03825dee720800000000000000
internalID: 0
vertices: []
indices:
edges: []
weights: []
secondaryTextures: []
nameFileIdTable: {}
mipmapLimitGroupName:
pSDRemoveMatte: 0
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,204 @@
#if UNITY_EDITOR
#nullable enable
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
namespace io.github.hatayama.uLoopMCP
{
public class SimulateKeyboardOverlay : MonoBehaviour
{
public const float CONTAINER_BACKGROUND_ALPHA = 0.8f;
private const float PRESS_DISPLAY_DURATION = 0.5f;
private const float FADE_DURATION = 0.2f;
private const int FONT_SIZE = 48;
private const int GLYPH_FONT_SIZE = 64;
private static readonly Color ContainerBackgroundColor = new Color(0.15f, 0.15f, 0.15f, CONTAINER_BACKGROUND_ALPHA);
[SerializeField] private GameObject _container = null!;
[SerializeField] private Image _containerImage = null!;
private readonly List<BadgeEntry> _badgePool = new();
private readonly List<string> _cachedKeyNames = new();
private readonly List<string> _displayKeys = new();
private void Awake()
{
Debug.Assert(_container != null, "_container must be assigned in prefab");
Debug.Assert(_containerImage != null, "_containerImage must be assigned in prefab");
// Prefab keeps preview badges for editor inspection, but runtime badges must start empty.
for (int i = _container!.transform.childCount - 1; i >= 0; i--)
{
DestroyImmediate(_container.transform.GetChild(i).gameObject);
}
_container.SetActive(false);
}
private void LateUpdate()
{
bool hasHeldKeys = SimulateKeyboardOverlayState.HeldKeys.Count > 0;
string? pressKey = SimulateKeyboardOverlayState.PressKey;
bool isPressHeld = SimulateKeyboardOverlayState.IsPressHeld;
float pressElapsedSinceRelease = 0f;
if (pressKey != null && !isPressHeld)
{
pressElapsedSinceRelease = Time.realtimeSinceStartup - SimulateKeyboardOverlayState.PressReleasedTime;
if (pressElapsedSinceRelease > PRESS_DISPLAY_DURATION + FADE_DURATION)
{
SimulateKeyboardOverlayState.ClearPress();
pressKey = null;
}
}
if (!hasHeldKeys && pressKey == null)
{
SetBadgeCount(0);
_container.SetActive(false);
return;
}
_displayKeys.Clear();
IReadOnlyList<string> heldKeys = SimulateKeyboardOverlayState.HeldKeys;
for (int i = 0; i < heldKeys.Count; i++)
{
_displayKeys.Add(heldKeys[i]);
}
if (pressKey != null && !_displayKeys.Contains(pressKey))
{
_displayKeys.Add(pressKey);
}
SetBadgeCount(_displayKeys.Count);
_container.SetActive(true);
float maxAlpha = 0f;
for (int i = 0; i < _displayKeys.Count; i++)
{
float alpha = GetBadgeAlpha(_displayKeys[i], pressKey, isPressHeld, pressElapsedSinceRelease);
UpdateBadge(_badgePool[i], i, _displayKeys[i], alpha);
if (alpha > maxAlpha)
{
maxAlpha = alpha;
}
}
_containerImage.color = new Color(
ContainerBackgroundColor.r,
ContainerBackgroundColor.g,
ContainerBackgroundColor.b,
ContainerBackgroundColor.a * maxAlpha);
}
private void SetBadgeCount(int count)
{
while (_badgePool.Count < count)
{
_badgePool.Add(CreateBadge());
_cachedKeyNames.Add("");
}
for (int i = 0; i < _badgePool.Count; i++)
{
_badgePool[i].Root.SetActive(i < count);
}
}
private BadgeEntry CreateBadge()
{
GameObject badge = new GameObject("KeyBadge");
badge.transform.SetParent(_container.transform, false);
badge.AddComponent<RectTransform>();
Image bg = badge.AddComponent<Image>();
bg.color = new Color(0f, 0f, 0f, 0f);
bg.raycastTarget = false;
LayoutElement layoutElement = badge.AddComponent<LayoutElement>();
GameObject textGo = new GameObject("KeyText");
textGo.transform.SetParent(badge.transform, false);
RectTransform textRect = textGo.AddComponent<RectTransform>();
textRect.anchorMin = Vector2.zero;
textRect.anchorMax = Vector2.one;
textRect.offsetMin = Vector2.zero;
textRect.offsetMax = Vector2.zero;
Text text = textGo.AddComponent<Text>();
text.font = Resources.GetBuiltinResource<Font>("LegacyRuntime.ttf");
text.fontSize = FONT_SIZE;
text.fontStyle = FontStyle.Bold;
text.color = Color.white;
text.alignment = TextAnchor.MiddleCenter;
text.horizontalOverflow = HorizontalWrapMode.Overflow;
text.raycastTarget = false;
// Thicken glyph strokes so Unicode symbols don't look too thin
Outline outline = textGo.AddComponent<Outline>();
outline.effectColor = Color.white;
outline.effectDistance = new Vector2(1f, -1f);
return new BadgeEntry(badge, bg, text, layoutElement);
}
private void UpdateBadge(BadgeEntry badge, int index, string keyName, float alpha)
{
badge.Text.color = new Color(1f, 1f, 1f, alpha);
if (_cachedKeyNames[index] == keyName)
{
return;
}
_cachedKeyNames[index] = keyName;
string symbol = KeySymbolMap.GetSymbol(keyName);
badge.Text.text = symbol;
badge.Text.fontSize = KeySymbolMap.IsGlyphSymbol(symbol) ? GLYPH_FONT_SIZE : FONT_SIZE;
TextGenerationSettings settings = badge.Text.GetGenerationSettings(new Vector2(float.MaxValue, float.MaxValue));
float preferredWidth = badge.Text.cachedTextGeneratorForLayout.GetPreferredWidth(symbol, settings);
float preferredHeight = badge.Text.cachedTextGeneratorForLayout.GetPreferredHeight(symbol, settings);
badge.Layout.preferredWidth = Mathf.Max(preferredWidth / badge.Text.pixelsPerUnit, preferredHeight / badge.Text.pixelsPerUnit);
badge.Layout.preferredHeight = preferredHeight / badge.Text.pixelsPerUnit;
}
private static float GetBadgeAlpha(
string keyName,
string? pressKey,
bool isPressHeld,
float pressElapsedSinceRelease)
{
if (pressKey == null || keyName != pressKey || isPressHeld || pressElapsedSinceRelease <= PRESS_DISPLAY_DURATION)
{
return 1f;
}
float fadeT = Mathf.Clamp01((pressElapsedSinceRelease - PRESS_DISPLAY_DURATION) / FADE_DURATION);
return 1f - fadeT;
}
private readonly struct BadgeEntry
{
public readonly GameObject Root;
public readonly Image Background;
public readonly Text Text;
public readonly LayoutElement Layout;
public BadgeEntry(GameObject root, Image background, Text text, LayoutElement layout)
{
Root = root;
Background = background;
Text = text;
Layout = layout;
}
}
}
}
#endif

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 22d59970393a54b4cb41f956e0eb3f41
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,376 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!1 &1163102534174049270
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 5371017374443542522}
- component: {fileID: 8025827109147581330}
- component: {fileID: 3026865949128803190}
- component: {fileID: 6066404719234391660}
m_Layer: 0
m_Name: PreviewBadge
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!224 &5371017374443542522
RectTransform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1163102534174049270}
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children:
- {fileID: 5808527078553167771}
m_Father: {fileID: 8394911915651975566}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0, y: 0}
m_AnchorMax: {x: 0, y: 0}
m_AnchoredPosition: {x: 0, y: 0}
m_SizeDelta: {x: 100, y: 100}
m_Pivot: {x: 0.5, y: 0.5}
--- !u!222 &8025827109147581330
CanvasRenderer:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1163102534174049270}
m_CullTransparentMesh: 1
--- !u!114 &3026865949128803190
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1163102534174049270}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3}
m_Name:
m_EditorClassIdentifier:
m_Material: {fileID: 0}
m_Color: {r: 0, g: 0, b: 0, a: 0}
m_RaycastTarget: 0
m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
m_Maskable: 1
m_OnCullStateChanged:
m_PersistentCalls:
m_Calls: []
m_Sprite: {fileID: 0}
m_Type: 0
m_PreserveAspect: 0
m_FillCenter: 1
m_FillMethod: 4
m_FillAmount: 1
m_FillClockwise: 1
m_FillOrigin: 0
m_UseSpriteMesh: 0
m_PixelsPerUnitMultiplier: 1
--- !u!114 &6066404719234391660
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1163102534174049270}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 306cc8c2b49d7114eaa3623786fc2126, type: 3}
m_Name:
m_EditorClassIdentifier:
m_IgnoreLayout: 0
m_MinWidth: -1
m_MinHeight: -1
m_PreferredWidth: 60
m_PreferredHeight: 80
m_FlexibleWidth: -1
m_FlexibleHeight: -1
m_LayoutPriority: 1
--- !u!1 &3492586335444099666
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 8394911915651975566}
- component: {fileID: 5543483528529774299}
- component: {fileID: 8787032785713595466}
- component: {fileID: 8195843448948172035}
- component: {fileID: 8555974250771983990}
m_Layer: 0
m_Name: Container
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!224 &8394911915651975566
RectTransform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 3492586335444099666}
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children:
- {fileID: 5371017374443542522}
m_Father: {fileID: 1447186769560363053}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0.5, y: 0}
m_AnchorMax: {x: 0.5, y: 0}
m_AnchoredPosition: {x: 0, y: 100}
m_SizeDelta: {x: 0, y: 0}
m_Pivot: {x: 0.5, y: 0}
--- !u!222 &5543483528529774299
CanvasRenderer:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 3492586335444099666}
m_CullTransparentMesh: 1
--- !u!114 &8787032785713595466
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 3492586335444099666}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3}
m_Name:
m_EditorClassIdentifier:
m_Material: {fileID: 0}
m_Color: {r: 0.15, g: 0.15, b: 0.15, a: 0.8}
m_RaycastTarget: 0
m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
m_Maskable: 1
m_OnCullStateChanged:
m_PersistentCalls:
m_Calls: []
m_Sprite: {fileID: 21300000, guid: 8de76314d55f142d687ee8b477288bae, type: 3}
m_Type: 1
m_PreserveAspect: 0
m_FillCenter: 1
m_FillMethod: 4
m_FillAmount: 1
m_FillClockwise: 1
m_FillOrigin: 0
m_UseSpriteMesh: 0
m_PixelsPerUnitMultiplier: 1
--- !u!114 &8195843448948172035
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 3492586335444099666}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 30649d3a9faa99c48a7b1166b86bf2a0, type: 3}
m_Name:
m_EditorClassIdentifier:
m_Padding:
m_Left: 24
m_Right: 24
m_Top: 16
m_Bottom: 16
m_ChildAlignment: 4
m_Spacing: 8
m_ChildForceExpandWidth: 0
m_ChildForceExpandHeight: 0
m_ChildControlWidth: 0
m_ChildControlHeight: 0
m_ChildScaleWidth: 0
m_ChildScaleHeight: 0
m_ReverseArrangement: 0
--- !u!114 &8555974250771983990
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 3492586335444099666}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 3245ec927659c4140ac4f8d17403cc18, type: 3}
m_Name:
m_EditorClassIdentifier:
m_HorizontalFit: 2
m_VerticalFit: 2
--- !u!1 &6281231881990964606
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 5808527078553167771}
- component: {fileID: 7861529244481486362}
- component: {fileID: 2900878144175824161}
- component: {fileID: 6622544667456466176}
m_Layer: 0
m_Name: KeyText
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!224 &5808527078553167771
RectTransform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 6281231881990964606}
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 5371017374443542522}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0, y: 0}
m_AnchorMax: {x: 1, y: 1}
m_AnchoredPosition: {x: 0, y: 0}
m_SizeDelta: {x: 0, y: 0}
m_Pivot: {x: 0.5, y: 0.5}
--- !u!222 &7861529244481486362
CanvasRenderer:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 6281231881990964606}
m_CullTransparentMesh: 1
--- !u!114 &2900878144175824161
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 6281231881990964606}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 5f7201a12d95ffc409449d95f23cf332, type: 3}
m_Name:
m_EditorClassIdentifier:
m_Material: {fileID: 0}
m_Color: {r: 1, g: 1, b: 1, a: 1}
m_RaycastTarget: 0
m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
m_Maskable: 1
m_OnCullStateChanged:
m_PersistentCalls:
m_Calls: []
m_FontData:
m_Font: {fileID: 10102, guid: 0000000000000000e000000000000000, type: 0}
m_FontSize: 48
m_FontStyle: 1
m_BestFit: 0
m_MinSize: 10
m_MaxSize: 48
m_Alignment: 4
m_AlignByGeometry: 0
m_RichText: 1
m_HorizontalOverflow: 1
m_VerticalOverflow: 0
m_LineSpacing: 1
m_Text: "\u2318"
--- !u!114 &6622544667456466176
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 6281231881990964606}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: e19747de3f5aca642ab2be37e372fb86, type: 3}
m_Name:
m_EditorClassIdentifier:
m_EffectColor: {r: 1, g: 1, b: 1, a: 1}
m_EffectDistance: {x: 1, y: -1}
m_UseGraphicAlpha: 1
--- !u!1 &9003946234088771061
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 1447186769560363053}
- component: {fileID: 6082752830946661477}
- component: {fileID: 7943424075059165438}
m_Layer: 0
m_Name: SimulateKeyboardOverlay
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!224 &1447186769560363053
RectTransform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 9003946234088771061}
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 1
m_Children:
- {fileID: 8394911915651975566}
m_Father: {fileID: 0}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0, y: 0}
m_AnchorMax: {x: 1, y: 1}
m_AnchoredPosition: {x: 0, y: 0}
m_SizeDelta: {x: 0, y: 0}
m_Pivot: {x: 0.5, y: 0.5}
--- !u!114 &6082752830946661477
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 9003946234088771061}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 22d59970393a54b4cb41f956e0eb3f41, type: 3}
m_Name:
m_EditorClassIdentifier:
_container: {fileID: 3492586335444099666}
_containerImage: {fileID: 8787032785713595466}
--- !u!225 &7943424075059165438
CanvasGroup:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 9003946234088771061}
m_Enabled: 1
m_Alpha: 1
m_Interactable: 0
m_BlocksRaycasts: 0
m_IgnoreParentGroups: 0

View File

@@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: 13a5dea128bba49df91807161c323487
PrefabImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,61 @@
#nullable enable
using System.Collections.Generic;
namespace io.github.hatayama.uLoopMCP
{
public static class SimulateKeyboardOverlayState
{
private static readonly List<string> _heldKeys = new();
private static string? _pressKey;
private static float _pressReleasedTime = -1f;
public static bool IsActive => _heldKeys.Count > 0 || _pressKey != null;
public static IReadOnlyList<string> HeldKeys => _heldKeys;
public static string? PressKey => _pressKey;
public static bool IsPressHeld => _pressKey != null && _pressReleasedTime < 0f;
public static float PressReleasedTime => _pressReleasedTime;
public static void AddHeldKey(string keyName)
{
if (!_heldKeys.Contains(keyName))
{
_heldKeys.Add(keyName);
}
}
public static void RemoveHeldKey(string keyName)
{
_heldKeys.Remove(keyName);
}
public static void ShowPress(string keyName)
{
_pressKey = keyName;
_pressReleasedTime = -1f;
}
public static void ReleasePress()
{
UnityEngine.Debug.Assert(_pressKey != null, "Press key must exist before it can be released.");
if (_pressKey == null)
{
return;
}
_pressReleasedTime = UnityEngine.Time.realtimeSinceStartup;
}
public static void ClearPress()
{
_pressKey = null;
_pressReleasedTime = -1f;
}
public static void Clear()
{
_heldKeys.Clear();
_pressKey = null;
_pressReleasedTime = -1f;
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 2d9f7c86425414af7aa5e2d0b0fd1a1b
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 1b1be043c192c47d9a9a486e520ae319
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,140 @@
fileFormatVersion: 2
guid: 274dddb42396c4c93bc9d0f4686e357e
TextureImporter:
internalIDToNameTable: []
externalObjects: {}
serializedVersion: 13
mipmaps:
mipMapMode: 0
enableMipMap: 0
sRGBTexture: 1
linearTexture: 0
fadeOut: 0
borderMipMap: 0
mipMapsPreserveCoverage: 0
alphaTestReferenceValue: 0.5
mipMapFadeDistanceStart: 1
mipMapFadeDistanceEnd: 3
bumpmap:
convertToNormalMap: 0
externalNormalMap: 0
heightScale: 0.25
normalMapFilter: 0
flipGreenChannel: 0
isReadable: 0
streamingMipmaps: 0
streamingMipmapsPriority: 0
vTOnly: 0
ignoreMipmapLimit: 0
grayScaleToAlpha: 0
generateCubemap: 6
cubemapConvolution: 0
seamlessCubemap: 0
textureFormat: 1
maxTextureSize: 2048
textureSettings:
serializedVersion: 2
filterMode: 1
aniso: 1
mipBias: 0
wrapU: 1
wrapV: 1
wrapW: 1
nPOTScale: 0
lightmap: 0
compressionQuality: 50
spriteMode: 1
spriteExtrude: 1
spriteMeshType: 1
alignment: 0
spritePivot: {x: 0.5, y: 0.5}
spritePixelsToUnits: 100
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
spriteGenerateFallbackPhysicsShape: 1
alphaUsage: 1
alphaIsTransparency: 1
spriteTessellationDetail: -1
textureType: 8
textureShape: 1
singleChannelComponent: 0
flipbookRows: 1
flipbookColumns: 1
maxTextureSizeSet: 0
compressionQualitySet: 0
textureFormatSet: 0
ignorePngGamma: 0
applyGammaDecoding: 0
swizzle: 50462976
cookieLightType: 0
platformSettings:
- serializedVersion: 3
buildTarget: DefaultTexturePlatform
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
- serializedVersion: 3
buildTarget: Standalone
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
- serializedVersion: 3
buildTarget: iPhone
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
- serializedVersion: 3
buildTarget: Android
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
spriteSheet:
serializedVersion: 2
sprites: []
outline: []
physicsShape: []
bones: []
spriteID: 5e97eb03825dee720800000000000000
internalID: 0
vertices: []
indices:
edges: []
weights: []
secondaryTextures: []
nameFileIdTable: {}
mipmapLimitGroupName:
pSDRemoveMatte: 0
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,140 @@
fileFormatVersion: 2
guid: 696769fce8dcf4cbf9e8e41c55e11260
TextureImporter:
internalIDToNameTable: []
externalObjects: {}
serializedVersion: 13
mipmaps:
mipMapMode: 0
enableMipMap: 0
sRGBTexture: 1
linearTexture: 0
fadeOut: 0
borderMipMap: 0
mipMapsPreserveCoverage: 0
alphaTestReferenceValue: 0.5
mipMapFadeDistanceStart: 1
mipMapFadeDistanceEnd: 3
bumpmap:
convertToNormalMap: 0
externalNormalMap: 0
heightScale: 0.25
normalMapFilter: 0
flipGreenChannel: 0
isReadable: 0
streamingMipmaps: 0
streamingMipmapsPriority: 0
vTOnly: 0
ignoreMipmapLimit: 0
grayScaleToAlpha: 0
generateCubemap: 6
cubemapConvolution: 0
seamlessCubemap: 0
textureFormat: 1
maxTextureSize: 2048
textureSettings:
serializedVersion: 2
filterMode: 1
aniso: 1
mipBias: 0
wrapU: 1
wrapV: 1
wrapW: 1
nPOTScale: 0
lightmap: 0
compressionQuality: 50
spriteMode: 1
spriteExtrude: 1
spriteMeshType: 1
alignment: 0
spritePivot: {x: 0.5, y: 0.5}
spritePixelsToUnits: 100
spriteBorder: {x: 32, y: 32, z: 32, w: 32}
spriteGenerateFallbackPhysicsShape: 1
alphaUsage: 1
alphaIsTransparency: 1
spriteTessellationDetail: -1
textureType: 8
textureShape: 1
singleChannelComponent: 0
flipbookRows: 1
flipbookColumns: 1
maxTextureSizeSet: 0
compressionQualitySet: 0
textureFormatSet: 0
ignorePngGamma: 0
applyGammaDecoding: 0
swizzle: 50462976
cookieLightType: 0
platformSettings:
- serializedVersion: 3
buildTarget: DefaultTexturePlatform
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
- serializedVersion: 3
buildTarget: Standalone
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
- serializedVersion: 3
buildTarget: iPhone
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
- serializedVersion: 3
buildTarget: Android
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
spriteSheet:
serializedVersion: 2
sprites: []
outline: []
physicsShape: []
bones: []
spriteID: 5e97eb03825dee720800000000000000
internalID: 0
vertices: []
indices:
edges: []
weights: []
secondaryTextures: []
nameFileIdTable: {}
mipmapLimitGroupName:
pSDRemoveMatte: 0
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,140 @@
fileFormatVersion: 2
guid: e2f0935a9b378436ea49e5e300e9d6c9
TextureImporter:
internalIDToNameTable: []
externalObjects: {}
serializedVersion: 13
mipmaps:
mipMapMode: 0
enableMipMap: 0
sRGBTexture: 1
linearTexture: 0
fadeOut: 0
borderMipMap: 0
mipMapsPreserveCoverage: 0
alphaTestReferenceValue: 0.5
mipMapFadeDistanceStart: 1
mipMapFadeDistanceEnd: 3
bumpmap:
convertToNormalMap: 0
externalNormalMap: 0
heightScale: 0.25
normalMapFilter: 0
flipGreenChannel: 0
isReadable: 0
streamingMipmaps: 0
streamingMipmapsPriority: 0
vTOnly: 0
ignoreMipmapLimit: 0
grayScaleToAlpha: 0
generateCubemap: 6
cubemapConvolution: 0
seamlessCubemap: 0
textureFormat: 1
maxTextureSize: 2048
textureSettings:
serializedVersion: 2
filterMode: 1
aniso: 1
mipBias: 0
wrapU: 1
wrapV: 1
wrapW: 1
nPOTScale: 0
lightmap: 0
compressionQuality: 50
spriteMode: 1
spriteExtrude: 1
spriteMeshType: 1
alignment: 0
spritePivot: {x: 0.5, y: 0.5}
spritePixelsToUnits: 100
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
spriteGenerateFallbackPhysicsShape: 1
alphaUsage: 1
alphaIsTransparency: 1
spriteTessellationDetail: -1
textureType: 8
textureShape: 1
singleChannelComponent: 0
flipbookRows: 1
flipbookColumns: 1
maxTextureSizeSet: 0
compressionQualitySet: 0
textureFormatSet: 0
ignorePngGamma: 0
applyGammaDecoding: 0
swizzle: 50462976
cookieLightType: 0
platformSettings:
- serializedVersion: 3
buildTarget: DefaultTexturePlatform
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
- serializedVersion: 3
buildTarget: Standalone
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
- serializedVersion: 3
buildTarget: iPhone
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
- serializedVersion: 3
buildTarget: Android
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
spriteSheet:
serializedVersion: 2
sprites: []
outline: []
physicsShape: []
bones: []
spriteID: 5e97eb03825dee720800000000000000
internalID: 0
vertices: []
indices:
edges: []
weights: []
secondaryTextures: []
nameFileIdTable: {}
mipmapLimitGroupName:
pSDRemoveMatte: 0
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,140 @@
fileFormatVersion: 2
guid: fc225262ec91644d08393ad2dedc73f2
TextureImporter:
internalIDToNameTable: []
externalObjects: {}
serializedVersion: 13
mipmaps:
mipMapMode: 0
enableMipMap: 0
sRGBTexture: 1
linearTexture: 0
fadeOut: 0
borderMipMap: 0
mipMapsPreserveCoverage: 0
alphaTestReferenceValue: 0.5
mipMapFadeDistanceStart: 1
mipMapFadeDistanceEnd: 3
bumpmap:
convertToNormalMap: 0
externalNormalMap: 0
heightScale: 0.25
normalMapFilter: 0
flipGreenChannel: 0
isReadable: 0
streamingMipmaps: 0
streamingMipmapsPriority: 0
vTOnly: 0
ignoreMipmapLimit: 0
grayScaleToAlpha: 0
generateCubemap: 6
cubemapConvolution: 0
seamlessCubemap: 0
textureFormat: 1
maxTextureSize: 2048
textureSettings:
serializedVersion: 2
filterMode: 1
aniso: 1
mipBias: 0
wrapU: 1
wrapV: 1
wrapW: 1
nPOTScale: 0
lightmap: 0
compressionQuality: 50
spriteMode: 1
spriteExtrude: 1
spriteMeshType: 1
alignment: 0
spritePivot: {x: 0.5, y: 0.5}
spritePixelsToUnits: 100
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
spriteGenerateFallbackPhysicsShape: 1
alphaUsage: 1
alphaIsTransparency: 1
spriteTessellationDetail: -1
textureType: 8
textureShape: 1
singleChannelComponent: 0
flipbookRows: 1
flipbookColumns: 1
maxTextureSizeSet: 0
compressionQualitySet: 0
textureFormatSet: 0
ignorePngGamma: 0
applyGammaDecoding: 0
swizzle: 50462976
cookieLightType: 0
platformSettings:
- serializedVersion: 3
buildTarget: DefaultTexturePlatform
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
- serializedVersion: 3
buildTarget: Standalone
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
- serializedVersion: 3
buildTarget: iPhone
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
- serializedVersion: 3
buildTarget: Android
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
spriteSheet:
serializedVersion: 2
sprites: []
outline: []
physicsShape: []
bones: []
spriteID: 5e97eb03825dee720800000000000000
internalID: 0
vertices: []
indices:
edges: []
weights: []
secondaryTextures: []
nameFileIdTable: {}
mipmapLimitGroupName:
pSDRemoveMatte: 0
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,11 @@
namespace io.github.hatayama.uLoopMCP
{
public enum MouseInputAction
{
Click = 0,
LongPress = 1,
MoveDelta = 2,
Scroll = 3,
SmoothDelta = 4
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: b937253237423470081656d0ae7b0917
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,140 @@
fileFormatVersion: 2
guid: fa770edf1801941279ad40d3958b3f3f
TextureImporter:
internalIDToNameTable: []
externalObjects: {}
serializedVersion: 13
mipmaps:
mipMapMode: 0
enableMipMap: 0
sRGBTexture: 1
linearTexture: 0
fadeOut: 0
borderMipMap: 0
mipMapsPreserveCoverage: 0
alphaTestReferenceValue: 0.5
mipMapFadeDistanceStart: 1
mipMapFadeDistanceEnd: 3
bumpmap:
convertToNormalMap: 0
externalNormalMap: 0
heightScale: 0.25
normalMapFilter: 0
flipGreenChannel: 0
isReadable: 0
streamingMipmaps: 0
streamingMipmapsPriority: 0
vTOnly: 0
ignoreMipmapLimit: 0
grayScaleToAlpha: 0
generateCubemap: 6
cubemapConvolution: 0
seamlessCubemap: 0
textureFormat: 1
maxTextureSize: 2048
textureSettings:
serializedVersion: 2
filterMode: 1
aniso: 1
mipBias: 0
wrapU: 1
wrapV: 1
wrapW: 1
nPOTScale: 0
lightmap: 0
compressionQuality: 50
spriteMode: 1
spriteExtrude: 1
spriteMeshType: 1
alignment: 0
spritePivot: {x: 0.5, y: 0.5}
spritePixelsToUnits: 100
spriteBorder: {x: 8, y: 8, z: 8, w: 8}
spriteGenerateFallbackPhysicsShape: 1
alphaUsage: 1
alphaIsTransparency: 1
spriteTessellationDetail: -1
textureType: 8
textureShape: 1
singleChannelComponent: 0
flipbookRows: 1
flipbookColumns: 1
maxTextureSizeSet: 0
compressionQualitySet: 0
textureFormatSet: 0
ignorePngGamma: 0
applyGammaDecoding: 0
swizzle: 50462976
cookieLightType: 0
platformSettings:
- serializedVersion: 3
buildTarget: DefaultTexturePlatform
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
- serializedVersion: 3
buildTarget: Standalone
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
- serializedVersion: 3
buildTarget: iPhone
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
- serializedVersion: 3
buildTarget: Android
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
spriteSheet:
serializedVersion: 2
sprites: []
outline: []
physicsShape: []
bones: []
spriteID: 5e97eb03825dee720800000000000000
internalID: 0
vertices: []
indices:
edges: []
weights: []
secondaryTextures: []
nameFileIdTable: {}
mipmapLimitGroupName:
pSDRemoveMatte: 0
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,149 @@
#if UNITY_EDITOR
#nullable enable
using UnityEngine;
using UnityEngine.UI;
namespace io.github.hatayama.uLoopMCP
{
// Overlay that renders a mouse device icon on Game View and highlights
// pressed buttons / scroll direction during simulate-mouse-input tool calls.
public class SimulateMouseInputOverlay : MonoBehaviour
{
private const float DISPLAY_DURATION = 1.0f;
private static readonly Color BUTTON_PRESSED_COLOR = new Color(1f, 1f, 1f, 0.95f);
[SerializeField] private Image? _leftButton;
[SerializeField] private Image? _rightButton;
[SerializeField] private Image? _scrollWheel;
[SerializeField] private Image? _scrollArrowTop;
[SerializeField] private Image? _scrollArrowBottom;
[SerializeField] private RectTransform? _moveDirectionGroup;
private CanvasGroup _canvasGroup = null!;
private bool _isVisible;
private Color _leftButtonIdleColor;
private Color _rightButtonIdleColor;
private Color _scrollWheelIdleColor;
private void Awake()
{
_canvasGroup = GetComponent<CanvasGroup>();
if (_canvasGroup == null)
{
_canvasGroup = gameObject.AddComponent<CanvasGroup>();
}
_canvasGroup.interactable = false;
_canvasGroup.blocksRaycasts = false;
SetVisible(false);
CaptureIdleColors();
}
private void LateUpdate()
{
if (SimulateMouseInputOverlayState.HasAnyActivity)
{
if (!_isVisible)
{
SetVisible(true);
}
UpdateButtonColors();
UpdateScrollIndicator();
UpdateMoveDirection();
return;
}
float elapsed = Time.realtimeSinceStartup - SimulateMouseInputOverlayState.LastActivityTime;
if (SimulateMouseInputOverlayState.LastActivityTime <= 0f || elapsed > DISPLAY_DURATION)
{
if (_isVisible)
{
SetVisible(false);
}
return;
}
UpdateButtonColors();
UpdateScrollIndicator();
UpdateMoveDirection();
}
private void SetVisible(bool visible)
{
_isVisible = visible;
_canvasGroup.alpha = visible ? 1f : 0f;
}
private void CaptureIdleColors()
{
Debug.Assert(_leftButton != null, "_leftButton must be assigned before CaptureIdleColors");
Debug.Assert(_rightButton != null, "_rightButton must be assigned before CaptureIdleColors");
Debug.Assert(_scrollWheel != null, "_scrollWheel must be assigned before CaptureIdleColors");
_leftButtonIdleColor = _leftButton!.color;
_rightButtonIdleColor = _rightButton!.color;
_scrollWheelIdleColor = _scrollWheel!.color;
}
private void UpdateButtonColors()
{
_leftButton!.color = SimulateMouseInputOverlayState.IsLeftButtonHeld
? BUTTON_PRESSED_COLOR
: _leftButtonIdleColor;
_rightButton!.color = SimulateMouseInputOverlayState.IsRightButtonHeld
? BUTTON_PRESSED_COLOR
: _rightButtonIdleColor;
bool wheelActive = SimulateMouseInputOverlayState.IsMiddleButtonHeld
|| SimulateMouseInputOverlayState.ScrollDirection != 0;
_scrollWheel!.color = wheelActive ? BUTTON_PRESSED_COLOR : _scrollWheelIdleColor;
}
private void UpdateScrollIndicator()
{
int dir = SimulateMouseInputOverlayState.ScrollDirection;
if (dir == 0)
{
_scrollArrowTop!.enabled = false;
_scrollArrowBottom!.enabled = false;
return;
}
_scrollArrowTop!.enabled = true;
_scrollArrowBottom!.enabled = true;
float rotation = dir > 0 ? 0f : 180f;
_scrollArrowTop.rectTransform.localRotation = Quaternion.Euler(0f, 0f, rotation);
_scrollArrowBottom.rectTransform.localRotation = Quaternion.Euler(0f, 0f, rotation);
}
private void UpdateMoveDirection()
{
if (_moveDirectionGroup == null)
{
return;
}
Vector2 delta = SimulateMouseInputOverlayState.MoveDelta;
if (delta == Vector2.zero)
{
_moveDirectionGroup.gameObject.SetActive(false);
return;
}
_moveDirectionGroup.gameObject.SetActive(true);
float angle = Mathf.Atan2(delta.y, delta.x) * Mathf.Rad2Deg;
_moveDirectionGroup.localRotation = Quaternion.Euler(0f, 0f, angle);
}
}
}
#endif

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: c6cfdc16dff1f4baa8199a1a405f3415
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,928 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!1 &253023116830826680
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 6211819109502077103}
- component: {fileID: 1339135654949297666}
- component: {fileID: 833440402481600460}
m_Layer: 0
m_Name: ScrollWheel
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!224 &6211819109502077103
RectTransform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 253023116830826680}
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 3407559167762903945}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0.5, y: 0.775}
m_AnchorMax: {x: 0.5, y: 0.775}
m_AnchoredPosition: {x: 0, y: 0}
m_SizeDelta: {x: 26, y: 50}
m_Pivot: {x: 0.5, y: 0.5}
--- !u!222 &1339135654949297666
CanvasRenderer:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 253023116830826680}
m_CullTransparentMesh: 1
--- !u!114 &833440402481600460
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 253023116830826680}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3}
m_Name:
m_EditorClassIdentifier:
m_Material: {fileID: 0}
m_Color: {r: 0.35, g: 0.35, b: 0.35, a: 0.85}
m_RaycastTarget: 0
m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
m_Maskable: 1
m_OnCullStateChanged:
m_PersistentCalls:
m_Calls: []
m_Sprite: {fileID: 21300000, guid: fa770edf1801941279ad40d3958b3f3f, type: 3}
m_Type: 1
m_PreserveAspect: 0
m_FillCenter: 1
m_FillMethod: 4
m_FillAmount: 1
m_FillClockwise: 1
m_FillOrigin: 0
m_UseSpriteMesh: 0
m_PixelsPerUnitMultiplier: 1
--- !u!1 &641186257110384445
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 3401165947063034107}
- component: {fileID: 542259975490809225}
- component: {fileID: 3062289549238960786}
m_Layer: 0
m_Name: ChevronBg
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!224 &3401165947063034107
RectTransform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 641186257110384445}
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children:
- {fileID: 7098793314482206520}
m_Father: {fileID: 5622481146988834445}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 1, y: 0.5}
m_AnchorMax: {x: 1, y: 0.5}
m_AnchoredPosition: {x: -9, y: 0}
m_SizeDelta: {x: 72, y: 72}
m_Pivot: {x: 0.5, y: 0.5}
--- !u!222 &542259975490809225
CanvasRenderer:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 641186257110384445}
m_CullTransparentMesh: 1
--- !u!114 &3062289549238960786
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 641186257110384445}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3}
m_Name:
m_EditorClassIdentifier:
m_Material: {fileID: 0}
m_Color: {r: 0.15, g: 0.15, b: 0.15, a: 0.85}
m_RaycastTarget: 0
m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
m_Maskable: 1
m_OnCullStateChanged:
m_PersistentCalls:
m_Calls: []
m_Sprite: {fileID: 21300000, guid: fc225262ec91644d08393ad2dedc73f2, type: 3}
m_Type: 0
m_PreserveAspect: 1
m_FillCenter: 1
m_FillMethod: 4
m_FillAmount: 1
m_FillClockwise: 1
m_FillOrigin: 0
m_UseSpriteMesh: 0
m_PixelsPerUnitMultiplier: 1
--- !u!1 &1893870842996581666
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 3407559167762903945}
- component: {fileID: 592473334876629387}
- component: {fileID: 1669590309250913437}
- component: {fileID: 1745363758329991082}
m_Layer: 0
m_Name: MouseBody
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!224 &3407559167762903945
RectTransform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1893870842996581666}
m_LocalRotation: {x: -0, y: -0, z: -0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children:
- {fileID: 8962951458191380602}
- {fileID: 465696906044753221}
- {fileID: 8432427601249552379}
- {fileID: 3137520466663547029}
- {fileID: 6211819109502077103}
- {fileID: 1330816473953486524}
- {fileID: 4809115105408360825}
m_Father: {fileID: 5128845981364829960}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0.5, y: 0.5}
m_AnchorMax: {x: 0.5, y: 0.5}
m_AnchoredPosition: {x: 0, y: 0}
m_SizeDelta: {x: 120, y: 195}
m_Pivot: {x: 0.5, y: 0.5}
--- !u!222 &592473334876629387
CanvasRenderer:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1893870842996581666}
m_CullTransparentMesh: 1
--- !u!114 &1669590309250913437
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1893870842996581666}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3}
m_Name:
m_EditorClassIdentifier:
m_Material: {fileID: 0}
m_Color: {r: 0, g: 0, b: 0, a: 0.6313726}
m_RaycastTarget: 0
m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
m_Maskable: 1
m_OnCullStateChanged:
m_PersistentCalls:
m_Calls: []
m_Sprite: {fileID: 21300000, guid: 696769fce8dcf4cbf9e8e41c55e11260, type: 3}
m_Type: 1
m_PreserveAspect: 0
m_FillCenter: 1
m_FillMethod: 4
m_FillAmount: 1
m_FillClockwise: 1
m_FillOrigin: 0
m_UseSpriteMesh: 0
m_PixelsPerUnitMultiplier: 1
--- !u!114 &1745363758329991082
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1893870842996581666}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 31a19414c41e5ae4aae2af33fee712f6, type: 3}
m_Name:
m_EditorClassIdentifier:
m_ShowMaskGraphic: 1
--- !u!1 &2122203629555508201
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 8124307820913732345}
- component: {fileID: 8863844378423265032}
- component: {fileID: 8237013949146870878}
m_Layer: 0
m_Name: SimulateMouseInputOverlay
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!224 &8124307820913732345
RectTransform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 2122203629555508201}
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children:
- {fileID: 5128845981364829960}
m_Father: {fileID: 0}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0, y: 0}
m_AnchorMax: {x: 0, y: 0}
m_AnchoredPosition: {x: 0, y: 0}
m_SizeDelta: {x: 0, y: 0}
m_Pivot: {x: 0, y: 0}
--- !u!114 &8863844378423265032
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 2122203629555508201}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: c6cfdc16dff1f4baa8199a1a405f3415, type: 3}
m_Name:
m_EditorClassIdentifier:
_leftButton: {fileID: 9067186644091917110}
_rightButton: {fileID: 4269098931396339987}
_scrollWheel: {fileID: 833440402481600460}
_scrollArrowTop: {fileID: 4893873975114215188}
_scrollArrowBottom: {fileID: 6545894353452666225}
_moveDirectionGroup: {fileID: 5622481146988834445}
--- !u!225 &8237013949146870878
CanvasGroup:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 2122203629555508201}
m_Enabled: 1
m_Alpha: 1
m_Interactable: 1
m_BlocksRaycasts: 1
m_IgnoreParentGroups: 0
--- !u!1 &2131268326784498726
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 465696906044753221}
- component: {fileID: 7102697736014393165}
- component: {fileID: 4269098931396339987}
m_Layer: 0
m_Name: RightButton
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!224 &465696906044753221
RectTransform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 2131268326784498726}
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 3407559167762903945}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0.5, y: 0.55}
m_AnchorMax: {x: 1, y: 1}
m_AnchoredPosition: {x: 3, y: 0}
m_SizeDelta: {x: -6, y: 0}
m_Pivot: {x: 0.5, y: 0.5}
--- !u!222 &7102697736014393165
CanvasRenderer:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 2131268326784498726}
m_CullTransparentMesh: 1
--- !u!114 &4269098931396339987
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 2131268326784498726}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3}
m_Name:
m_EditorClassIdentifier:
m_Material: {fileID: 0}
m_Color: {r: 0.23584908, g: 0.23584908, b: 0.23584908, a: 1}
m_RaycastTarget: 0
m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
m_Maskable: 1
m_OnCullStateChanged:
m_PersistentCalls:
m_Calls: []
m_Sprite: {fileID: 0}
m_Type: 0
m_PreserveAspect: 0
m_FillCenter: 1
m_FillMethod: 4
m_FillAmount: 1
m_FillClockwise: 1
m_FillOrigin: 0
m_UseSpriteMesh: 0
m_PixelsPerUnitMultiplier: 1
--- !u!1 &6254897849895741874
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 5128845981364829960}
- component: {fileID: 3667878836297973193}
m_Layer: 0
m_Name: CanvasGroup
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!224 &5128845981364829960
RectTransform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 6254897849895741874}
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children:
- {fileID: 3407559167762903945}
- {fileID: 5622481146988834445}
m_Father: {fileID: 8124307820913732345}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0, y: 0}
m_AnchorMax: {x: 1, y: 1}
m_AnchoredPosition: {x: 0, y: 0}
m_SizeDelta: {x: 0, y: 0}
m_Pivot: {x: 0.5, y: 0.5}
--- !u!225 &3667878836297973193
CanvasGroup:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 6254897849895741874}
m_Enabled: 1
m_Alpha: 0.9
m_Interactable: 0
m_BlocksRaycasts: 0
m_IgnoreParentGroups: 0
--- !u!1 &7009724595179871094
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 4809115105408360825}
- component: {fileID: 4041191362035881534}
- component: {fileID: 6545894353452666225}
m_Layer: 0
m_Name: ScrollArrowBottom
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!224 &4809115105408360825
RectTransform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 7009724595179871094}
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 3407559167762903945}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0.5, y: 0.775}
m_AnchorMax: {x: 0.5, y: 0.775}
m_AnchoredPosition: {x: 0, y: -12}
m_SizeDelta: {x: 14, y: 14}
m_Pivot: {x: 0.5, y: 0.5}
--- !u!222 &4041191362035881534
CanvasRenderer:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 7009724595179871094}
m_CullTransparentMesh: 1
--- !u!114 &6545894353452666225
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 7009724595179871094}
m_Enabled: 0
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3}
m_Name:
m_EditorClassIdentifier:
m_Material: {fileID: 0}
m_Color: {r: 0.1, g: 0.1, b: 0.1, a: 1}
m_RaycastTarget: 0
m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
m_Maskable: 1
m_OnCullStateChanged:
m_PersistentCalls:
m_Calls: []
m_Sprite: {fileID: 21300000, guid: 274dddb42396c4c93bc9d0f4686e357e, type: 3}
m_Type: 0
m_PreserveAspect: 0
m_FillCenter: 1
m_FillMethod: 4
m_FillAmount: 1
m_FillClockwise: 1
m_FillOrigin: 0
m_UseSpriteMesh: 0
m_PixelsPerUnitMultiplier: 1
--- !u!1 &7345968847908351245
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 1330816473953486524}
- component: {fileID: 4775689186010506371}
- component: {fileID: 4893873975114215188}
m_Layer: 0
m_Name: ScrollArrowTop
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!224 &1330816473953486524
RectTransform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 7345968847908351245}
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 3407559167762903945}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0.5, y: 0.775}
m_AnchorMax: {x: 0.5, y: 0.775}
m_AnchoredPosition: {x: 0, y: 12}
m_SizeDelta: {x: 14, y: 14}
m_Pivot: {x: 0.5, y: 0.5}
--- !u!222 &4775689186010506371
CanvasRenderer:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 7345968847908351245}
m_CullTransparentMesh: 1
--- !u!114 &4893873975114215188
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 7345968847908351245}
m_Enabled: 0
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3}
m_Name:
m_EditorClassIdentifier:
m_Material: {fileID: 0}
m_Color: {r: 0.1, g: 0.1, b: 0.1, a: 1}
m_RaycastTarget: 0
m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
m_Maskable: 1
m_OnCullStateChanged:
m_PersistentCalls:
m_Calls: []
m_Sprite: {fileID: 21300000, guid: 274dddb42396c4c93bc9d0f4686e357e, type: 3}
m_Type: 0
m_PreserveAspect: 0
m_FillCenter: 1
m_FillMethod: 4
m_FillAmount: 1
m_FillClockwise: 1
m_FillOrigin: 0
m_UseSpriteMesh: 0
m_PixelsPerUnitMultiplier: 1
--- !u!1 &7553317276571807195
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 8432427601249552379}
- component: {fileID: 626464046296980867}
- component: {fileID: 7338358790227330862}
m_Layer: 0
m_Name: Divider
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!224 &8432427601249552379
RectTransform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 7553317276571807195}
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 3407559167762903945}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0.5, y: 0.55}
m_AnchorMax: {x: 0.5, y: 1}
m_AnchoredPosition: {x: 0, y: 0}
m_SizeDelta: {x: 12, y: 0}
m_Pivot: {x: 0.5, y: 0.5}
--- !u!222 &626464046296980867
CanvasRenderer:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 7553317276571807195}
m_CullTransparentMesh: 1
--- !u!114 &7338358790227330862
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 7553317276571807195}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3}
m_Name:
m_EditorClassIdentifier:
m_Material: {fileID: 0}
m_Color: {r: 0.1, g: 0.1, b: 0.1, a: 1}
m_RaycastTarget: 0
m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
m_Maskable: 1
m_OnCullStateChanged:
m_PersistentCalls:
m_Calls: []
m_Sprite: {fileID: 0}
m_Type: 0
m_PreserveAspect: 0
m_FillCenter: 1
m_FillMethod: 4
m_FillAmount: 1
m_FillClockwise: 1
m_FillOrigin: 0
m_UseSpriteMesh: 0
m_PixelsPerUnitMultiplier: 1
--- !u!1 &8009591172217868134
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 5622481146988834445}
m_Layer: 0
m_Name: MoveDirectionGroup
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!224 &5622481146988834445
RectTransform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 8009591172217868134}
m_LocalRotation: {x: -0, y: -0, z: -0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children:
- {fileID: 3401165947063034107}
m_Father: {fileID: 5128845981364829960}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0.5, y: 0.5}
m_AnchorMax: {x: 0.5, y: 0.5}
m_AnchoredPosition: {x: 0, y: 0}
m_SizeDelta: {x: 300, y: 60}
m_Pivot: {x: 0.5, y: 0.5}
--- !u!1 &8293422726571725699
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 8962951458191380602}
- component: {fileID: 4502291206784101432}
- component: {fileID: 9067186644091917110}
m_Layer: 0
m_Name: LeftButton
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!224 &8962951458191380602
RectTransform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 8293422726571725699}
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 3407559167762903945}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0, y: 0.55}
m_AnchorMax: {x: 0.5, y: 1}
m_AnchoredPosition: {x: -3, y: 0}
m_SizeDelta: {x: -6, y: 0}
m_Pivot: {x: 0.5, y: 0.5}
--- !u!222 &4502291206784101432
CanvasRenderer:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 8293422726571725699}
m_CullTransparentMesh: 1
--- !u!114 &9067186644091917110
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 8293422726571725699}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3}
m_Name:
m_EditorClassIdentifier:
m_Material: {fileID: 0}
m_Color: {r: 0.23584908, g: 0.23584908, b: 0.23584908, a: 1}
m_RaycastTarget: 0
m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
m_Maskable: 1
m_OnCullStateChanged:
m_PersistentCalls:
m_Calls: []
m_Sprite: {fileID: 0}
m_Type: 0
m_PreserveAspect: 0
m_FillCenter: 1
m_FillMethod: 4
m_FillAmount: 1
m_FillClockwise: 1
m_FillOrigin: 0
m_UseSpriteMesh: 0
m_PixelsPerUnitMultiplier: 1
--- !u!1 &8702196187181304333
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 3137520466663547029}
- component: {fileID: 7037657719098377586}
- component: {fileID: 8349798665654410308}
m_Layer: 0
m_Name: WheelOutline
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!224 &3137520466663547029
RectTransform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 8702196187181304333}
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 3407559167762903945}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0.5, y: 0.775}
m_AnchorMax: {x: 0.5, y: 0.775}
m_AnchoredPosition: {x: 0, y: 0}
m_SizeDelta: {x: 38, y: 62}
m_Pivot: {x: 0.5, y: 0.5}
--- !u!222 &7037657719098377586
CanvasRenderer:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 8702196187181304333}
m_CullTransparentMesh: 1
--- !u!114 &8349798665654410308
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 8702196187181304333}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3}
m_Name:
m_EditorClassIdentifier:
m_Material: {fileID: 0}
m_Color: {r: 0.1, g: 0.1, b: 0.1, a: 0.9}
m_RaycastTarget: 0
m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
m_Maskable: 1
m_OnCullStateChanged:
m_PersistentCalls:
m_Calls: []
m_Sprite: {fileID: 21300000, guid: fa770edf1801941279ad40d3958b3f3f, type: 3}
m_Type: 1
m_PreserveAspect: 0
m_FillCenter: 1
m_FillMethod: 4
m_FillAmount: 1
m_FillClockwise: 1
m_FillOrigin: 0
m_UseSpriteMesh: 0
m_PixelsPerUnitMultiplier: 1
--- !u!1 &8719267255120921363
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 7098793314482206520}
- component: {fileID: 7109963236635679673}
- component: {fileID: 4677096323163002241}
m_Layer: 0
m_Name: Chevron1
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!224 &7098793314482206520
RectTransform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 8719267255120921363}
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 3401165947063034107}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0.5, y: 0.5}
m_AnchorMax: {x: 0.5, y: 0.5}
m_AnchoredPosition: {x: 0, y: 0}
m_SizeDelta: {x: 40, y: 40}
m_Pivot: {x: 0.5, y: 0.5}
--- !u!222 &7109963236635679673
CanvasRenderer:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 8719267255120921363}
m_CullTransparentMesh: 1
--- !u!114 &4677096323163002241
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 8719267255120921363}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3}
m_Name:
m_EditorClassIdentifier:
m_Material: {fileID: 0}
m_Color: {r: 1, g: 1, b: 1, a: 1}
m_RaycastTarget: 0
m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
m_Maskable: 1
m_OnCullStateChanged:
m_PersistentCalls:
m_Calls: []
m_Sprite: {fileID: 21300000, guid: e2f0935a9b378436ea49e5e300e9d6c9, type: 3}
m_Type: 0
m_PreserveAspect: 0
m_FillCenter: 1
m_FillMethod: 4
m_FillAmount: 1
m_FillClockwise: 1
m_FillOrigin: 0
m_UseSpriteMesh: 0
m_PixelsPerUnitMultiplier: 1

View File

@@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: 242afb3abe6ac48f99512e35951c9978
PrefabImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,131 @@
#nullable enable
using UnityEngine;
namespace io.github.hatayama.uLoopMCP
{
public static class SimulateMouseInputOverlayState
{
private const float BUTTON_MIN_DISPLAY_DURATION = 0.05f;
private static bool _leftButtonHeld;
private static bool _rightButtonHeld;
private static bool _middleButtonHeld;
private static float _leftButtonActiveUntil;
private static float _rightButtonActiveUntil;
private static float _middleButtonActiveUntil;
public static bool IsLeftButtonHeld =>
_leftButtonHeld || Time.realtimeSinceStartup < _leftButtonActiveUntil;
public static bool IsRightButtonHeld =>
_rightButtonHeld || Time.realtimeSinceStartup < _rightButtonActiveUntil;
public static bool IsMiddleButtonHeld =>
_middleButtonHeld || Time.realtimeSinceStartup < _middleButtonActiveUntil;
private const float SCROLL_DISPLAY_DURATION = 0.05f;
private static int _scrollDirection;
private static float _scrollActiveUntil;
public static int ScrollDirection =>
_scrollDirection != 0 && Time.realtimeSinceStartup < _scrollActiveUntil
? _scrollDirection
: 0;
private const float MOVE_DISPLAY_DURATION = 0.3f;
private const int MOVE_SAMPLE_FRAMES = 5;
private static Vector2 _moveDelta;
private static Vector2 _moveAccumulator;
private static int _moveFrameCount;
private static float _moveActiveUntil;
public static Vector2 MoveDelta =>
_moveDelta != Vector2.zero && Time.realtimeSinceStartup < _moveActiveUntil
? _moveDelta
: Vector2.zero;
public static float LastActivityTime { get; private set; }
public static bool HasAnyActivity =>
IsLeftButtonHeld || IsRightButtonHeld || IsMiddleButtonHeld
|| ScrollDirection != 0 || MoveDelta != Vector2.zero;
public static void SetButtonHeld(MouseButton button, bool held)
{
// When releasing, set a minimum display time so short clicks are always visible
float activeUntil = held ? 0f : Time.realtimeSinceStartup + BUTTON_MIN_DISPLAY_DURATION;
switch (button)
{
case MouseButton.Left:
_leftButtonHeld = held;
if (!held) _leftButtonActiveUntil = activeUntil;
break;
case MouseButton.Right:
_rightButtonHeld = held;
if (!held) _rightButtonActiveUntil = activeUntil;
break;
case MouseButton.Middle:
_middleButtonHeld = held;
if (!held) _middleButtonActiveUntil = activeUntil;
break;
default:
Debug.Assert(false, $"Unexpected MouseButton value: {button}");
break;
}
LastActivityTime = Time.realtimeSinceStartup;
}
public static void SetScrollDirection(int direction)
{
Debug.Assert(direction >= -1 && direction <= 1, $"direction must be -1, 0, or 1, got: {direction}");
_scrollDirection = direction;
_scrollActiveUntil = Time.realtimeSinceStartup + SCROLL_DISPLAY_DURATION;
LastActivityTime = Time.realtimeSinceStartup;
}
public static void ClearScroll()
{
_scrollActiveUntil = 0f;
}
public static void SetMoveDelta(Vector2 delta)
{
_moveAccumulator += delta;
_moveFrameCount++;
// Update direction every frame from accumulated delta so single-call
// MoveDelta actions are visible, while the accumulator reset every N
// frames smooths out per-frame integer quantization noise.
if (_moveAccumulator != Vector2.zero)
{
_moveDelta = _moveAccumulator.normalized;
}
if (_moveFrameCount >= MOVE_SAMPLE_FRAMES)
{
_moveAccumulator = Vector2.zero;
_moveFrameCount = 0;
}
_moveActiveUntil = Time.realtimeSinceStartup + MOVE_DISPLAY_DURATION;
LastActivityTime = Time.realtimeSinceStartup;
}
public static void Clear()
{
_leftButtonHeld = false;
_rightButtonHeld = false;
_middleButtonHeld = false;
_leftButtonActiveUntil = 0f;
_rightButtonActiveUntil = 0f;
_middleButtonActiveUntil = 0f;
_scrollDirection = 0;
_scrollActiveUntil = 0f;
_moveDelta = Vector2.zero;
_moveAccumulator = Vector2.zero;
_moveFrameCount = 0;
_moveActiveUntil = 0f;
LastActivityTime = 0f;
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 1cc075b404c91432ebd44a0f6b3095ee
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 659f828709cca454688613d415063d70
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,140 @@
fileFormatVersion: 2
guid: 0294a084c436048db9ed81eac798a709
TextureImporter:
internalIDToNameTable: []
externalObjects: {}
serializedVersion: 13
mipmaps:
mipMapMode: 0
enableMipMap: 0
sRGBTexture: 1
linearTexture: 0
fadeOut: 0
borderMipMap: 0
mipMapsPreserveCoverage: 0
alphaTestReferenceValue: 0.5
mipMapFadeDistanceStart: 1
mipMapFadeDistanceEnd: 3
bumpmap:
convertToNormalMap: 0
externalNormalMap: 0
heightScale: 0.25
normalMapFilter: 0
flipGreenChannel: 0
isReadable: 0
streamingMipmaps: 0
streamingMipmapsPriority: 0
vTOnly: 0
ignoreMipmapLimit: 0
grayScaleToAlpha: 0
generateCubemap: 6
cubemapConvolution: 0
seamlessCubemap: 0
textureFormat: 1
maxTextureSize: 2048
textureSettings:
serializedVersion: 2
filterMode: 1
aniso: 1
mipBias: 0
wrapU: 1
wrapV: 1
wrapW: 1
nPOTScale: 0
lightmap: 0
compressionQuality: 50
spriteMode: 1
spriteExtrude: 1
spriteMeshType: 1
alignment: 0
spritePivot: {x: 0.5, y: 0.5}
spritePixelsToUnits: 100
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
spriteGenerateFallbackPhysicsShape: 1
alphaUsage: 1
alphaIsTransparency: 1
spriteTessellationDetail: -1
textureType: 8
textureShape: 1
singleChannelComponent: 0
flipbookRows: 1
flipbookColumns: 1
maxTextureSizeSet: 0
compressionQualitySet: 0
textureFormatSet: 0
ignorePngGamma: 0
applyGammaDecoding: 0
swizzle: 50462976
cookieLightType: 0
platformSettings:
- serializedVersion: 3
buildTarget: DefaultTexturePlatform
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 0
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
- serializedVersion: 3
buildTarget: Standalone
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
- serializedVersion: 3
buildTarget: iPhone
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
- serializedVersion: 3
buildTarget: Android
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
spriteSheet:
serializedVersion: 2
sprites: []
outline: []
physicsShape: []
bones: []
spriteID: 5e97eb03825dee720800000000000000
internalID: 0
vertices: []
indices:
edges: []
weights: []
secondaryTextures: []
nameFileIdTable: {}
mipmapLimitGroupName:
pSDRemoveMatte: 0
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,12 @@
namespace io.github.hatayama.uLoopMCP
{
public enum MouseAction
{
Click = 0,
Drag = 1,
DragStart = 2,
DragMove = 3,
DragEnd = 4,
LongPress = 5
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: d063a5fabb86749b4be11bd2b189db8d
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,9 @@
namespace io.github.hatayama.uLoopMCP
{
public static class SimulateMouseUiAnimationConstants
{
public const float EXPAND_DURATION = 0.1f;
public const float EXPAND_START_SCALE = 1.5f;
public const float DISSIPATE_DURATION = 0.1f;
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 1b2a42b98d6124b0a828dd71a039d401
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,318 @@
#if UNITY_EDITOR
#nullable enable
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
namespace io.github.hatayama.uLoopMCP
{
// Canvas-based overlay that visualizes SimulateMouseUi cursor position and drag state on Game View.
// Animation is driven externally via SetCursorScale/SetAlpha from async functions in SimulateMouseUiTool.
public class SimulateMouseUiOverlay : MonoBehaviour
{
private const float WAYPOINT_MARKER_DIAMETER = 12f;
private const float LINE_THICKNESS = 2f;
private static readonly Color CLICK_COLOR = new Color(0f, 1f, 0.4f, 0.9f);
private static readonly Color DRAG_COLOR = new Color(1f, 0.6f, 0f, 0.9f);
[SerializeField] private CanvasGroup _canvasGroup = null!;
[SerializeField] private RectTransform _cursorGroup = null!;
[SerializeField] private Image _circleImage = null!;
[SerializeField] private Image _crosshairH = null!;
[SerializeField] private Image _crosshairV = null!;
[SerializeField] private Text _longPressText = null!;
[SerializeField] private Image _dragStartMarker = null!;
[SerializeField] private Sprite _circleSprite = null!;
private readonly List<Image> _pathSegments = new List<Image>();
private readonly List<Image> _waypointMarkers = new List<Image>();
private const float SELF_EXPAND_DURATION = SimulateMouseUiAnimationConstants.EXPAND_DURATION;
private const float SELF_EXPAND_START_SCALE = SimulateMouseUiAnimationConstants.EXPAND_START_SCALE;
private const float SELF_DISSIPATE_DURATION = SimulateMouseUiAnimationConstants.DISSIPATE_DURATION;
private enum SelfAnimState { None, Expanding, Dissipating }
private SelfAnimState _selfAnimState = SelfAnimState.None;
private float _selfAnimStartTime;
private void Awake()
{
Debug.Assert(_canvasGroup != null, "_canvasGroup must be assigned in prefab");
Debug.Assert(_cursorGroup != null, "_cursorGroup must be assigned in prefab");
Debug.Assert(_circleImage != null, "_circleImage must be assigned in prefab");
Debug.Assert(_crosshairH != null, "_crosshairH must be assigned in prefab");
Debug.Assert(_crosshairV != null, "_crosshairV must be assigned in prefab");
Debug.Assert(_longPressText != null, "_longPressText must be assigned in prefab");
Debug.Assert(_dragStartMarker != null, "_dragStartMarker must be assigned in prefab");
Debug.Assert(_circleSprite != null, "_circleSprite must be assigned in prefab");
_canvasGroup!.alpha = 0;
}
private void LateUpdate()
{
ConsumePendingAnimationRequests();
// Dissipate runs independently of overlay state (state is already cleared on release)
if (_selfAnimState == SelfAnimState.Dissipating)
{
float elapsed = Time.realtimeSinceStartup - _selfAnimStartTime;
float t = Mathf.Clamp01(elapsed / SELF_DISSIPATE_DURATION);
_cursorGroup.localScale = Vector3.one * Mathf.Lerp(1f, 0f, t);
_canvasGroup.alpha = Mathf.Lerp(1f, 0f, t);
if (t >= 1f)
{
_selfAnimState = SelfAnimState.None;
_canvasGroup.alpha = 0f;
}
return;
}
if (!SimulateMouseUiOverlayState.IsActive)
{
_canvasGroup.alpha = 0;
return;
}
// SimulateMouseUiTool controls alpha via SetAlpha during animations.
// For non-animated callers (e.g. InputReplayer), auto-show on first active frame.
if (_canvasGroup.alpha == 0f)
{
_canvasGroup.alpha = 1f;
_cursorGroup.localScale = Vector3.one;
}
if (_selfAnimState == SelfAnimState.Expanding)
{
float elapsed = Time.realtimeSinceStartup - _selfAnimStartTime;
float t = Mathf.Clamp01(elapsed / SELF_EXPAND_DURATION);
_cursorGroup.localScale = Vector3.one * Mathf.Lerp(SELF_EXPAND_START_SCALE, 1f, t);
if (t >= 1f)
{
_selfAnimState = SelfAnimState.None;
}
}
UpdateCursorPosition();
UpdateCursorMode();
UpdateDragPath();
}
private void ConsumePendingAnimationRequests()
{
if (SimulateMouseUiOverlayState.ConsumePendingExpandAnimation())
{
_canvasGroup.alpha = 1f;
_cursorGroup.localScale = Vector3.one * SELF_EXPAND_START_SCALE;
_selfAnimState = SelfAnimState.Expanding;
_selfAnimStartTime = Time.realtimeSinceStartup;
}
if (SimulateMouseUiOverlayState.ConsumePendingDissipateAnimation())
{
_selfAnimState = SelfAnimState.Dissipating;
_selfAnimStartTime = Time.realtimeSinceStartup;
}
}
public void SetCursorScale(float scale)
{
_cursorGroup.localScale = Vector3.one * scale;
// SimulateMouseUiTool drives animation externally; cancel any self-driven animation
_selfAnimState = SelfAnimState.None;
}
public void SetAlpha(float alpha)
{
_canvasGroup.alpha = alpha;
_selfAnimState = SelfAnimState.None;
}
// sim coordinate: simX = screen pixel X, simY = EditorScreen.height - canvasY (top-left origin)
// Canvas Screen Space Overlay position: bottom-left origin
private static Vector2 SimToScreen(Vector2 simPos)
{
Vector2 srcSize = SimulateMouseUiOverlayState.SourceScreenSize;
Debug.Assert(srcSize.x > 0f && srcSize.y > 0f, "SourceScreenSize must be set before SimToScreen is called");
return new Vector2(simPos.x, srcSize.y - simPos.y);
}
private void UpdateCursorPosition()
{
Vector2 screenPos = SimToScreen(SimulateMouseUiOverlayState.CurrentPosition);
_cursorGroup.position = new Vector3(screenPos.x, screenPos.y, 0f);
}
private void UpdateCursorMode()
{
bool isLongPress = SimulateMouseUiOverlayState.Action == MouseAction.LongPress;
_crosshairH.enabled = !isLongPress;
_crosshairV.enabled = !isLongPress;
_longPressText.enabled = isLongPress;
if (isLongPress)
{
_longPressText.text = SimulateMouseUiOverlayState.LongPressElapsed.ToString("F1") + "s";
// Pulse the circle between 1.0x and 1.2x scale over a 2-second cycle
float t = Mathf.PingPong(SimulateMouseUiOverlayState.LongPressElapsed, 2f) / 2f;
float scale = Mathf.Lerp(1.0f, 1.2f, t);
_circleImage.rectTransform.localScale = Vector3.one * scale;
}
else
{
_circleImage.rectTransform.localScale = Vector3.one;
}
}
private void UpdateDragPath()
{
if (!SimulateMouseUiOverlayState.DragStartPosition.HasValue)
{
_dragStartMarker.enabled = false;
HidePool(_pathSegments);
HidePool(_waypointMarkers);
// Keep a reasonable number of pooled objects for reuse across drags
TrimPool(_pathSegments, 5);
TrimPool(_waypointMarkers, 4);
return;
}
Color activeColor = GetActiveColor();
// Start marker
Vector2 startScreen = SimToScreen(SimulateMouseUiOverlayState.DragStartPosition.Value);
_dragStartMarker.enabled = true;
_dragStartMarker.color = activeColor;
_dragStartMarker.rectTransform.position = new Vector3(startScreen.x, startScreen.y, 0f);
// Polyline: start → waypoints → current
IReadOnlyList<Vector2> waypoints = SimulateMouseUiOverlayState.DragWaypoints;
Vector2 currentScreen = SimToScreen(SimulateMouseUiOverlayState.CurrentPosition);
int segmentCount = waypoints.Count + 1;
EnsurePoolCount(_pathSegments, segmentCount, CreatePooledSegment);
EnsurePoolCount(_waypointMarkers, waypoints.Count, CreatePooledWaypointMarker);
// All segments fade: oldest = transparent, newest = most visible (but not fully opaque)
float canvasScale = _pathSegments.Count > 0 ? _pathSegments[0].rectTransform.lossyScale.x : 1f;
Vector2 prev = startScreen;
for (int i = 0; i < segmentCount; i++)
{
Vector2 to = (i < waypoints.Count) ? SimToScreen(waypoints[i]) : currentScreen;
float alpha = (float)(i + 1) / (segmentCount + 1);
Color fadedColor = activeColor;
fadedColor.a = activeColor.a * alpha;
DrawSegment(_pathSegments[i], prev, to, fadedColor, canvasScale);
if (i < waypoints.Count)
{
_waypointMarkers[i].enabled = true;
_waypointMarkers[i].color = fadedColor;
_waypointMarkers[i].rectTransform.position = new Vector3(to.x, to.y, 0f);
}
prev = to;
}
HidePoolFrom(_pathSegments, segmentCount);
HidePoolFrom(_waypointMarkers, waypoints.Count);
}
private void DrawSegment(Image line, Vector2 from, Vector2 to, Color color, float canvasScale)
{
Vector2 delta = to - from;
float length = delta.magnitude;
if (length < 1f)
{
line.enabled = false;
return;
}
line.enabled = true;
line.color = color;
float angle = Mathf.Atan2(delta.y, delta.x) * Mathf.Rad2Deg;
RectTransform rect = line.rectTransform;
rect.position = new Vector3(from.x, from.y, 0f);
// sizeDelta is in local space; convert screen-pixel length via lossyScale
rect.sizeDelta = new Vector2(length / canvasScale, LINE_THICKNESS / canvasScale);
rect.localRotation = Quaternion.Euler(0f, 0f, angle);
}
private Image CreatePooledSegment()
{
Image line = CreateImage("PathSegment", gameObject.transform);
line.rectTransform.pivot = new Vector2(0f, 0.5f);
line.rectTransform.sizeDelta = Vector2.zero;
line.enabled = false;
return line;
}
private Image CreatePooledWaypointMarker()
{
Image marker = CreateImage("WaypointMarker", gameObject.transform);
marker.rectTransform.sizeDelta = new Vector2(WAYPOINT_MARKER_DIAMETER, WAYPOINT_MARKER_DIAMETER);
marker.sprite = _circleSprite;
marker.enabled = false;
return marker;
}
private void EnsurePoolCount(List<Image> pool, int count, System.Func<Image> factory)
{
while (pool.Count < count)
{
pool.Add(factory());
}
}
private static void HidePool(List<Image> pool)
{
for (int i = 0; i < pool.Count; i++)
{
pool[i].enabled = false;
}
}
// Pools only grow via EnsurePoolCount; trim excess to prevent unbounded accumulation
private static void TrimPool(List<Image> pool, int maxRetain)
{
while (pool.Count > maxRetain)
{
Image excess = pool[pool.Count - 1];
pool.RemoveAt(pool.Count - 1);
Destroy(excess.gameObject);
}
}
private static void HidePoolFrom(List<Image> pool, int startIndex)
{
for (int i = startIndex; i < pool.Count; i++)
{
pool[i].enabled = false;
}
}
private Color GetActiveColor()
{
return SimulateMouseUiOverlayState.Action == MouseAction.Click
? CLICK_COLOR
: DRAG_COLOR;
}
private static Image CreateImage(string name, Transform parent)
{
GameObject go = new GameObject(name);
go.transform.SetParent(parent, false);
RectTransform rect = go.AddComponent<RectTransform>();
rect.anchorMin = Vector2.zero;
rect.anchorMax = Vector2.zero;
rect.pivot = new Vector2(0.5f, 0.5f);
Image image = go.AddComponent<Image>();
image.raycastTarget = false;
return image;
}
}
}
#endif

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: c4a25f7a1c89649bd9cef96ea292a47e
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,507 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!1 &3579496036604184255
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 903290766560929725}
- component: {fileID: 4854423239222691101}
- component: {fileID: 2204762901719864460}
m_Layer: 0
m_Name: DragStartMarker
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!224 &903290766560929725
RectTransform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 3579496036604184255}
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 5435175328419204271}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0, y: 0}
m_AnchorMax: {x: 0, y: 0}
m_AnchoredPosition: {x: 0, y: 0}
m_SizeDelta: {x: 8, y: 8}
m_Pivot: {x: 0.5, y: 0.5}
--- !u!222 &4854423239222691101
CanvasRenderer:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 3579496036604184255}
m_CullTransparentMesh: 1
--- !u!114 &2204762901719864460
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 3579496036604184255}
m_Enabled: 0
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3}
m_Name:
m_EditorClassIdentifier:
m_Material: {fileID: 0}
m_Color: {r: 1, g: 1, b: 1, a: 1}
m_RaycastTarget: 0
m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
m_Maskable: 1
m_OnCullStateChanged:
m_PersistentCalls:
m_Calls: []
m_Sprite: {fileID: 0}
m_Type: 0
m_PreserveAspect: 0
m_FillCenter: 1
m_FillMethod: 4
m_FillAmount: 1
m_FillClockwise: 1
m_FillOrigin: 0
m_UseSpriteMesh: 0
m_PixelsPerUnitMultiplier: 1
--- !u!1 &3645456351603840414
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 1795238667056386859}
m_Layer: 0
m_Name: CursorGroup
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!224 &1795238667056386859
RectTransform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 3645456351603840414}
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children:
- {fileID: 910718756846548758}
- {fileID: 1713159570844151935}
- {fileID: 7309688806247926274}
- {fileID: 4259856659709602188}
m_Father: {fileID: 5435175328419204271}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0.5, y: 0.5}
m_AnchorMax: {x: 0.5, y: 0.5}
m_AnchoredPosition: {x: 0, y: 0}
m_SizeDelta: {x: 0, y: 0}
m_Pivot: {x: 0.5, y: 0.5}
--- !u!1 &4096853404940709834
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 7309688806247926274}
- component: {fileID: 4947376121546195582}
- component: {fileID: 3118357298515763328}
m_Layer: 0
m_Name: CrosshairV
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!224 &7309688806247926274
RectTransform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 4096853404940709834}
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 1795238667056386859}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0, y: 0}
m_AnchorMax: {x: 0, y: 0}
m_AnchoredPosition: {x: 0, y: 0}
m_SizeDelta: {x: 3, y: 40}
m_Pivot: {x: 0.5, y: 0.5}
--- !u!222 &4947376121546195582
CanvasRenderer:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 4096853404940709834}
m_CullTransparentMesh: 1
--- !u!114 &3118357298515763328
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 4096853404940709834}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3}
m_Name:
m_EditorClassIdentifier:
m_Material: {fileID: 0}
m_Color: {r: 0, g: 0, b: 0, a: 1}
m_RaycastTarget: 0
m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
m_Maskable: 1
m_OnCullStateChanged:
m_PersistentCalls:
m_Calls: []
m_Sprite: {fileID: 0}
m_Type: 0
m_PreserveAspect: 0
m_FillCenter: 1
m_FillMethod: 4
m_FillAmount: 1
m_FillClockwise: 1
m_FillOrigin: 0
m_UseSpriteMesh: 0
m_PixelsPerUnitMultiplier: 1
--- !u!1 &6086391879608123167
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 910718756846548758}
- component: {fileID: 3831445468382753575}
- component: {fileID: 1668577853838809154}
m_Layer: 0
m_Name: Circle
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!224 &910718756846548758
RectTransform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 6086391879608123167}
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 1795238667056386859}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0, y: 0}
m_AnchorMax: {x: 0, y: 0}
m_AnchoredPosition: {x: 0, y: 0}
m_SizeDelta: {x: 70, y: 70}
m_Pivot: {x: 0.5, y: 0.5}
--- !u!222 &3831445468382753575
CanvasRenderer:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 6086391879608123167}
m_CullTransparentMesh: 1
--- !u!114 &1668577853838809154
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 6086391879608123167}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3}
m_Name:
m_EditorClassIdentifier:
m_Material: {fileID: 0}
m_Color: {r: 1, g: 1, b: 1, a: 0.8}
m_RaycastTarget: 0
m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
m_Maskable: 1
m_OnCullStateChanged:
m_PersistentCalls:
m_Calls: []
m_Sprite: {fileID: 21300000, guid: 0294a084c436048db9ed81eac798a709, type: 3}
m_Type: 0
m_PreserveAspect: 0
m_FillCenter: 1
m_FillMethod: 4
m_FillAmount: 1
m_FillClockwise: 1
m_FillOrigin: 0
m_UseSpriteMesh: 0
m_PixelsPerUnitMultiplier: 1
--- !u!1 &7486829258772114075
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 1713159570844151935}
- component: {fileID: 6661013875495849459}
- component: {fileID: 2445404945182483613}
m_Layer: 0
m_Name: CrosshairH
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!224 &1713159570844151935
RectTransform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 7486829258772114075}
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 1795238667056386859}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0, y: 0}
m_AnchorMax: {x: 0, y: 0}
m_AnchoredPosition: {x: 0, y: 0}
m_SizeDelta: {x: 40, y: 3}
m_Pivot: {x: 0.5, y: 0.5}
--- !u!222 &6661013875495849459
CanvasRenderer:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 7486829258772114075}
m_CullTransparentMesh: 1
--- !u!114 &2445404945182483613
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 7486829258772114075}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3}
m_Name:
m_EditorClassIdentifier:
m_Material: {fileID: 0}
m_Color: {r: 0, g: 0, b: 0, a: 1}
m_RaycastTarget: 0
m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
m_Maskable: 1
m_OnCullStateChanged:
m_PersistentCalls:
m_Calls: []
m_Sprite: {fileID: 0}
m_Type: 0
m_PreserveAspect: 0
m_FillCenter: 1
m_FillMethod: 4
m_FillAmount: 1
m_FillClockwise: 1
m_FillOrigin: 0
m_UseSpriteMesh: 0
m_PixelsPerUnitMultiplier: 1
--- !u!1 &8398465818153543159
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 4259856659709602188}
- component: {fileID: 7692415534472380766}
- component: {fileID: 8021270174096083990}
- component: {fileID: 7159060278707641568}
m_Layer: 0
m_Name: LongPressText
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!224 &4259856659709602188
RectTransform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 8398465818153543159}
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 1795238667056386859}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0.5, y: 0.5}
m_AnchorMax: {x: 0.5, y: 0.5}
m_AnchoredPosition: {x: 0, y: 0}
m_SizeDelta: {x: 140, y: 70}
m_Pivot: {x: 0.5, y: 0.5}
--- !u!222 &7692415534472380766
CanvasRenderer:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 8398465818153543159}
m_CullTransparentMesh: 1
--- !u!114 &8021270174096083990
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 8398465818153543159}
m_Enabled: 0
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 5f7201a12d95ffc409449d95f23cf332, type: 3}
m_Name:
m_EditorClassIdentifier:
m_Material: {fileID: 0}
m_Color: {r: 0, g: 0, b: 0, a: 1}
m_RaycastTarget: 0
m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
m_Maskable: 1
m_OnCullStateChanged:
m_PersistentCalls:
m_Calls: []
m_FontData:
m_Font: {fileID: 10102, guid: 0000000000000000e000000000000000, type: 0}
m_FontSize: 28
m_FontStyle: 0
m_BestFit: 0
m_MinSize: 10
m_MaxSize: 40
m_Alignment: 4
m_AlignByGeometry: 0
m_RichText: 1
m_HorizontalOverflow: 0
m_VerticalOverflow: 0
m_LineSpacing: 1
m_Text:
--- !u!114 &7159060278707641568
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 8398465818153543159}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: e19747de3f5aca642ab2be37e372fb86, type: 3}
m_Name:
m_EditorClassIdentifier:
m_EffectColor: {r: 1, g: 1, b: 1, a: 1}
m_EffectDistance: {x: 1.5, y: -1.5}
m_UseGraphicAlpha: 1
--- !u!1 &9106729417482781781
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 5435175328419204271}
- component: {fileID: 7252727134433425355}
- component: {fileID: 6021016629897285075}
m_Layer: 0
m_Name: SimulateMouseUiOverlay
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!224 &5435175328419204271
RectTransform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 9106729417482781781}
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children:
- {fileID: 903290766560929725}
- {fileID: 1795238667056386859}
m_Father: {fileID: 0}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0, y: 0}
m_AnchorMax: {x: 0, y: 0}
m_AnchoredPosition: {x: 0, y: 0}
m_SizeDelta: {x: 0, y: 0}
m_Pivot: {x: 0, y: 0}
--- !u!114 &7252727134433425355
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 9106729417482781781}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: c4a25f7a1c89649bd9cef96ea292a47e, type: 3}
m_Name:
m_EditorClassIdentifier:
_canvasGroup: {fileID: 6021016629897285075}
_cursorGroup: {fileID: 1795238667056386859}
_circleImage: {fileID: 1668577853838809154}
_crosshairH: {fileID: 2445404945182483613}
_crosshairV: {fileID: 3118357298515763328}
_longPressText: {fileID: 8021270174096083990}
_dragStartMarker: {fileID: 2204762901719864460}
_circleSprite: {fileID: 21300000, guid: 0294a084c436048db9ed81eac798a709, type: 3}
--- !u!225 &6021016629897285075
CanvasGroup:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 9106729417482781781}
m_Enabled: 1
m_Alpha: 1
m_Interactable: 0
m_BlocksRaycasts: 0
m_IgnoreParentGroups: 0

View File

@@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: f47ccc1f9351044799d3c9da246db73a
PrefabImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,118 @@
#nullable enable
using System.Collections.Generic;
using UnityEngine;
namespace io.github.hatayama.uLoopMCP
{
public static class SimulateMouseUiOverlayState
{
public static bool IsActive { get; private set; }
public static MouseAction Action { get; private set; }
public static Vector2 CurrentPosition { get; private set; }
public static Vector2? DragStartPosition { get; private set; }
public static string? HitGameObjectName { get; private set; }
// Screen.width/height at the time positions were recorded (Editor context may differ from Game context)
public static Vector2 SourceScreenSize { get; private set; }
public static float LongPressElapsed { get; private set; }
// Animation request flags survive Clear() — they are consumed by the overlay in LateUpdate
private static bool _pendingExpandAnimation;
private static bool _pendingDissipateAnimation;
private const int MAX_DRAG_WAYPOINTS = 4;
private static readonly List<Vector2> _dragWaypoints = new List<Vector2>();
// Intermediate positions where DragMove stopped, forming a polyline path
public static IReadOnlyList<Vector2> DragWaypoints => _dragWaypoints;
public static void Update(
MouseAction action,
Vector2 currentPosition,
Vector2? dragStartPosition,
string? hitGameObjectName,
Vector2 sourceScreenSize)
{
// PlayDissipateAnimation calls Clear() on normal completion, but a cancelled or stuck drag
// may leave stale waypoints — defensive clear ensures a fresh start
if (action == MouseAction.DragStart || action == MouseAction.Drag)
{
_dragWaypoints.Clear();
}
IsActive = true;
Action = action;
CurrentPosition = currentPosition;
DragStartPosition = dragStartPosition;
HitGameObjectName = hitGameObjectName;
SourceScreenSize = sourceScreenSize;
}
public static void UpdateLongPressElapsed(float elapsed)
{
LongPressElapsed = elapsed;
}
public static void UpdatePosition(Vector2 position)
{
CurrentPosition = position;
}
public static void AddWaypoint(Vector2 position)
{
// Keep only the most recent waypoints to bound overlay draw cost during long drags
if (_dragWaypoints.Count >= MAX_DRAG_WAYPOINTS)
{
_dragWaypoints.RemoveAt(0);
}
_dragWaypoints.Add(position);
}
public static void RequestExpandAnimation()
{
_pendingExpandAnimation = true;
}
public static void RequestDissipateAnimation()
{
_pendingDissipateAnimation = true;
}
public static bool ConsumePendingExpandAnimation()
{
if (!_pendingExpandAnimation)
{
return false;
}
_pendingExpandAnimation = false;
return true;
}
public static bool ConsumePendingDissipateAnimation()
{
if (!_pendingDissipateAnimation)
{
return false;
}
_pendingDissipateAnimation = false;
return true;
}
public static void Clear()
{
IsActive = false;
Action = default;
CurrentPosition = Vector2.zero;
DragStartPosition = null;
HitGameObjectName = null;
SourceScreenSize = Vector2.zero;
LongPressElapsed = 0f;
_dragWaypoints.Clear();
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 79bc949237a954d0dac73dae3ce9c496
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,14 @@
{
"name": "uLoopMCP.Runtime",
"rootNamespace": "",
"references": [],
"includePlatforms": [],
"excludePlatforms": [],
"allowUnsafeCode": false,
"overrideReferences": false,
"precompiledReferences": [],
"autoReferenced": false,
"defineConstraints": [],
"versionDefines": [],
"noEngineReferences": false
}

View File

@@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: c956a21f824994ef087b6de566690b3d
AssemblyDefinitionImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant: