Skip to content

Instantly share code, notes, and snippets.

@LordNed
Created October 16, 2015 19:55
Show Gist options
  • Select an option

  • Save LordNed/7ccee3c27855efe8d09c to your computer and use it in GitHub Desktop.

Select an option

Save LordNed/7ccee3c27855efe8d09c to your computer and use it in GitHub Desktop.

Revisions

  1. LordNed created this gist Oct 16, 2015.
    303 changes: 303 additions & 0 deletions ConsoleEntry.prefab
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,303 @@
    %YAML 1.1
    %TAG !u! tag:unity3d.com,2011:
    --- !u!1 &121470
    GameObject:
    m_ObjectHideFlags: 0
    m_PrefabParentObject: {fileID: 0}
    m_PrefabInternal: {fileID: 100100000}
    serializedVersion: 4
    m_Component:
    - 224: {fileID: 22423080}
    - 222: {fileID: 22203802}
    - 114: {fileID: 11477746}
    m_Layer: 5
    m_Name: Timestamp
    m_TagString: Untagged
    m_Icon: {fileID: 0}
    m_NavMeshLayer: 0
    m_StaticEditorFlags: 0
    m_IsActive: 1
    --- !u!1 &154374
    GameObject:
    m_ObjectHideFlags: 0
    m_PrefabParentObject: {fileID: 0}
    m_PrefabInternal: {fileID: 100100000}
    serializedVersion: 4
    m_Component:
    - 224: {fileID: 22431972}
    - 222: {fileID: 22262152}
    - 114: {fileID: 11419304}
    m_Layer: 5
    m_Name: OutputText
    m_TagString: Untagged
    m_Icon: {fileID: 0}
    m_NavMeshLayer: 0
    m_StaticEditorFlags: 0
    m_IsActive: 1
    --- !u!1 &176866
    GameObject:
    m_ObjectHideFlags: 0
    m_PrefabParentObject: {fileID: 0}
    m_PrefabInternal: {fileID: 100100000}
    serializedVersion: 4
    m_Component:
    - 224: {fileID: 22485038}
    - 222: {fileID: 22299566}
    - 114: {fileID: 11442334}
    m_Layer: 5
    m_Name: Panel
    m_TagString: Untagged
    m_Icon: {fileID: 0}
    m_NavMeshLayer: 0
    m_StaticEditorFlags: 0
    m_IsActive: 1
    --- !u!1 &187106
    GameObject:
    m_ObjectHideFlags: 0
    m_PrefabParentObject: {fileID: 0}
    m_PrefabInternal: {fileID: 100100000}
    serializedVersion: 4
    m_Component:
    - 224: {fileID: 22454218}
    - 114: {fileID: 11460020}
    - 114: {fileID: 11456854}
    m_Layer: 5
    m_Name: ConsoleEntry
    m_TagString: Untagged
    m_Icon: {fileID: 0}
    m_NavMeshLayer: 0
    m_StaticEditorFlags: 0
    m_IsActive: 1
    --- !u!114 &11419304
    MonoBehaviour:
    m_ObjectHideFlags: 1
    m_PrefabParentObject: {fileID: 0}
    m_PrefabInternal: {fileID: 100100000}
    m_GameObject: {fileID: 154374}
    m_Enabled: 1
    m_EditorHideFlags: 0
    m_Script: {fileID: 708705254, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3}
    m_Name:
    m_EditorClassIdentifier:
    m_Material: {fileID: 0}
    m_Color: {r: .196078435, g: .196078435, b: .196078435, a: 1}
    m_FontData:
    m_Font: {fileID: 10102, guid: 0000000000000000e000000000000000, type: 0}
    m_FontSize: 14
    m_FontStyle: 0
    m_BestFit: 0
    m_MinSize: 10
    m_MaxSize: 40
    m_Alignment: 0
    m_RichText: 1
    m_HorizontalOverflow: 0
    m_VerticalOverflow: 0
    m_LineSpacing: 1
    m_Text: 'Hello world. This is output from the console. Do we want to have the stack
    trace as well?
    <size=10>Pretend this is the stack trace.
    Line one
    Line two.
    Line three. </size>'
    --- !u!114 &11442334
    MonoBehaviour:
    m_ObjectHideFlags: 1
    m_PrefabParentObject: {fileID: 0}
    m_PrefabInternal: {fileID: 100100000}
    m_GameObject: {fileID: 176866}
    m_Enabled: 1
    m_EditorHideFlags: 0
    m_Script: {fileID: -765806418, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3}
    m_Name:
    m_EditorClassIdentifier:
    m_Material: {fileID: 0}
    m_Color: {r: 1, g: 1, b: 1, a: .39199999}
    m_Sprite: {fileID: 10907, guid: 0000000000000000f000000000000000, type: 0}
    m_Type: 1
    m_PreserveAspect: 0
    m_FillCenter: 1
    m_FillMethod: 4
    m_FillAmount: 1
    m_FillClockwise: 1
    m_FillOrigin: 0
    --- !u!114 &11456854
    MonoBehaviour:
    m_ObjectHideFlags: 1
    m_PrefabParentObject: {fileID: 0}
    m_PrefabInternal: {fileID: 100100000}
    m_GameObject: {fileID: 187106}
    m_Enabled: 1
    m_EditorHideFlags: 0
    m_Script: {fileID: 1679637790, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3}
    m_Name:
    m_EditorClassIdentifier:
    m_IgnoreLayout: 0
    m_MinWidth: -1
    m_MinHeight: -1
    m_PreferredWidth: -1
    m_PreferredHeight: 75
    m_FlexibleWidth: -1
    m_FlexibleHeight: -1
    --- !u!114 &11460020
    MonoBehaviour:
    m_ObjectHideFlags: 1
    m_PrefabParentObject: {fileID: 0}
    m_PrefabInternal: {fileID: 100100000}
    m_GameObject: {fileID: 187106}
    m_Enabled: 1
    m_EditorHideFlags: 0
    m_Script: {fileID: 11500000, guid: 5b8ffe36c3fa1eb43ad95cb72d6c79eb, type: 3}
    m_Name:
    m_EditorClassIdentifier:
    m_outputText: {fileID: 11419304}
    m_timestampText: {fileID: 11477746}
    --- !u!114 &11477746
    MonoBehaviour:
    m_ObjectHideFlags: 1
    m_PrefabParentObject: {fileID: 0}
    m_PrefabInternal: {fileID: 100100000}
    m_GameObject: {fileID: 121470}
    m_Enabled: 1
    m_EditorHideFlags: 0
    m_Script: {fileID: 708705254, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3}
    m_Name:
    m_EditorClassIdentifier:
    m_Material: {fileID: 0}
    m_Color: {r: .196078435, g: .196078435, b: .196078435, a: 1}
    m_FontData:
    m_Font: {fileID: 10102, guid: 0000000000000000e000000000000000, type: 0}
    m_FontSize: 12
    m_FontStyle: 0
    m_BestFit: 0
    m_MinSize: 10
    m_MaxSize: 40
    m_Alignment: 8
    m_RichText: 1
    m_HorizontalOverflow: 0
    m_VerticalOverflow: 0
    m_LineSpacing: 1
    m_Text: 5:39am
    --- !u!222 &22203802
    CanvasRenderer:
    m_ObjectHideFlags: 1
    m_PrefabParentObject: {fileID: 0}
    m_PrefabInternal: {fileID: 100100000}
    m_GameObject: {fileID: 121470}
    --- !u!222 &22262152
    CanvasRenderer:
    m_ObjectHideFlags: 1
    m_PrefabParentObject: {fileID: 0}
    m_PrefabInternal: {fileID: 100100000}
    m_GameObject: {fileID: 154374}
    --- !u!222 &22299566
    CanvasRenderer:
    m_ObjectHideFlags: 1
    m_PrefabParentObject: {fileID: 0}
    m_PrefabInternal: {fileID: 100100000}
    m_GameObject: {fileID: 176866}
    --- !u!224 &22423080
    RectTransform:
    m_ObjectHideFlags: 1
    m_PrefabParentObject: {fileID: 0}
    m_PrefabInternal: {fileID: 100100000}
    m_GameObject: {fileID: 121470}
    m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
    m_LocalPosition: {x: 0, y: 0, z: .000128034371}
    m_LocalScale: {x: 1, y: 1, z: 1}
    m_Children: []
    m_Father: {fileID: 22454218}
    m_RootOrder: 2
    m_AnchorMin: {x: 0, y: 0}
    m_AnchorMax: {x: 1, y: 1}
    m_AnchoredPosition: {x: 2.77161598e-05, y: -2.32458115e-05}
    m_SizeDelta: {x: -10, y: -10}
    m_Pivot: {x: .5, y: .5}
    --- !u!224 &22431972
    RectTransform:
    m_ObjectHideFlags: 1
    m_PrefabParentObject: {fileID: 0}
    m_PrefabInternal: {fileID: 100100000}
    m_GameObject: {fileID: 154374}
    m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
    m_LocalPosition: {x: 0, y: 0, z: -.000105019746}
    m_LocalScale: {x: 1, y: 1, z: 1}
    m_Children: []
    m_Father: {fileID: 22454218}
    m_RootOrder: 1
    m_AnchorMin: {x: 0, y: 0}
    m_AnchorMax: {x: 1, y: 1}
    m_AnchoredPosition: {x: 0, y: 0}
    m_SizeDelta: {x: -10, y: -10}
    m_Pivot: {x: .5, y: .5}
    --- !u!224 &22454218
    RectTransform:
    m_ObjectHideFlags: 1
    m_PrefabParentObject: {fileID: 0}
    m_PrefabInternal: {fileID: 100100000}
    m_GameObject: {fileID: 187106}
    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_Children:
    - {fileID: 22485038}
    - {fileID: 22431972}
    - {fileID: 22423080}
    m_Father: {fileID: 0}
    m_RootOrder: 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: .5, y: 1}
    --- !u!224 &22485038
    RectTransform:
    m_ObjectHideFlags: 1
    m_PrefabParentObject: {fileID: 0}
    m_PrefabInternal: {fileID: 100100000}
    m_GameObject: {fileID: 176866}
    m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
    m_LocalPosition: {x: 0, y: 0, z: -1.60931941e-05}
    m_LocalScale: {x: 1, y: 1, z: 1}
    m_Children: []
    m_Father: {fileID: 22454218}
    m_RootOrder: 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: .5, y: .5}
    --- !u!1001 &100100000
    Prefab:
    m_ObjectHideFlags: 1
    serializedVersion: 2
    m_Modification:
    m_TransformParent: {fileID: 0}
    m_Modifications:
    - target: {fileID: 0}
    propertyPath: m_AnchorMin.y
    value: .5
    objectReference: {fileID: 0}
    - target: {fileID: 0}
    propertyPath: m_AnchorMax.y
    value: .5
    objectReference: {fileID: 0}
    - target: {fileID: 0}
    propertyPath: m_Pivot.y
    value: .5
    objectReference: {fileID: 0}
    - target: {fileID: 0}
    propertyPath: m_AnchorMin.x
    value: .5
    objectReference: {fileID: 0}
    - target: {fileID: 0}
    propertyPath: m_AnchorMax.x
    value: .5
    objectReference: {fileID: 0}
    m_RemovedComponents: []
    m_ParentPrefab: {fileID: 0}
    m_RootGameObject: {fileID: 187106}
    m_IsPrefabParent: 1
    66 changes: 66 additions & 0 deletions ConsoleLogger.cs
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,66 @@
    using System;
    using System.Collections.Generic;
    using UnityEngine;
    using UnityEngine.Events;

    public class ConsoleLogEvent : UnityEvent<ConsoleLogger.MessageEntry> { }

    /* This is a singleton that should be placed on an object in the scene which is active all of the time.
    If the gameobject it is on is inactive, it will miss the debug log messages and you'll not be able to see them!
    */
    public class ConsoleLogger : MonoBehaviour
    {
    public struct MessageEntry
    {
    public string ErrorText;
    public string StackTrace;
    public LogType Type;
    public DateTime Time;

    public MessageEntry(string errorText, string stackTrace, LogType type, DateTime time)
    {
    ErrorText = errorText;
    StackTrace = stackTrace;
    Type = type;
    Time = time;
    }
    }

    public static ConsoleLogger Instance;

    public List<MessageEntry> History { get { return m_consoleHistory; } }
    public ConsoleLogEvent OnMessage = new ConsoleLogEvent();

    private List<MessageEntry> m_consoleHistory;

    private void Awake()
    {
    if(Instance != null)
    {
    Debug.LogWarning("Tried to create second instance of ConsoleLogger, destroying duplicate.");
    Destroy(gameObject);
    return;
    }

    Instance = this;
    m_consoleHistory = new List<MessageEntry>();
    }

    private void OnEnable()
    {
    Application.logMessageReceived += OnLogMessageRecieved;
    }

    private void OnDisable()
    {
    Application.logMessageReceived -= OnLogMessageRecieved;
    }

    private void OnLogMessageRecieved(string condition, string stackTrace, LogType type)
    {
    var newEntry = new MessageEntry(condition, stackTrace, type, DateTime.Now);
    m_consoleHistory.Add(newEntry);

    OnMessage.Invoke(newEntry);
    }
    }
    862 changes: 862 additions & 0 deletions SteamVR Controller.prefab
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,862 @@
    %YAML 1.1
    %TAG !u! tag:unity3d.com,2011:
    --- !u!1 &114336
    GameObject:
    m_ObjectHideFlags: 1
    m_PrefabParentObject: {fileID: 0}
    m_PrefabInternal: {fileID: 100100000}
    serializedVersion: 4
    m_Component:
    - 224: {fileID: 22417834}
    - 114: {fileID: 11405790}
    - 114: {fileID: 11439528}
    m_Layer: 5
    m_Name: Content
    m_TagString: Untagged
    m_Icon: {fileID: 0}
    m_NavMeshLayer: 0
    m_StaticEditorFlags: 0
    m_IsActive: 1
    --- !u!1 &114816
    GameObject:
    m_ObjectHideFlags: 1
    m_PrefabParentObject: {fileID: 0}
    m_PrefabInternal: {fileID: 100100000}
    serializedVersion: 4
    m_Component:
    - 224: {fileID: 22419622}
    - 222: {fileID: 22225266}
    - 114: {fileID: 11481512}
    m_Layer: 5
    m_Name: Background
    m_TagString: Untagged
    m_Icon: {fileID: 0}
    m_NavMeshLayer: 0
    m_StaticEditorFlags: 0
    m_IsActive: 1
    --- !u!1 &127524
    GameObject:
    m_ObjectHideFlags: 1
    m_PrefabParentObject: {fileID: 0}
    m_PrefabInternal: {fileID: 100100000}
    serializedVersion: 4
    m_Component:
    - 224: {fileID: 22446476}
    - 223: {fileID: 22367286}
    - 114: {fileID: 11464414}
    m_Layer: 5
    m_Name: DebugPanel
    m_TagString: Untagged
    m_Icon: {fileID: 0}
    m_NavMeshLayer: 0
    m_StaticEditorFlags: 0
    m_IsActive: 1
    --- !u!1 &142154
    GameObject:
    m_ObjectHideFlags: 0
    m_PrefabParentObject: {fileID: 0}
    m_PrefabInternal: {fileID: 100100000}
    serializedVersion: 4
    m_Component:
    - 4: {fileID: 488580}
    m_Layer: 0
    m_Name: GrabTip
    m_TagString: Untagged
    m_Icon: {fileID: 0}
    m_NavMeshLayer: 0
    m_StaticEditorFlags: 0
    m_IsActive: 1
    --- !u!1 &144022
    GameObject:
    m_ObjectHideFlags: 0
    m_PrefabParentObject: {fileID: 0}
    m_PrefabInternal: {fileID: 100100000}
    serializedVersion: 4
    m_Component:
    - 4: {fileID: 413742}
    - 114: {fileID: 11464704}
    m_Layer: 0
    m_Name: DebugConsole
    m_TagString: Untagged
    m_Icon: {fileID: 0}
    m_NavMeshLayer: 0
    m_StaticEditorFlags: 0
    m_IsActive: 1
    --- !u!1 &145000
    GameObject:
    m_ObjectHideFlags: 1
    m_PrefabParentObject: {fileID: 0}
    m_PrefabInternal: {fileID: 100100000}
    serializedVersion: 4
    m_Component:
    - 224: {fileID: 22473968}
    - 222: {fileID: 22251734}
    - 114: {fileID: 11499134}
    - 114: {fileID: 11421930}
    m_Layer: 5
    m_Name: Scrollbar
    m_TagString: Untagged
    m_Icon: {fileID: 0}
    m_NavMeshLayer: 0
    m_StaticEditorFlags: 0
    m_IsActive: 1
    --- !u!1 &146874
    GameObject:
    m_ObjectHideFlags: 1
    m_PrefabParentObject: {fileID: 0}
    m_PrefabInternal: {fileID: 100100000}
    serializedVersion: 4
    m_Component:
    - 4: {fileID: 426298}
    - 33: {fileID: 3324900}
    - 23: {fileID: 2336154}
    m_Layer: 0
    m_Name: polySurface10
    m_TagString: Untagged
    m_Icon: {fileID: 0}
    m_NavMeshLayer: 0
    m_StaticEditorFlags: 0
    m_IsActive: 1
    --- !u!1 &150298
    GameObject:
    m_ObjectHideFlags: 1
    m_PrefabParentObject: {fileID: 0}
    m_PrefabInternal: {fileID: 100100000}
    serializedVersion: 4
    m_Component:
    - 4: {fileID: 431144}
    - 33: {fileID: 3378106}
    - 23: {fileID: 2346686}
    m_Layer: 0
    m_Name: Sphere
    m_TagString: Untagged
    m_Icon: {fileID: 0}
    m_NavMeshLayer: 0
    m_StaticEditorFlags: 0
    m_IsActive: 1
    --- !u!1 &159552
    GameObject:
    m_ObjectHideFlags: 1
    m_PrefabParentObject: {fileID: 0}
    m_PrefabInternal: {fileID: 100100000}
    serializedVersion: 4
    m_Component:
    - 224: {fileID: 22480654}
    - 222: {fileID: 22265446}
    - 114: {fileID: 11477126}
    m_Layer: 5
    m_Name: Handle
    m_TagString: Untagged
    m_Icon: {fileID: 0}
    m_NavMeshLayer: 0
    m_StaticEditorFlags: 0
    m_IsActive: 1
    --- !u!1 &168472
    GameObject:
    m_ObjectHideFlags: 0
    m_PrefabParentObject: {fileID: 0}
    m_PrefabInternal: {fileID: 100100000}
    serializedVersion: 4
    m_Component:
    - 4: {fileID: 461692}
    m_Layer: 0
    m_Name: mesh
    m_TagString: Untagged
    m_Icon: {fileID: 0}
    m_NavMeshLayer: 0
    m_StaticEditorFlags: 0
    m_IsActive: 1
    --- !u!1 &188860
    GameObject:
    m_ObjectHideFlags: 1
    m_PrefabParentObject: {fileID: 0}
    m_PrefabInternal: {fileID: 100100000}
    serializedVersion: 4
    m_Component:
    - 224: {fileID: 22460348}
    - 114: {fileID: 11456248}
    - 222: {fileID: 22256016}
    - 114: {fileID: 11431504}
    - 114: {fileID: 11499664}
    m_Layer: 5
    m_Name: ScrollRect
    m_TagString: Untagged
    m_Icon: {fileID: 0}
    m_NavMeshLayer: 0
    m_StaticEditorFlags: 0
    m_IsActive: 1
    --- !u!1 &192988
    GameObject:
    m_ObjectHideFlags: 0
    m_PrefabParentObject: {fileID: 0}
    m_PrefabInternal: {fileID: 100100000}
    serializedVersion: 4
    m_Component:
    - 4: {fileID: 444192}
    - 114: {fileID: 11459012}
    m_Layer: 0
    m_Name: SteamVR Controller
    m_TagString: Untagged
    m_Icon: {fileID: 0}
    m_NavMeshLayer: 0
    m_StaticEditorFlags: 0
    m_IsActive: 1
    --- !u!1 &195098
    GameObject:
    m_ObjectHideFlags: 1
    m_PrefabParentObject: {fileID: 0}
    m_PrefabInternal: {fileID: 100100000}
    serializedVersion: 4
    m_Component:
    - 224: {fileID: 22493968}
    m_Layer: 5
    m_Name: Sliding Area
    m_TagString: Untagged
    m_Icon: {fileID: 0}
    m_NavMeshLayer: 0
    m_StaticEditorFlags: 0
    m_IsActive: 1
    --- !u!4 &413742
    Transform:
    m_ObjectHideFlags: 1
    m_PrefabParentObject: {fileID: 0}
    m_PrefabInternal: {fileID: 100100000}
    m_GameObject: {fileID: 144022}
    m_LocalRotation: {x: .707106829, y: 0, z: 0, w: .707106709}
    m_LocalPosition: {x: .219999999, y: 0, z: -.0900000036}
    m_LocalScale: {x: .000500000024, y: .000500000024, z: .000500000024}
    m_Children:
    - {fileID: 22446476}
    m_Father: {fileID: 444192}
    m_RootOrder: 0
    --- !u!4 &426298
    Transform:
    m_ObjectHideFlags: 1
    m_PrefabParentObject: {fileID: 0}
    m_PrefabInternal: {fileID: 100100000}
    m_GameObject: {fileID: 146874}
    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_Children: []
    m_Father: {fileID: 461692}
    m_RootOrder: 0
    --- !u!4 &431144
    Transform:
    m_ObjectHideFlags: 1
    m_PrefabParentObject: {fileID: 0}
    m_PrefabInternal: {fileID: 100100000}
    m_GameObject: {fileID: 150298}
    m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
    m_LocalPosition: {x: 0, y: 0, z: 0}
    m_LocalScale: {x: .0199999996, y: .0199999996, z: .0199999996}
    m_Children: []
    m_Father: {fileID: 488580}
    m_RootOrder: 0
    --- !u!4 &444192
    Transform:
    m_ObjectHideFlags: 1
    m_PrefabParentObject: {fileID: 0}
    m_PrefabInternal: {fileID: 100100000}
    m_GameObject: {fileID: 192988}
    m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
    m_LocalPosition: {x: .5, y: .5, z: -.5}
    m_LocalScale: {x: 1, y: 1, z: 1}
    m_Children:
    - {fileID: 413742}
    - {fileID: 461692}
    - {fileID: 488580}
    m_Father: {fileID: 0}
    m_RootOrder: 0
    --- !u!4 &461692
    Transform:
    m_ObjectHideFlags: 1
    m_PrefabParentObject: {fileID: 0}
    m_PrefabInternal: {fileID: 100100000}
    m_GameObject: {fileID: 168472}
    m_LocalRotation: {x: 0, y: 1, z: 0, w: -1.62920685e-07}
    m_LocalPosition: {x: 0, y: 0, z: 0}
    m_LocalScale: {x: 1, y: 1, z: 1}
    m_Children:
    - {fileID: 426298}
    m_Father: {fileID: 444192}
    m_RootOrder: 1
    --- !u!4 &488580
    Transform:
    m_ObjectHideFlags: 1
    m_PrefabParentObject: {fileID: 0}
    m_PrefabInternal: {fileID: 100100000}
    m_GameObject: {fileID: 142154}
    m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
    m_LocalPosition: {x: 0, y: -.0168600008, z: .0785999969}
    m_LocalScale: {x: 1, y: 1, z: 1}
    m_Children:
    - {fileID: 431144}
    m_Father: {fileID: 444192}
    m_RootOrder: 2
    --- !u!23 &2336154
    MeshRenderer:
    m_ObjectHideFlags: 1
    m_PrefabParentObject: {fileID: 0}
    m_PrefabInternal: {fileID: 100100000}
    m_GameObject: {fileID: 146874}
    m_Enabled: 1
    m_CastShadows: 1
    m_ReceiveShadows: 1
    m_Materials:
    - {fileID: 2100000, guid: 3c7bde36bf020924495f657b425ae076, type: 2}
    m_SubsetIndices:
    m_StaticBatchRoot: {fileID: 0}
    m_UseLightProbes: 1
    m_ReflectionProbeUsage: 1
    m_ProbeAnchor: {fileID: 0}
    m_ScaleInLightmap: 1
    m_PreserveUVs: 0
    m_ImportantGI: 0
    m_AutoUVMaxDistance: .5
    m_AutoUVMaxAngle: 89
    m_LightmapParameters: {fileID: 0}
    m_SortingLayerID: 0
    m_SortingOrder: 0
    --- !u!23 &2346686
    MeshRenderer:
    m_ObjectHideFlags: 1
    m_PrefabParentObject: {fileID: 0}
    m_PrefabInternal: {fileID: 100100000}
    m_GameObject: {fileID: 150298}
    m_Enabled: 1
    m_CastShadows: 1
    m_ReceiveShadows: 1
    m_Materials:
    - {fileID: 2100000, guid: c8a01ba0be2d74744ac7d8077aad259d, type: 2}
    m_SubsetIndices:
    m_StaticBatchRoot: {fileID: 0}
    m_UseLightProbes: 1
    m_ReflectionProbeUsage: 1
    m_ProbeAnchor: {fileID: 0}
    m_ScaleInLightmap: 1
    m_PreserveUVs: 1
    m_ImportantGI: 0
    m_AutoUVMaxDistance: .5
    m_AutoUVMaxAngle: 89
    m_LightmapParameters: {fileID: 0}
    m_SortingLayerID: 0
    m_SortingOrder: 0
    --- !u!33 &3324900
    MeshFilter:
    m_ObjectHideFlags: 1
    m_PrefabParentObject: {fileID: 0}
    m_PrefabInternal: {fileID: 100100000}
    m_GameObject: {fileID: 146874}
    m_Mesh: {fileID: 4300000, guid: 4b84c5488eacee94dbe463a65c742cc8, type: 3}
    --- !u!33 &3378106
    MeshFilter:
    m_ObjectHideFlags: 1
    m_PrefabParentObject: {fileID: 0}
    m_PrefabInternal: {fileID: 100100000}
    m_GameObject: {fileID: 150298}
    m_Mesh: {fileID: 10207, guid: 0000000000000000e000000000000000, type: 0}
    --- !u!114 &11405790
    MonoBehaviour:
    m_ObjectHideFlags: 1
    m_PrefabParentObject: {fileID: 0}
    m_PrefabInternal: {fileID: 100100000}
    m_GameObject: {fileID: 114336}
    m_Enabled: 1
    m_EditorHideFlags: 0
    m_Script: {fileID: 1297475563, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3}
    m_Name:
    m_EditorClassIdentifier:
    m_Padding:
    m_Left: 0
    m_Right: 0
    m_Top: 0
    m_Bottom: 0
    m_ChildAlignment: 1
    m_Spacing: 0
    m_ChildForceExpandWidth: 1
    m_ChildForceExpandHeight: 1
    --- !u!114 &11421930
    MonoBehaviour:
    m_ObjectHideFlags: 1
    m_PrefabParentObject: {fileID: 0}
    m_PrefabInternal: {fileID: 100100000}
    m_GameObject: {fileID: 145000}
    m_Enabled: 1
    m_EditorHideFlags: 0
    m_Script: {fileID: -2061169968, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3}
    m_Name:
    m_EditorClassIdentifier:
    m_Navigation:
    m_Mode: 0
    m_SelectOnUp: {fileID: 0}
    m_SelectOnDown: {fileID: 0}
    m_SelectOnLeft: {fileID: 0}
    m_SelectOnRight: {fileID: 0}
    m_Transition: 1
    m_Colors:
    m_NormalColor: {r: 1, g: 1, b: 1, a: 1}
    m_HighlightedColor: {r: .960784316, g: .960784316, b: .960784316, a: 1}
    m_PressedColor: {r: .784313738, g: .784313738, b: .784313738, a: 1}
    m_DisabledColor: {r: .784313738, g: .784313738, b: .784313738, a: .501960814}
    m_ColorMultiplier: 1
    m_FadeDuration: .100000001
    m_SpriteState:
    m_HighlightedSprite: {fileID: 0}
    m_PressedSprite: {fileID: 0}
    m_DisabledSprite: {fileID: 0}
    m_AnimationTriggers:
    m_NormalTrigger: Normal
    m_HighlightedTrigger: Highlighted
    m_PressedTrigger: Pressed
    m_DisabledTrigger: Disabled
    m_Interactable: 1
    m_TargetGraphic: {fileID: 11477126}
    m_HandleRect: {fileID: 22480654}
    m_Direction: 3
    m_Value: 1
    m_Size: 1
    m_NumberOfSteps: 0
    m_OnValueChanged:
    m_PersistentCalls:
    m_Calls: []
    m_TypeName: UnityEngine.UI.Scrollbar+ScrollEvent, UnityEngine.UI, Version=1.0.0.0,
    Culture=neutral, PublicKeyToken=null
    --- !u!114 &11431504
    MonoBehaviour:
    m_ObjectHideFlags: 1
    m_PrefabParentObject: {fileID: 0}
    m_PrefabInternal: {fileID: 100100000}
    m_GameObject: {fileID: 188860}
    m_Enabled: 1
    m_EditorHideFlags: 0
    m_Script: {fileID: -765806418, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3}
    m_Name:
    m_EditorClassIdentifier:
    m_Material: {fileID: 0}
    m_Color: {r: 1, g: 1, b: 1, a: 1}
    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
    --- !u!114 &11439528
    MonoBehaviour:
    m_ObjectHideFlags: 1
    m_PrefabParentObject: {fileID: 0}
    m_PrefabInternal: {fileID: 100100000}
    m_GameObject: {fileID: 114336}
    m_Enabled: 1
    m_EditorHideFlags: 0
    m_Script: {fileID: 1741964061, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3}
    m_Name:
    m_EditorClassIdentifier:
    m_HorizontalFit: 0
    m_VerticalFit: 2
    --- !u!114 &11456248
    MonoBehaviour:
    m_ObjectHideFlags: 1
    m_PrefabParentObject: {fileID: 0}
    m_PrefabInternal: {fileID: 100100000}
    m_GameObject: {fileID: 188860}
    m_Enabled: 1
    m_EditorHideFlags: 0
    m_Script: {fileID: 1367256648, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3}
    m_Name:
    m_EditorClassIdentifier:
    m_Content: {fileID: 22417834}
    m_Horizontal: 0
    m_Vertical: 1
    m_MovementType: 2
    m_Elasticity: .100000001
    m_Inertia: 1
    m_DecelerationRate: .135000005
    m_ScrollSensitivity: 10
    m_HorizontalScrollbar: {fileID: 0}
    m_VerticalScrollbar: {fileID: 11421930}
    m_OnValueChanged:
    m_PersistentCalls:
    m_Calls: []
    m_TypeName: UnityEngine.UI.ScrollRect+ScrollRectEvent, UnityEngine.UI, Version=1.0.0.0,
    Culture=neutral, PublicKeyToken=null
    --- !u!114 &11459012
    MonoBehaviour:
    m_ObjectHideFlags: 1
    m_PrefabParentObject: {fileID: 0}
    m_PrefabInternal: {fileID: 100100000}
    m_GameObject: {fileID: 192988}
    m_Enabled: 1
    m_EditorHideFlags: 0
    m_Script: {fileID: 11500000, guid: 7e039363f7f166a44a80822c05c766ee, type: 3}
    m_Name:
    m_EditorClassIdentifier:
    MenuButtonClicked:
    m_PersistentCalls:
    m_Calls: []
    m_TypeName: PuzzleBox.ControllerEvent, Assembly-CSharp, Version=0.0.0.0, Culture=neutral,
    PublicKeyToken=null
    MenuButtonReleased:
    m_PersistentCalls:
    m_Calls: []
    m_TypeName: PuzzleBox.ControllerEvent, Assembly-CSharp, Version=0.0.0.0, Culture=neutral,
    PublicKeyToken=null
    TriggerClicked:
    m_PersistentCalls:
    m_Calls: []
    m_TypeName: PuzzleBox.ControllerEvent, Assembly-CSharp, Version=0.0.0.0, Culture=neutral,
    PublicKeyToken=null
    TriggerReleased:
    m_PersistentCalls:
    m_Calls: []
    m_TypeName: PuzzleBox.ControllerEvent, Assembly-CSharp, Version=0.0.0.0, Culture=neutral,
    PublicKeyToken=null
    TriggerChanged:
    m_PersistentCalls:
    m_Calls: []
    m_TypeName: PuzzleBox.ControllerTriggerEvent, Assembly-CSharp, Version=0.0.0.0,
    Culture=neutral, PublicKeyToken=null
    HairTriggerClicked:
    m_PersistentCalls:
    m_Calls: []
    m_TypeName: PuzzleBox.ControllerEvent, Assembly-CSharp, Version=0.0.0.0, Culture=neutral,
    PublicKeyToken=null
    HairTriggerReleased:
    m_PersistentCalls:
    m_Calls: []
    m_TypeName: PuzzleBox.ControllerEvent, Assembly-CSharp, Version=0.0.0.0, Culture=neutral,
    PublicKeyToken=null
    PadButtonClicked:
    m_PersistentCalls:
    m_Calls: []
    m_TypeName: PuzzleBox.ControllerEvent, Assembly-CSharp, Version=0.0.0.0, Culture=neutral,
    PublicKeyToken=null
    PadButtonReleased:
    m_PersistentCalls:
    m_Calls: []
    m_TypeName: PuzzleBox.ControllerEvent, Assembly-CSharp, Version=0.0.0.0, Culture=neutral,
    PublicKeyToken=null
    PadTouchClicked:
    m_PersistentCalls:
    m_Calls: []
    m_TypeName: PuzzleBox.ControllerEvent, Assembly-CSharp, Version=0.0.0.0, Culture=neutral,
    PublicKeyToken=null
    PadTouchReleased:
    m_PersistentCalls:
    m_Calls: []
    m_TypeName: PuzzleBox.ControllerEvent, Assembly-CSharp, Version=0.0.0.0, Culture=neutral,
    PublicKeyToken=null
    PadTouchMoved:
    m_PersistentCalls:
    m_Calls: []
    m_TypeName: PuzzleBox.ControllerPadEvent, Assembly-CSharp, Version=0.0.0.0, Culture=neutral,
    PublicKeyToken=null
    GripClicked:
    m_PersistentCalls:
    m_Calls: []
    m_TypeName: PuzzleBox.ControllerEvent, Assembly-CSharp, Version=0.0.0.0, Culture=neutral,
    PublicKeyToken=null
    GripReleased:
    m_PersistentCalls:
    m_Calls: []
    m_TypeName: PuzzleBox.ControllerEvent, Assembly-CSharp, Version=0.0.0.0, Culture=neutral,
    PublicKeyToken=null
    HairTriggerThreshold: .100000001
    m_controllerTip: {fileID: 488580}
    --- !u!114 &11464414
    MonoBehaviour:
    m_ObjectHideFlags: 1
    m_PrefabParentObject: {fileID: 0}
    m_PrefabInternal: {fileID: 100100000}
    m_GameObject: {fileID: 127524}
    m_Enabled: 1
    m_EditorHideFlags: 0
    m_Script: {fileID: 1980459831, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3}
    m_Name:
    m_EditorClassIdentifier:
    m_UiScaleMode: 0
    m_ReferencePixelsPerUnit: 100
    m_ScaleFactor: 1
    m_ReferenceResolution: {x: 800, y: 600}
    m_ScreenMatchMode: 0
    m_MatchWidthOrHeight: 0
    m_PhysicalUnit: 3
    m_FallbackScreenDPI: 96
    m_DefaultSpriteDPI: 96
    m_DynamicPixelsPerUnit: 1
    --- !u!114 &11464704
    MonoBehaviour:
    m_ObjectHideFlags: 1
    m_PrefabParentObject: {fileID: 0}
    m_PrefabInternal: {fileID: 100100000}
    m_GameObject: {fileID: 144022}
    m_Enabled: 1
    m_EditorHideFlags: 0
    m_Script: {fileID: 11500000, guid: be80ae908a740e7489f9bd1f3ce4d9dd, type: 3}
    m_Name:
    m_EditorClassIdentifier:
    m_entryPrefab: {fileID: 11460020, guid: de8e4472d245b4349877db8db2550576, type: 2}
    m_scrollView: {fileID: 11456248}
    m_debugPanel: {fileID: 127524}
    --- !u!114 &11477126
    MonoBehaviour:
    m_ObjectHideFlags: 1
    m_PrefabParentObject: {fileID: 0}
    m_PrefabInternal: {fileID: 100100000}
    m_GameObject: {fileID: 159552}
    m_Enabled: 1
    m_EditorHideFlags: 0
    m_Script: {fileID: -765806418, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3}
    m_Name:
    m_EditorClassIdentifier:
    m_Material: {fileID: 0}
    m_Color: {r: 1, g: 1, b: 1, a: 1}
    m_Sprite: {fileID: 10905, guid: 0000000000000000f000000000000000, type: 0}
    m_Type: 1
    m_PreserveAspect: 0
    m_FillCenter: 1
    m_FillMethod: 4
    m_FillAmount: 1
    m_FillClockwise: 1
    m_FillOrigin: 0
    --- !u!114 &11481512
    MonoBehaviour:
    m_ObjectHideFlags: 1
    m_PrefabParentObject: {fileID: 0}
    m_PrefabInternal: {fileID: 100100000}
    m_GameObject: {fileID: 114816}
    m_Enabled: 1
    m_EditorHideFlags: 0
    m_Script: {fileID: -765806418, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3}
    m_Name:
    m_EditorClassIdentifier:
    m_Material: {fileID: 0}
    m_Color: {r: 1, g: 1, b: 1, a: .746999979}
    m_Sprite: {fileID: 10907, guid: 0000000000000000f000000000000000, type: 0}
    m_Type: 1
    m_PreserveAspect: 0
    m_FillCenter: 1
    m_FillMethod: 4
    m_FillAmount: 1
    m_FillClockwise: 1
    m_FillOrigin: 0
    --- !u!114 &11499134
    MonoBehaviour:
    m_ObjectHideFlags: 1
    m_PrefabParentObject: {fileID: 0}
    m_PrefabInternal: {fileID: 100100000}
    m_GameObject: {fileID: 145000}
    m_Enabled: 1
    m_EditorHideFlags: 0
    m_Script: {fileID: -765806418, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3}
    m_Name:
    m_EditorClassIdentifier:
    m_Material: {fileID: 0}
    m_Color: {r: 1, g: 1, b: 1, a: 1}
    m_Sprite: {fileID: 10907, guid: 0000000000000000f000000000000000, type: 0}
    m_Type: 1
    m_PreserveAspect: 0
    m_FillCenter: 1
    m_FillMethod: 4
    m_FillAmount: 1
    m_FillClockwise: 1
    m_FillOrigin: 0
    --- !u!114 &11499664
    MonoBehaviour:
    m_ObjectHideFlags: 1
    m_PrefabParentObject: {fileID: 0}
    m_PrefabInternal: {fileID: 100100000}
    m_GameObject: {fileID: 188860}
    m_Enabled: 1
    m_EditorHideFlags: 0
    m_Script: {fileID: -1200242548, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3}
    m_Name:
    m_EditorClassIdentifier:
    m_ShowMaskGraphic: 0
    --- !u!222 &22225266
    CanvasRenderer:
    m_ObjectHideFlags: 1
    m_PrefabParentObject: {fileID: 0}
    m_PrefabInternal: {fileID: 100100000}
    m_GameObject: {fileID: 114816}
    --- !u!222 &22251734
    CanvasRenderer:
    m_ObjectHideFlags: 1
    m_PrefabParentObject: {fileID: 0}
    m_PrefabInternal: {fileID: 100100000}
    m_GameObject: {fileID: 145000}
    --- !u!222 &22256016
    CanvasRenderer:
    m_ObjectHideFlags: 1
    m_PrefabParentObject: {fileID: 0}
    m_PrefabInternal: {fileID: 100100000}
    m_GameObject: {fileID: 188860}
    --- !u!222 &22265446
    CanvasRenderer:
    m_ObjectHideFlags: 1
    m_PrefabParentObject: {fileID: 0}
    m_PrefabInternal: {fileID: 100100000}
    m_GameObject: {fileID: 159552}
    --- !u!223 &22367286
    Canvas:
    m_ObjectHideFlags: 1
    m_PrefabParentObject: {fileID: 0}
    m_PrefabInternal: {fileID: 100100000}
    m_GameObject: {fileID: 127524}
    m_Enabled: 1
    serializedVersion: 2
    m_RenderMode: 2
    m_Camera: {fileID: 0}
    m_PlaneDistance: 100
    m_PixelPerfect: 0
    m_ReceivesEvents: 1
    m_OverrideSorting: 0
    m_OverridePixelPerfect: 0
    m_SortingLayerID: 0
    m_SortingOrder: 0
    --- !u!224 &22417834
    RectTransform:
    m_ObjectHideFlags: 1
    m_PrefabParentObject: {fileID: 0}
    m_PrefabInternal: {fileID: 100100000}
    m_GameObject: {fileID: 114336}
    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_Children: []
    m_Father: {fileID: 22460348}
    m_RootOrder: 0
    m_AnchorMin: {x: 0, y: 1}
    m_AnchorMax: {x: 1, y: 1}
    m_AnchoredPosition: {x: -12.5, y: 0}
    m_SizeDelta: {x: -25, y: 0}
    m_Pivot: {x: .5, y: 1}
    --- !u!224 &22419622
    RectTransform:
    m_ObjectHideFlags: 1
    m_PrefabParentObject: {fileID: 0}
    m_PrefabInternal: {fileID: 100100000}
    m_GameObject: {fileID: 114816}
    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_Children: []
    m_Father: {fileID: 22446476}
    m_RootOrder: 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: .5, y: .5}
    --- !u!224 &22446476
    RectTransform:
    m_ObjectHideFlags: 1
    m_PrefabParentObject: {fileID: 0}
    m_PrefabInternal: {fileID: 100100000}
    m_GameObject: {fileID: 127524}
    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_Children:
    - {fileID: 22419622}
    - {fileID: 22460348}
    m_Father: {fileID: 413742}
    m_RootOrder: 0
    m_AnchorMin: {x: 0, y: 0}
    m_AnchorMax: {x: 0, y: 0}
    m_AnchoredPosition: {x: 0, y: 0}
    m_SizeDelta: {x: 650, y: 450}
    m_Pivot: {x: .5, y: .5}
    --- !u!224 &22460348
    RectTransform:
    m_ObjectHideFlags: 1
    m_PrefabParentObject: {fileID: 0}
    m_PrefabInternal: {fileID: 100100000}
    m_GameObject: {fileID: 188860}
    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_Children:
    - {fileID: 22417834}
    - {fileID: 22473968}
    m_Father: {fileID: 22446476}
    m_RootOrder: 1
    m_AnchorMin: {x: 0, y: 0}
    m_AnchorMax: {x: 1, y: 1}
    m_AnchoredPosition: {x: 0, y: 0}
    m_SizeDelta: {x: -10, y: -10}
    m_Pivot: {x: .5, y: .5}
    --- !u!224 &22473968
    RectTransform:
    m_ObjectHideFlags: 1
    m_PrefabParentObject: {fileID: 0}
    m_PrefabInternal: {fileID: 100100000}
    m_GameObject: {fileID: 145000}
    m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
    m_LocalPosition: {x: 0, y: 0, z: .000119209282}
    m_LocalScale: {x: 1, y: 1, z: 1}
    m_Children:
    - {fileID: 22493968}
    m_Father: {fileID: 22460348}
    m_RootOrder: 1
    m_AnchorMin: {x: 1, y: 0}
    m_AnchorMax: {x: 1, y: 1}
    m_AnchoredPosition: {x: 4.99999189, y: 0}
    m_SizeDelta: {x: 20, y: 10}
    m_Pivot: {x: 1, y: .5}
    --- !u!224 &22480654
    RectTransform:
    m_ObjectHideFlags: 1
    m_PrefabParentObject: {fileID: 0}
    m_PrefabInternal: {fileID: 100100000}
    m_GameObject: {fileID: 159552}
    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_Children: []
    m_Father: {fileID: 22493968}
    m_RootOrder: 0
    m_AnchorMin: {x: 0, y: 0}
    m_AnchorMax: {x: 0, y: 0}
    m_AnchoredPosition: {x: 0, y: 0}
    m_SizeDelta: {x: 20, y: 20}
    m_Pivot: {x: .5, y: .5}
    --- !u!224 &22493968
    RectTransform:
    m_ObjectHideFlags: 1
    m_PrefabParentObject: {fileID: 0}
    m_PrefabInternal: {fileID: 100100000}
    m_GameObject: {fileID: 195098}
    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_Children:
    - {fileID: 22480654}
    m_Father: {fileID: 22473968}
    m_RootOrder: 0
    m_AnchorMin: {x: 0, y: 0}
    m_AnchorMax: {x: 1, y: 1}
    m_AnchoredPosition: {x: 0, y: 0}
    m_SizeDelta: {x: -20, y: -20}
    m_Pivot: {x: .5, y: .5}
    --- !u!1001 &100100000
    Prefab:
    m_ObjectHideFlags: 1
    serializedVersion: 2
    m_Modification:
    m_TransformParent: {fileID: 0}
    m_Modifications:
    - target: {fileID: 0}
    propertyPath: m_controllerTip
    value:
    objectReference: {fileID: 488580}
    - target: {fileID: 0}
    propertyPath: m_Name
    value: mesh
    objectReference: {fileID: 0}
    m_RemovedComponents: []
    m_ParentPrefab: {fileID: 0}
    m_RootGameObject: {fileID: 192988}
    m_IsPrefabParent: 1
    124 changes: 124 additions & 0 deletions UIConsoleViewer.cs
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,124 @@
    using PuzzleBox;
    using System.Collections.Generic;
    using UnityEngine;
    using UnityEngine.UI;

    /* This one actually listens to the events broadcasted by the ConsoleLogger script above. */
    public class UIConsoleViewer : MonoBehaviour
    {
    [SerializeField] private UIConsoleEntry m_entryPrefab;
    [SerializeField] private ScrollRect m_scrollView;
    [SerializeField] private GameObject m_debugPanel;

    private VRController m_controller;
    private bool m_consoleIsOpen;
    private List<UIConsoleEntry> m_entryList;

    private GameObject m_dockedPanelRoot;

    private void Start()
    {
    m_controller = GetComponentInParent<VRController>();
    m_entryList = new List<UIConsoleEntry>();

    foreach (var entry in ConsoleLogger.Instance.History)
    LogMessage(entry);

    HideConsole();
    m_dockedPanelRoot = new GameObject("UIConsoleViewer::DockedPanel");
    }

    private void OnEnable()
    {
    ConsoleLogger.Instance.OnMessage.AddListener(LogMessage);
    }

    private void OnDisable()
    {
    ConsoleLogger.Instance.OnMessage.RemoveListener(LogMessage);
    }

    private void LogMessage(ConsoleLogger.MessageEntry entry)
    {
    // We're only going to keep a history of the last 50 messages. If we're over that, we
    // re-use the oldest message.
    UIConsoleEntry uiEntry = null;
    if (m_entryList.Count < 50)
    {
    uiEntry = (UIConsoleEntry)Instantiate(m_entryPrefab);
    uiEntry.transform.SetParent(m_scrollView.content, false);
    }
    else
    {
    uiEntry = m_entryList[0];
    m_entryList.RemoveAt(0);
    }

    uiEntry.SetText(entry);

    // Set us as the first sibling so we're bumped to the top of the list.
    uiEntry.transform.SetAsFirstSibling();
    m_entryList.Add(uiEntry);

    if (entry.Type != LogType.Log)
    ShowConsole();
    }

    private void Update()
    {
    if(m_controller.GetGripDown())
    {
    if(m_consoleIsOpen)
    HideConsole();
    else
    ShowConsole();
    }

    if (!m_consoleIsOpen)
    return;

    if(m_controller.GetMenuButtonDown())
    {
    // If they push the menu button while the console is open, toggle the snap state.
    if (m_debugPanel.transform.parent == transform)
    {
    m_debugPanel.transform.SetParent(m_dockedPanelRoot.transform, true);
    }
    else
    {
    ParentDebugPanel();
    }
    }

    m_scrollView.verticalScrollbar.value -= m_controller.PadDelta.y / 2f;
    }

    private void ShowConsole()
    {
    if (m_debugPanel.activeSelf)
    return;

    // Any time the console is shown, re-parent it as our child so it re-snaps to the controller.
    ParentDebugPanel();

    m_debugPanel.SetActive(true);
    m_consoleIsOpen = true;
    }

    private void HideConsole()
    {
    if (!m_debugPanel.activeSelf)
    return;

    m_debugPanel.SetActive(false);
    m_consoleIsOpen = false;
    }

    private void ParentDebugPanel()
    {
    m_debugPanel.transform.SetParent(transform, false);
    m_debugPanel.transform.localPosition = Vector3.zero;
    m_debugPanel.transform.localScale = Vector3.one;
    m_debugPanel.transform.localRotation = Quaternion.identity;
    }
    }
    605 changes: 605 additions & 0 deletions VRController.cs
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,605 @@
    using UnityEngine;
    using System.Collections;
    using UnityEngine.Events;
    using Valve.VR;

    namespace PuzzleBox
    {
    [System.Serializable]
    public class ControllerEvent : UnityEvent<VRController> { }

    [System.Serializable]
    public class ControllerPadEvent : UnityEvent<Vector2> { }

    [System.Serializable]
    public class ControllerTriggerEvent : UnityEvent<float> { }

    /* Custom implementation of the SteamVR_Controller meant for the HTCVive that has a more Unity-like API. It's to serve as code
    reference for the UIConsoleViewer which requires a few of the functions from it. */
    public class VRController : MonoBehaviour
    {
    /// <summary>
    /// Which hand is this controller being held in. Can be used for controls
    /// that should always show up on left hand, etc.
    /// </summary>
    public enum HandSides
    {
    Invalid = 0,
    Right,
    Left
    }

    public enum Button
    {
    Invalid = 0,
    Trigger,
    HairTrigger,
    PadTouch,
    PadButton,
    Menu,
    Grip
    }

    /// <summary> Called when the large button on handle is pressed down. </summary>
    public ControllerEvent MenuButtonClicked = new ControllerEvent();

    /// <summary> Called when the large button on handle is released. </summary>
    public ControllerEvent MenuButtonReleased = new ControllerEvent();

    /// <summary> Called when the trigger button goes over the threshold when starting to be pressed. </summary>
    public ControllerEvent TriggerClicked = new ControllerEvent();

    /// <summary> Called when the trigger button goes under the threshold when being released. </summary>
    public ControllerEvent TriggerReleased = new ControllerEvent();

    /// <summary> Called when the trigger value changes, provides delta value of trigger. </summary>
    public ControllerTriggerEvent TriggerChanged = new ControllerTriggerEvent();

    /// <summary> Called when the trigger button goes over the <see cref="HairTriggerThreshold"/>. </summary>
    public ControllerEvent HairTriggerClicked = new ControllerEvent();

    /// <summary> Called when the trigger button goes under the <see cref="HairTriggerThreshold"/>. </summary>
    public ControllerEvent HairTriggerReleased = new ControllerEvent();

    /// <summary> Called when the touchpad button is fully pressed (makes a click). </summary>
    public ControllerEvent PadButtonClicked = new ControllerEvent();

    /// <summary> Called when the touchpad button is released (makes a click). </summary>
    public ControllerEvent PadButtonReleased = new ControllerEvent();

    /// <summary> Called when the user starts touching the touchpad (not a full click, just touch). </summary>
    public ControllerEvent PadTouchClicked = new ControllerEvent();

    /// <summary> Called when the user stops touching the touchpad. </summary>
    public ControllerEvent PadTouchReleased = new ControllerEvent();

    /// <summary> Called when the user changes position on the thumbpad. </summary>
    public ControllerPadEvent PadTouchMoved = new ControllerPadEvent();

    /// <summary> Called when the buttons on the side of the controller are pressed. </summary>
    public ControllerEvent GripClicked = new ControllerEvent();

    /// <summary> Called when the buttons on the side of the controller are released. </summary>
    public ControllerEvent GripReleased = new ControllerEvent();



    /// <summary> The position of the last touch on the touchpad position. ToDo: What range is this in? </summary>
    public Vector2 PadPosition
    {
    get { return m_padPosition; }
    }

    /// <summary> The delta between this frame and the last frames position on the touchpad. </summary>
    public Vector2 PadDelta
    {
    get { return m_padDelta; }
    }

    /// <summary> The current value of the analog trigger. ToDo: What range is this in? </summary>
    public float Trigger
    {
    get { return m_triggerValue; }
    }

    /// <summary> The delta between this frame and the last frames trigger values. </summary>
    public float TriggerDelta
    {
    get { return m_triggerDelta; }
    }

    /// <summary> Which hand is this controller assigned to? Updated via <see cref="SetControllerHand"/>. </summary>
    public HandSides Hand
    {
    get { return m_hand; }
    }

    /// <summary> What is the index of the device as represented in SteamVR? </summary>
    public int DeviceIndex
    {
    get { return m_deviceIndex; }
    }

    /// <summary> Returns if this controller is actively being tracked. </summary>
    public bool IsTracked
    {
    get { return gameObject.activeInHierarchy; }
    }

    public Transform Tip
    {
    get { return m_controllerTip; }
    }

    /// <summary> The trigger must be depressed more than this normalized value for it to be considered "Hairtrigger" pressed. [0-1] value.</summary>
    [Range(0f, 1f)]
    public float HairTriggerThreshold = 0.1f;

    [SerializeField] private Transform m_controllerTip;

    /// <summary> Device Index as represented to SteamVR. Changed dynamically as devices are added/lost and never guranteed to be the same index. </summary>
    private int m_deviceIndex = -1;
    /// <summary> Snapshot of the controller button/input state as of last frame. </summary>
    private VRControllerState_t m_prevState;
    /// <summary> Snapshot of the controller button/input state as of this frame. </summary
    private VRControllerState_t m_currentState;

    private Vector2 m_padPosition;
    private Vector2 m_padPositionPrev;
    private Vector2 m_padDelta;
    private float m_triggerValue;
    private float m_triggerValuePrev;
    private float m_triggerDelta;
    private HandSides m_hand = HandSides.Invalid;

    private void Awake()
    {
    // Add the SteamVR_TrackedObject component so it gets position/rotation updates from SteamVR.
    if (GetComponent<SteamVR_TrackedObject>() == null)
    {
    gameObject.AddComponent<SteamVR_TrackedObject>();
    }
    }

    private void Update()
    {
    // If we're not currently tracked, don't try to update our state.
    if (m_deviceIndex == -1)
    return;

    m_prevState = m_currentState;

    // Update the current state to match the new state as provided by SteamVR. Then check the status
    // of all of the buttons and send off events based on their new state.
    if(SteamVR.instance.hmd.GetControllerState((uint) m_deviceIndex, ref m_currentState))
    {
    // We only have a valid pad position if the pad is being touched, otherwise it reports 0,0.
    if (GetPadTouched())
    {
    // Update the state of the pad position and calculate a new delta.
    m_padPositionPrev = m_padPosition;
    m_padPosition.x = m_currentState.rAxis[(int)EVRControllerAxisType.k_eControllerAxis_None].x;
    m_padPosition.y = m_currentState.rAxis[(int)EVRControllerAxisType.k_eControllerAxis_None].y;

    m_padDelta = m_padPosition - m_padPositionPrev;

    if (m_padDelta != Vector2.zero)
    PadTouchMoved.Invoke(m_padDelta);
    }
    else
    {
    // Otherwise, with have zero position and zero delta.
    m_padDelta = Vector2.zero;
    m_padPosition = Vector2.zero;
    }


    // Update the state of the trigger.
    m_triggerValuePrev = m_triggerValue;
    m_triggerValue = GetTriggerValue(m_currentState);
    m_triggerDelta = m_triggerValue - m_triggerValuePrev;

    if (m_triggerDelta != 0f)
    TriggerChanged.Invoke(m_triggerDelta);

    if(GetMenuButtonDown())
    MenuButtonClicked.Invoke(this);

    if(GetMenuButtonUp())
    MenuButtonReleased.Invoke(this);

    if(GetTriggerDown())
    TriggerClicked.Invoke(this);

    if(GetTriggerUp())
    TriggerReleased.Invoke(this);

    if(GetPadButtonDown())
    PadButtonClicked.Invoke(this);

    if(GetPadButtonUp())
    PadTouchReleased.Invoke(this);

    if(GetPadTouchedDown())
    PadTouchClicked.Invoke(this);

    if(GetPadTouchedUp())
    PadTouchReleased.Invoke(this);

    if(GetGripDown())
    GripClicked.Invoke(this);

    if(GetGripUp())
    GripReleased.Invoke(this);

    if (GetHairTriggerDown())
    HairTriggerClicked.Invoke(this);

    if (GetHairTriggerUp())
    HairTriggerReleased.Invoke(this);
    }

    }

    /// <summary>
    /// Trigger haptic feedback in the controller for the specified duration of time. May be two haptic feedback motors
    /// for different buttons (ie: touchpad vs trigger?) unknown at the moment.
    /// </summary>
    /// <param name="durationMicroSec">Duration of the haptic pulse in **Micro Seconds** (1/1000 of a Millisecond).
    ///
    /// Application may not trigger another haptic pulse for this controller/axis combination for 5ms.
    /// </param>
    /// <param name="buttonId">Button for which to trigger the haptic pulse.</param>
    public void TriggerHapticPulse(ushort durationMicroSec = 500, EVRButtonId buttonId = EVRButtonId.k_EButton_SteamVR_Touchpad)
    {
    // We can't do a haptic pulse if we have no device index.
    if (DeviceIndex == -1)
    return;

    // From SteamVR_Controller.cs
    uint axisId = (uint)buttonId - (uint)EVRButtonId.k_EButton_Axis0;
    SteamVR.instance.hmd.TriggerHapticPulse((uint)m_deviceIndex, axisId, (char)durationMicroSec);
    }

    /// <summary>
    /// Set the device index that this controller is tracking.
    /// Automatically updates the associated SteamVR_TrackedObject.
    /// Automatically updates the ControllerHand to <see cref="HandSides.Invalid"/> if deviceIndex is -1.
    /// </summary>
    /// <param name="deviceIndex"></param>
    public void SetDeviceIndex(int deviceIndex)
    {
    m_deviceIndex = deviceIndex;
    if (m_deviceIndex == -1)
    SetControllerHand(HandSides.Invalid);

    // Update our SteamVR_TrackedObject as well so it tracks the same thing.
    GetComponent<SteamVR_TrackedObject>().SetDeviceIndex(deviceIndex);

    Debug.LogFormat("Controller {0} deviceIndex Set: {1}", this, deviceIndex);
    }

    /// <summary>
    /// Called by <see cref="VRControllerManager"/> when controllers are being updated. This is calculated when
    /// both controllers are initially detected, and when <see cref="VRControllerManager::UpdateControllerHandStatuses"/>
    /// is called.
    /// </summary>
    /// <param name="hand"></param>
    public void SetControllerHand(HandSides hand)
    {
    m_hand = hand;
    Debug.LogFormat("Controller {0} hand Set: {1}", this, hand);
    }

    #region Controller State Getters
    #region Menu Button
    /// <summary>
    /// Returns true if the menu button was pressed down this frame but was not pressed last frame.
    /// </summary>
    public bool GetMenuButtonDown()
    {
    bool prev = GetButtonPressed(EVRButtonId.k_EButton_ApplicationMenu, m_prevState);
    bool now = GetButtonPressed(EVRButtonId.k_EButton_ApplicationMenu, m_currentState);

    return !prev && now;
    }

    /// <summary>
    /// Returns true if the menu button was released this frame and pressed last frame.
    /// </summary>
    public bool GetMenuButtonUp()
    {
    bool prev = GetButtonPressed(EVRButtonId.k_EButton_ApplicationMenu, m_prevState);
    bool now = GetButtonPressed(EVRButtonId.k_EButton_ApplicationMenu, m_currentState);

    return prev && !now;
    }

    /// <summary>
    /// Returns true if the menu button is currently held down.
    /// </summary>
    public bool GetMenuButton()
    {
    return GetButtonPressed(EVRButtonId.k_EButton_ApplicationMenu, m_prevState);
    }
    #endregion

    #region Trigger Button
    /// <summary>
    /// Returns true if the trigger button was fully pressed down this frame but was not pressed last frame.
    /// </summary>
    public bool GetTriggerDown()
    {
    bool prev = GetButtonPressed(EVRButtonId.k_EButton_SteamVR_Trigger, m_prevState);
    bool now = GetButtonPressed(EVRButtonId.k_EButton_SteamVR_Trigger, m_currentState);

    return !prev && now;
    }

    /// <summary>
    /// Returns true if the trigger button was released (from fully pressed) this frame and pressed last frame.
    /// </summary>
    public bool GetTriggerUp()
    {
    bool prev = GetButtonPressed(EVRButtonId.k_EButton_SteamVR_Trigger, m_prevState);
    bool now = GetButtonPressed(EVRButtonId.k_EButton_SteamVR_Trigger, m_currentState);

    return prev && !now;
    }

    /// <summary>
    /// Returns true if the trigger button is currently held down.
    /// </summary>
    public bool GetTrigger()
    {
    return GetButtonPressed(EVRButtonId.k_EButton_SteamVR_Trigger, m_currentState);
    }

    /// <summary>
    /// Returns true if the trigger button crossed over the hair trigger threshold this frame, but was not last frame.
    /// A hair trigger is considered that the trigger is only being pressed slightly down (ie: more than <see cref="HairTriggerThreshold"/>).
    /// </summary>
    public bool GetHairTriggerDown()
    {
    float lastValue = GetTriggerValue(m_prevState);
    float curValue = GetTriggerValue(m_currentState);

    return lastValue < HairTriggerThreshold && curValue >= HairTriggerThreshold;
    }

    /// <summary>
    /// Returns true if the trigger button fell under the hair trigger threshold this frame, but was over it last frame.
    /// A hair trigger is considered that the trigger is only being pressed slightly down (ie: more than <see cref="HairTriggerThreshold"/>).
    /// </summary>
    public bool GetHairTriggerUp()
    {
    float lastValue = GetTriggerValue(m_prevState);
    float curValue = GetTriggerValue(m_currentState);

    return curValue < HairTriggerThreshold && lastValue >= HairTriggerThreshold;
    }

    /// <summary>
    /// Returns true if the trigger is currently more depressed than the hair trigger threshold.
    /// A hair trigger is considered that the trigger is only being pressed slightly down (ie: more than <see cref="HairTriggerThreshold"/>).
    /// </summary>
    public bool GetHairTrigger()
    {
    return GetTriggerValue(m_currentState) >= HairTriggerThreshold;
    }
    #endregion

    #region Touchpad Button
    /// <summary>
    /// Returns true if the pad button was pressed down this frame but was not pressed last frame.
    /// </summary>
    public bool GetPadButtonDown()
    {
    bool prev = GetButtonPressed(EVRButtonId.k_EButton_SteamVR_Touchpad, m_prevState);
    bool now = GetButtonPressed(EVRButtonId.k_EButton_SteamVR_Touchpad, m_currentState);

    return !prev && now;
    }

    /// <summary>
    /// Returns true if the pad button was released this frame and pressed last frame.
    /// </summary>
    public bool GetPadButtonUp()
    {
    bool prev = GetButtonPressed(EVRButtonId.k_EButton_SteamVR_Touchpad, m_prevState);
    bool now = GetButtonPressed(EVRButtonId.k_EButton_SteamVR_Touchpad, m_currentState);

    return prev && !now;

    }

    /// <summary>
    /// Returns true if the pad button is currently held down.
    /// </summary>
    public bool GetPadButton()
    {
    return GetButtonPressed(EVRButtonId.k_EButton_SteamVR_Touchpad, m_currentState);
    }
    #endregion

    #region Touchpad Touched
    /// <summary>
    /// Returns true if the pad started being touched this frame but was not touched last frame.
    /// </summary>
    public bool GetPadTouchedDown()
    {
    bool prev = GetButtonTouched(EVRButtonId.k_EButton_SteamVR_Touchpad, m_prevState);
    bool now = GetButtonTouched(EVRButtonId.k_EButton_SteamVR_Touchpad, m_currentState);

    return !prev && now;
    }

    /// <summary>
    /// Returns true if the pad is no longer being touched but was being touched last frame.
    /// </summary>
    public bool GetPadTouchedUp()
    {
    bool prev = GetButtonTouched(EVRButtonId.k_EButton_SteamVR_Touchpad, m_prevState);
    bool now = GetButtonTouched(EVRButtonId.k_EButton_SteamVR_Touchpad, m_currentState);

    return prev && !now;
    }

    /// <summary>
    /// Returns true if the pad is currently being touched (but not clicked in).
    /// </summary>
    public bool GetPadTouched()
    {
    return GetButtonTouched(EVRButtonId.k_EButton_SteamVR_Touchpad, m_currentState);
    }
    #endregion

    #region Grip
    /// <summary>
    /// Returns true if the grip buttons were pressed down this frame but was not pressed last frame.
    /// </summary>
    public bool GetGripDown()
    {
    bool prev = GetButtonPressed(EVRButtonId.k_EButton_Grip, m_prevState);
    bool now = GetButtonPressed(EVRButtonId.k_EButton_Grip, m_currentState);

    return !prev && now;
    }

    /// <summary>
    /// Returns true if the grip buttons were released this frame and pressed last frame.
    /// </summary>
    public bool GetGripUp()
    {
    bool prev = GetButtonPressed(EVRButtonId.k_EButton_Grip, m_prevState);
    bool now = GetButtonPressed(EVRButtonId.k_EButton_Grip, m_currentState);

    return prev && !now;
    }

    /// <summary>
    /// Returns true if the grip buttons are currently held down.
    /// </summary>
    public bool GetGrip()
    {
    return GetButtonPressed(EVRButtonId.k_EButton_Grip, m_currentState);

    }
    #endregion

    /// <summary>
    /// Returns true if the specified <see cref"VRController::Button"/> was pressed down
    /// this frame.
    ///
    /// Helper function to allow the use of a configurable enum instead of a specific function variant.
    /// </summary>
    public bool GetButtonDown(Button button)
    {
    switch (button)
    {
    case Button.Trigger: return GetTriggerDown();
    case Button.HairTrigger: return GetHairTriggerDown();
    case Button.PadTouch: return GetPadTouchedDown();
    case Button.PadButton: return GetPadButtonDown();
    case Button.Menu: return GetMenuButtonDown();
    case Button.Grip: return GetGripDown();
    case Button.Invalid:
    default:
    Debug.LogWarning("GetButtonDown - Invalid button enum specified for controller.", this);
    return false;
    }
    }

    /// <summary>
    /// Returns true if the specified <see cref"VRController::Button"/> was released this frame.
    ///
    /// Helper function to allow the use of a configurable enum instead of a specific function variant.
    /// </summary>
    public bool GetButtonUp(Button button)
    {
    switch (button)
    {
    case Button.Trigger: return GetTriggerUp();
    case Button.HairTrigger: return GetHairTriggerUp();
    case Button.PadTouch: return GetPadTouchedUp();
    case Button.PadButton: return GetPadButtonUp();
    case Button.Menu: return GetMenuButtonUp();
    case Button.Grip: return GetGripUp();
    case Button.Invalid:
    default:
    Debug.LogWarning("GetButtonUp Invalid button enum specified for controller.", this);
    return false;
    }
    }

    /// <summary>
    /// Returns true if the specified <see cref"VRController::Button"/> is currently pressed.
    ///
    /// Helper function to allow the use of a configurable enum instead of a specific function variant.
    /// </summary>
    public bool GetButton(Button button)
    {
    switch (button)
    {
    case Button.Trigger: return GetTrigger();
    case Button.HairTrigger: return GetHairTrigger();
    case Button.PadTouch: return GetPadTouched();
    case Button.PadButton: return GetPadButton();
    case Button.Menu: return GetMenuButton();
    case Button.Grip: return GetGrip();
    case Button.Invalid:
    default:
    Debug.LogWarning("GetButton Invalid button enum specified for controller.", this);
    return false;
    }
    }
    #endregion

    /// <summary>
    /// Unpack a button pressed state from a <see cref="VRControllerState_t"/> struct.
    /// </summary>
    /// <param name="button"><see cref="EVRButtonId"/> to return state for.</param>
    /// <param name="fromState"><see cref="VRControllerState_t"/> instance to return state of.</param>
    /// <returns>True if the button is pressed, false if it is not.</returns>
    private bool GetButtonPressed(EVRButtonId button, VRControllerState_t fromState)
    {
    ulong state = fromState.ulButtonPressed & (1UL << ((int)button));
    return state > 0L;
    }

    /// <summary>
    /// Unpack a button touched state from a <see cref="VRControllerState_t"/> struct.
    /// </summary>
    /// <param name="button"><see cref="EVRButtonId"/> to return state for.</param>
    /// <param name="fromState"><see cref="VRControllerState_t"/> instance to return state of.</param>
    /// <returns>True if the button is being touched, false if it is not.</returns>
    private bool GetButtonTouched(EVRButtonId button, VRControllerState_t fromState)
    {
    ulong state = fromState.ulButtonTouched & (1UL << ((int)button));
    return state > 0L;
    }

    /// <summary>
    /// Returns the value of the trigger from the specified state.
    /// </summary>
    /// <param name="fromState"></param>
    /// <returns></returns>
    private float GetTriggerValue(VRControllerState_t fromState)
    {
    // Copied out of SteamVR_Controller.cs
    const uint axisId = (uint)EVRButtonId.k_EButton_SteamVR_Trigger - (uint)EVRButtonId.k_EButton_Axis0;

    // rAxis will be null if we've not gotten the state from the controller before (ie: first frame)
    // the struct is valid, but not the array inside.
    if (fromState.rAxis == null || fromState.rAxis.Length == 0)
    return 0f;

    return fromState.rAxis[axisId].x; // Presumed [0-1] range.
    }

    public override string ToString()
    {
    return string.Format("VRController ({0})[{1}]", m_hand, gameObject.name);
    }
    }
    }