A lot of changes
|
@ -33,8 +33,6 @@ namespace BNG {
|
|||
lookAt = Camera.main.transform;
|
||||
lineTo = GetComponentInChildren<LineToTransform>();
|
||||
|
||||
childTransform = transform.GetChild(0);
|
||||
|
||||
if (DrawLineTo && lineTo) {
|
||||
lineTo.ConnectTo = DrawLineTo;
|
||||
}
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
using System.Collections;
|
||||
using QFSW.QC;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using UnityEngine.SceneManagement;
|
||||
|
|
|
@ -81,7 +81,6 @@ namespace BNG {
|
|||
|
||||
public void Update() {
|
||||
data = uiSystem.EventData;
|
||||
|
||||
// Can bail early if not looking at anything
|
||||
if (data == null || data.pointerCurrentRaycast.gameObject == null) {
|
||||
|
||||
|
|
|
@ -0,0 +1,71 @@
|
|||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Events;
|
||||
|
||||
public class BonusController : MonoBehaviour, ITextChangable
|
||||
{
|
||||
public UnityEvent<object> OnTextChange => _OnTextChange;
|
||||
private UnityEvent<object> _OnTextChange = new UnityEvent<object>();
|
||||
|
||||
private float _bonusValue = 1f;
|
||||
public float BonusValue
|
||||
{
|
||||
get => _bonusValue;
|
||||
set
|
||||
{
|
||||
_bonusValue = value;
|
||||
_OnTextChange?.Invoke(_bonusValue);
|
||||
}
|
||||
}
|
||||
|
||||
[SerializeField]
|
||||
private float _bonusOffset = 0.1f;
|
||||
[SerializeField]
|
||||
private float _decreaseReloadTime = 5f;
|
||||
[SerializeField]
|
||||
private float _decreaseSpeed = 0.6f;
|
||||
|
||||
private bool _decreaseBonus = false;
|
||||
private Coroutine _decreaseReloadCoroutine;
|
||||
|
||||
private void Start()
|
||||
{
|
||||
BonusValue = 1;
|
||||
}
|
||||
|
||||
private IEnumerator DecreaseReload_Coroutine()
|
||||
{
|
||||
_decreaseBonus = false;
|
||||
yield return new WaitForSeconds(_decreaseReloadTime);
|
||||
_decreaseBonus = true;
|
||||
}
|
||||
|
||||
public void DecreaseReload()
|
||||
{
|
||||
if (_decreaseReloadCoroutine != null)
|
||||
{
|
||||
StopCoroutine(_decreaseReloadCoroutine);
|
||||
}
|
||||
|
||||
_decreaseReloadCoroutine = StartCoroutine(DecreaseReload_Coroutine());
|
||||
}
|
||||
|
||||
public void UseBonus()
|
||||
{
|
||||
BonusValue += _bonusOffset;
|
||||
}
|
||||
|
||||
private void FixedUpdate()
|
||||
{
|
||||
if (_decreaseBonus)
|
||||
{
|
||||
BonusValue -= Time.deltaTime * _decreaseSpeed;
|
||||
BonusValue = Mathf.Clamp(BonusValue, 1, float.MaxValue);
|
||||
|
||||
_OnTextChange?.Invoke(BonusValue);
|
||||
if (BonusValue == 1)
|
||||
_decreaseBonus = false;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: fcac5d61675676348a971415642afa3c
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -21,7 +21,7 @@ public class CockpitUIModule : MonoBehaviour
|
|||
_UITextShow.ShowSubtitle
|
||||
(
|
||||
description,
|
||||
0.01f,
|
||||
0.1f,
|
||||
5,
|
||||
null,
|
||||
() => { _previewPanel.HidePanel(); }
|
||||
|
|
|
@ -0,0 +1,75 @@
|
|||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Events;
|
||||
|
||||
public class DynamicLeaderboard : MonoBehaviour, ITextChangable
|
||||
{
|
||||
private ScoreController _scoreController;
|
||||
|
||||
public UnityEvent<object> OnTextChange => _OnTextChange;
|
||||
private UnityEvent<object> _OnTextChange = new UnityEvent<object>();
|
||||
|
||||
[SerializeField]
|
||||
private RectTransform _content;
|
||||
[SerializeField]
|
||||
private LeaderboardEntry _leaderboardEntryPrefab;
|
||||
|
||||
private List<LeaderboardEntry> _entries = new List<LeaderboardEntry>();
|
||||
|
||||
[SerializeField]
|
||||
private int _abovePlayersCount = 6;
|
||||
[SerializeField]
|
||||
private int _totalPlayersCount = 10;
|
||||
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
_scoreController = FindObjectOfType<ScoreController>();
|
||||
}
|
||||
|
||||
private void OnEnable()
|
||||
{
|
||||
_scoreController.OnScoreChange += OnScoreChange;
|
||||
}
|
||||
|
||||
private void OnDisable()
|
||||
{
|
||||
_scoreController.OnScoreChange -= OnScoreChange;
|
||||
}
|
||||
|
||||
|
||||
private void OnScoreChange(float value)
|
||||
{
|
||||
Debug.Log("Refactor leaderboard");
|
||||
Debug.Log($"New player {value}");
|
||||
|
||||
UpdateLeaderboard();
|
||||
}
|
||||
|
||||
[ContextMenu("Debug Update LB")]
|
||||
private void UpdateLeaderboard()
|
||||
{
|
||||
_entries.ForEach(x => Destroy(x.gameObject));
|
||||
_entries.Clear();
|
||||
_entries = new List<LeaderboardEntry>();
|
||||
Debug.Log("Tst");
|
||||
|
||||
var sortedList = PlayerSetup.Instance.PlayerInfo.Players.OrderByDescending(x => x.Score).ToList();
|
||||
|
||||
int indexOfOutPlayer = sortedList.IndexOf(PlayerSetup.Instance.CurrentPlayer);
|
||||
|
||||
int startIndex = Mathf.Clamp(indexOfOutPlayer - _abovePlayersCount, 0, sortedList.Count);
|
||||
int lastIndex = Mathf.Clamp(startIndex + _totalPlayersCount, 0, sortedList.Count);
|
||||
|
||||
for (int i = startIndex; i < lastIndex; i++)
|
||||
{
|
||||
var newEntry = Instantiate(_leaderboardEntryPrefab, _content);
|
||||
_entries.Add(newEntry);
|
||||
newEntry.Init(sortedList[i], i, i == indexOfOutPlayer);
|
||||
}
|
||||
|
||||
_OnTextChange?.Invoke(indexOfOutPlayer + 1);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 0ed63b8d95151544089de4eeed8c9b1a
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -1,3 +1,4 @@
|
|||
using BNG;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
@ -12,9 +13,19 @@ public class EndGameModule : MonoBehaviour
|
|||
|
||||
[SerializeField]
|
||||
private UITextShow _textShow;
|
||||
[SerializeField]
|
||||
private UITextShow _textTimer;
|
||||
|
||||
[SerializeField]
|
||||
private UIPanel _uiPanel;
|
||||
|
||||
private SceneLoader _sceneLoader;
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
_sceneLoader = FindObjectOfType<SceneLoader>();
|
||||
}
|
||||
|
||||
public void ShowEndMenu(bool success)
|
||||
{
|
||||
_uiPanel.ShowPanel();
|
||||
|
@ -27,5 +38,7 @@ public class EndGameModule : MonoBehaviour
|
|||
{
|
||||
_textShow.SetText(LoseText);
|
||||
}
|
||||
|
||||
_textTimer.ShowTimer(3, string.Empty, 0, null, () => { _sceneLoader.LoadScene("ResultScene"); });
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,13 +8,15 @@ public class MonumentController : MonoBehaviour
|
|||
private float _energyToUnlock;
|
||||
[SerializeField]
|
||||
private MonumentInfo _info;
|
||||
|
||||
private EnergyController _energyController;
|
||||
private float _currentEnergy;
|
||||
|
||||
private ScoreController _scoreController;
|
||||
private CockpitUIModule _cockpitUI;
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
_scoreController = FindObjectOfType<ScoreController>();
|
||||
_cockpitUI = FindObjectOfType<CockpitUIModule>();
|
||||
_energyController = FindObjectOfType<EnergyController>();
|
||||
_currentEnergy = _energyToUnlock;
|
||||
|
@ -31,10 +33,12 @@ public class MonumentController : MonoBehaviour
|
|||
Debug.Log($"Clamped energy value: {_currentEnergy / _energyToUnlock}");
|
||||
});
|
||||
|
||||
_scoreController.AddScoreInTime(_info.Score, 1, false);
|
||||
//TODO: ÐÀÇÁËÎÊÈÐÎÂÀÒÜ ÌÎÍÓÌÅÍÒ ÒÎËÜÊÎ ÅÑËÈ ÕÂÀÒÈËÎ ÝÍÅÐÃÈÈ
|
||||
PlayerSetup.Instance.UnlockMonument(_info);
|
||||
}
|
||||
|
||||
[ContextMenu("Debug Preview")]
|
||||
public void ShowPreview()
|
||||
{
|
||||
_cockpitUI.ShowInfo(_info.Image, _info.Description);
|
||||
|
|
|
@ -0,0 +1,8 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 82d1493c4b76fa64485519afe8919eae
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,8 @@
|
|||
fileFormatVersion: 2
|
||||
guid: b8ce61d0462147c4789d22c6bdacd045
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,8 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 7288d5d133aff2a4ea46b88ef2d9a151
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,8 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 0b8922a5489a74b5ebfd54fa257dbfc6
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,8 @@
|
|||
fileFormatVersion: 2
|
||||
guid: b6dcd5bbe38024ae6b2389ff04c696a0
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,167 @@
|
|||
%YAML 1.1
|
||||
%TAG !u! tag:unity3d.com,2011:
|
||||
--- !u!91 &9100000
|
||||
AnimatorController:
|
||||
m_ObjectHideFlags: 0
|
||||
m_PrefabParentObject: {fileID: 0}
|
||||
m_PrefabInternal: {fileID: 0}
|
||||
m_Name: Gate
|
||||
serializedVersion: 5
|
||||
m_AnimatorParameters:
|
||||
- m_Name: opened
|
||||
m_Type: 4
|
||||
m_DefaultFloat: 0
|
||||
m_DefaultInt: 0
|
||||
m_DefaultBool: 0
|
||||
m_Controller: {fileID: 0}
|
||||
m_AnimatorLayers:
|
||||
- serializedVersion: 5
|
||||
m_Name: Base Layer
|
||||
m_StateMachine: {fileID: 1107068299116960040}
|
||||
m_Mask: {fileID: 0}
|
||||
m_Motions: []
|
||||
m_Behaviours: []
|
||||
m_BlendingMode: 0
|
||||
m_SyncedLayerIndex: -1
|
||||
m_DefaultWeight: 0
|
||||
m_IKPass: 0
|
||||
m_SyncedLayerAffectsTiming: 0
|
||||
m_Controller: {fileID: 9100000}
|
||||
--- !u!1101 &1101412341846453426
|
||||
AnimatorStateTransition:
|
||||
m_ObjectHideFlags: 1
|
||||
m_PrefabParentObject: {fileID: 0}
|
||||
m_PrefabInternal: {fileID: 0}
|
||||
m_Name:
|
||||
m_Conditions:
|
||||
- m_ConditionMode: 1
|
||||
m_ConditionEvent: opened
|
||||
m_EventTreshold: 0
|
||||
m_DstStateMachine: {fileID: 0}
|
||||
m_DstState: {fileID: 1102542311080980048}
|
||||
m_Solo: 0
|
||||
m_Mute: 0
|
||||
m_IsExit: 0
|
||||
serializedVersion: 3
|
||||
m_TransitionDuration: 0
|
||||
m_TransitionOffset: 0
|
||||
m_ExitTime: 1
|
||||
m_HasExitTime: 0
|
||||
m_HasFixedDuration: 0
|
||||
m_InterruptionSource: 0
|
||||
m_OrderedInterruption: 1
|
||||
m_CanTransitionToSelf: 1
|
||||
--- !u!1101 &1101867287240705608
|
||||
AnimatorStateTransition:
|
||||
m_ObjectHideFlags: 1
|
||||
m_PrefabParentObject: {fileID: 0}
|
||||
m_PrefabInternal: {fileID: 0}
|
||||
m_Name:
|
||||
m_Conditions:
|
||||
- m_ConditionMode: 2
|
||||
m_ConditionEvent: opened
|
||||
m_EventTreshold: 0
|
||||
m_DstStateMachine: {fileID: 0}
|
||||
m_DstState: {fileID: 1102970369894184824}
|
||||
m_Solo: 0
|
||||
m_Mute: 0
|
||||
m_IsExit: 0
|
||||
serializedVersion: 3
|
||||
m_TransitionDuration: 0
|
||||
m_TransitionOffset: 0
|
||||
m_ExitTime: 1
|
||||
m_HasExitTime: 0
|
||||
m_HasFixedDuration: 0
|
||||
m_InterruptionSource: 0
|
||||
m_OrderedInterruption: 1
|
||||
m_CanTransitionToSelf: 1
|
||||
--- !u!1102 &1102542311080980048
|
||||
AnimatorState:
|
||||
serializedVersion: 5
|
||||
m_ObjectHideFlags: 1
|
||||
m_PrefabParentObject: {fileID: 0}
|
||||
m_PrefabInternal: {fileID: 0}
|
||||
m_Name: GateOpen
|
||||
m_Speed: 1
|
||||
m_CycleOffset: 0
|
||||
m_Transitions:
|
||||
- {fileID: 1101867287240705608}
|
||||
m_StateMachineBehaviours: []
|
||||
m_Position: {x: 50, y: 50, z: 0}
|
||||
m_IKOnFeet: 0
|
||||
m_WriteDefaultValues: 1
|
||||
m_Mirror: 0
|
||||
m_SpeedParameterActive: 0
|
||||
m_MirrorParameterActive: 0
|
||||
m_CycleOffsetParameterActive: 0
|
||||
m_TimeParameterActive: 0
|
||||
m_Motion: {fileID: 7400000, guid: 509dd06e376974a80be87395ca1da5b8, type: 2}
|
||||
m_Tag:
|
||||
m_SpeedParameter:
|
||||
m_MirrorParameter:
|
||||
m_CycleOffsetParameter:
|
||||
m_TimeParameter:
|
||||
--- !u!1102 &1102970369894184824
|
||||
AnimatorState:
|
||||
serializedVersion: 5
|
||||
m_ObjectHideFlags: 3
|
||||
m_PrefabParentObject: {fileID: 0}
|
||||
m_PrefabInternal: {fileID: 0}
|
||||
m_Name: GateClose
|
||||
m_Speed: -1
|
||||
m_CycleOffset: 0
|
||||
m_Transitions:
|
||||
- {fileID: 1101412341846453426}
|
||||
m_StateMachineBehaviours: []
|
||||
m_Position: {x: 50, y: 50, z: 0}
|
||||
m_IKOnFeet: 0
|
||||
m_WriteDefaultValues: 1
|
||||
m_Mirror: 0
|
||||
m_SpeedParameterActive: 0
|
||||
m_MirrorParameterActive: 0
|
||||
m_CycleOffsetParameterActive: 0
|
||||
m_TimeParameterActive: 0
|
||||
m_Motion: {fileID: 7400000, guid: 509dd06e376974a80be87395ca1da5b8, type: 2}
|
||||
m_Tag:
|
||||
m_SpeedParameter:
|
||||
m_MirrorParameter:
|
||||
m_CycleOffsetParameter:
|
||||
m_TimeParameter:
|
||||
--- !u!1107 &1107068299116960040
|
||||
AnimatorStateMachine:
|
||||
serializedVersion: 5
|
||||
m_ObjectHideFlags: 1
|
||||
m_PrefabParentObject: {fileID: 0}
|
||||
m_PrefabInternal: {fileID: 0}
|
||||
m_Name: Base Layer
|
||||
m_ChildStates:
|
||||
- serializedVersion: 1
|
||||
m_State: {fileID: 1102542311080980048}
|
||||
m_Position: {x: 276, y: 60, z: 0}
|
||||
- serializedVersion: 1
|
||||
m_State: {fileID: 1102970369894184824}
|
||||
m_Position: {x: 276, y: 120, z: 0}
|
||||
m_ChildStateMachines: []
|
||||
m_AnyStateTransitions: []
|
||||
m_EntryTransitions:
|
||||
- {fileID: 1109804302365171388}
|
||||
m_StateMachineTransitions: {}
|
||||
m_StateMachineBehaviours: []
|
||||
m_AnyStatePosition: {x: 50, y: 20, z: 0}
|
||||
m_EntryPosition: {x: 50, y: 120, z: 0}
|
||||
m_ExitPosition: {x: 800, y: 120, z: 0}
|
||||
m_ParentStateMachinePosition: {x: 800, y: 20, z: 0}
|
||||
m_DefaultState: {fileID: 1102970369894184824}
|
||||
--- !u!1109 &1109804302365171388
|
||||
AnimatorTransition:
|
||||
m_ObjectHideFlags: 1
|
||||
m_PrefabParentObject: {fileID: 0}
|
||||
m_PrefabInternal: {fileID: 0}
|
||||
m_Name:
|
||||
m_Conditions: []
|
||||
m_DstStateMachine: {fileID: 0}
|
||||
m_DstState: {fileID: 1102970369894184824}
|
||||
m_Solo: 0
|
||||
m_Mute: 0
|
||||
m_IsExit: 0
|
||||
serializedVersion: 1
|
|
@ -0,0 +1,8 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 4116117e33ea046eab1abc1d101b4086
|
||||
NativeFormatImporter:
|
||||
externalObjects: {}
|
||||
mainObjectFileID: 9100000
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,169 @@
|
|||
%YAML 1.1
|
||||
%TAG !u! tag:unity3d.com,2011:
|
||||
--- !u!74 &7400000
|
||||
AnimationClip:
|
||||
m_ObjectHideFlags: 0
|
||||
m_PrefabParentObject: {fileID: 0}
|
||||
m_PrefabInternal: {fileID: 0}
|
||||
m_Name: GateOpen
|
||||
serializedVersion: 6
|
||||
m_Legacy: 0
|
||||
m_Compressed: 0
|
||||
m_UseHighQualityCurve: 1
|
||||
m_RotationCurves: []
|
||||
m_CompressedRotationCurves: []
|
||||
m_EulerCurves: []
|
||||
m_PositionCurves:
|
||||
- curve:
|
||||
serializedVersion: 2
|
||||
m_Curve:
|
||||
- serializedVersion: 3
|
||||
time: 0
|
||||
value: {x: 0, y: 0, z: 0}
|
||||
inSlope: {x: 0, y: 0, z: 0}
|
||||
outSlope: {x: 0, y: 0, z: 0}
|
||||
tangentMode: 0
|
||||
weightedMode: 0
|
||||
inWeight: {x: 0.33333334, y: 0.33333334, z: 0.33333334}
|
||||
outWeight: {x: 0.33333334, y: 0.33333334, z: 0.33333334}
|
||||
- serializedVersion: 3
|
||||
time: 1
|
||||
value: {x: 0, y: 8, z: 0}
|
||||
inSlope: {x: 0, y: 0, z: 0}
|
||||
outSlope: {x: 0, y: 0, z: 0}
|
||||
tangentMode: 0
|
||||
weightedMode: 0
|
||||
inWeight: {x: 0.33333334, y: 0.33333334, z: 0.33333334}
|
||||
outWeight: {x: 0.33333334, y: 0.33333334, z: 0.33333334}
|
||||
m_PreInfinity: 2
|
||||
m_PostInfinity: 2
|
||||
m_RotationOrder: 4
|
||||
path:
|
||||
m_ScaleCurves: []
|
||||
m_FloatCurves: []
|
||||
m_PPtrCurves: []
|
||||
m_SampleRate: 60
|
||||
m_WrapMode: 0
|
||||
m_Bounds:
|
||||
m_Center: {x: 0, y: 0, z: 0}
|
||||
m_Extent: {x: 0, y: 0, z: 0}
|
||||
m_ClipBindingConstant:
|
||||
genericBindings:
|
||||
- serializedVersion: 2
|
||||
path: 0
|
||||
attribute: 1
|
||||
script: {fileID: 0}
|
||||
typeID: 4
|
||||
customType: 0
|
||||
isPPtrCurve: 0
|
||||
pptrCurveMapping: []
|
||||
m_AnimationClipSettings:
|
||||
serializedVersion: 2
|
||||
m_AdditiveReferencePoseClip: {fileID: 0}
|
||||
m_AdditiveReferencePoseTime: 0
|
||||
m_StartTime: 0
|
||||
m_StopTime: 1
|
||||
m_OrientationOffsetY: 0
|
||||
m_Level: 0
|
||||
m_CycleOffset: 0
|
||||
m_HasAdditiveReferencePose: 0
|
||||
m_LoopTime: 0
|
||||
m_LoopBlend: 0
|
||||
m_LoopBlendOrientation: 0
|
||||
m_LoopBlendPositionY: 0
|
||||
m_LoopBlendPositionXZ: 0
|
||||
m_KeepOriginalOrientation: 0
|
||||
m_KeepOriginalPositionY: 1
|
||||
m_KeepOriginalPositionXZ: 0
|
||||
m_HeightFromFeet: 0
|
||||
m_Mirror: 0
|
||||
m_EditorCurves:
|
||||
- curve:
|
||||
serializedVersion: 2
|
||||
m_Curve:
|
||||
- serializedVersion: 3
|
||||
time: 0
|
||||
value: 0
|
||||
inSlope: 0
|
||||
outSlope: 0
|
||||
tangentMode: 136
|
||||
weightedMode: 0
|
||||
inWeight: 0.33333334
|
||||
outWeight: 0.33333334
|
||||
- serializedVersion: 3
|
||||
time: 1
|
||||
value: 0
|
||||
inSlope: 0
|
||||
outSlope: 0
|
||||
tangentMode: 136
|
||||
weightedMode: 0
|
||||
inWeight: 0.33333334
|
||||
outWeight: 0.33333334
|
||||
m_PreInfinity: 2
|
||||
m_PostInfinity: 2
|
||||
m_RotationOrder: 4
|
||||
attribute: m_LocalPosition.x
|
||||
path:
|
||||
classID: 4
|
||||
script: {fileID: 0}
|
||||
- curve:
|
||||
serializedVersion: 2
|
||||
m_Curve:
|
||||
- serializedVersion: 3
|
||||
time: 0
|
||||
value: 0
|
||||
inSlope: 0
|
||||
outSlope: 0
|
||||
tangentMode: 136
|
||||
weightedMode: 0
|
||||
inWeight: 0.33333334
|
||||
outWeight: 0.33333334
|
||||
- serializedVersion: 3
|
||||
time: 1
|
||||
value: 8
|
||||
inSlope: 0
|
||||
outSlope: 0
|
||||
tangentMode: 136
|
||||
weightedMode: 0
|
||||
inWeight: 0.33333334
|
||||
outWeight: 0.33333334
|
||||
m_PreInfinity: 2
|
||||
m_PostInfinity: 2
|
||||
m_RotationOrder: 4
|
||||
attribute: m_LocalPosition.y
|
||||
path:
|
||||
classID: 4
|
||||
script: {fileID: 0}
|
||||
- curve:
|
||||
serializedVersion: 2
|
||||
m_Curve:
|
||||
- serializedVersion: 3
|
||||
time: 0
|
||||
value: 0
|
||||
inSlope: 0
|
||||
outSlope: 0
|
||||
tangentMode: 136
|
||||
weightedMode: 0
|
||||
inWeight: 0.33333334
|
||||
outWeight: 0.33333334
|
||||
- serializedVersion: 3
|
||||
time: 1
|
||||
value: 0
|
||||
inSlope: 0
|
||||
outSlope: 0
|
||||
tangentMode: 136
|
||||
weightedMode: 0
|
||||
inWeight: 0.33333334
|
||||
outWeight: 0.33333334
|
||||
m_PreInfinity: 2
|
||||
m_PostInfinity: 2
|
||||
m_RotationOrder: 4
|
||||
attribute: m_LocalPosition.z
|
||||
path:
|
||||
classID: 4
|
||||
script: {fileID: 0}
|
||||
m_EulerEditorCurves: []
|
||||
m_HasGenericRootTransform: 1
|
||||
m_HasMotionFloatCurves: 0
|
||||
m_GenerateMotionCurves: 0
|
||||
m_Events: []
|
|
@ -0,0 +1,8 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 509dd06e376974a80be87395ca1da5b8
|
||||
NativeFormatImporter:
|
||||
externalObjects: {}
|
||||
mainObjectFileID: 7400000
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,199 @@
|
|||
%YAML 1.1
|
||||
%TAG !u! tag:unity3d.com,2011:
|
||||
--- !u!74 &7400000
|
||||
AnimationClip:
|
||||
m_ObjectHideFlags: 0
|
||||
m_PrefabParentObject: {fileID: 0}
|
||||
m_PrefabInternal: {fileID: 0}
|
||||
m_Name: PortalSpin
|
||||
serializedVersion: 6
|
||||
m_Legacy: 0
|
||||
m_Compressed: 0
|
||||
m_UseHighQualityCurve: 1
|
||||
m_RotationCurves: []
|
||||
m_CompressedRotationCurves: []
|
||||
m_EulerCurves:
|
||||
- curve:
|
||||
serializedVersion: 2
|
||||
m_Curve:
|
||||
- serializedVersion: 3
|
||||
time: 0
|
||||
value: {x: 0, y: 0, z: 0}
|
||||
inSlope: {x: 0, y: 0, z: 0}
|
||||
outSlope: {x: 0, y: 0, z: 360}
|
||||
tangentMode: 0
|
||||
weightedMode: 0
|
||||
inWeight: {x: 0.33333334, y: 0.33333334, z: 0.33333334}
|
||||
outWeight: {x: 0.33333334, y: 0.33333334, z: 0.33333334}
|
||||
- serializedVersion: 3
|
||||
time: 1
|
||||
value: {x: 0, y: 0, z: 360}
|
||||
inSlope: {x: 0, y: 0, z: 360}
|
||||
outSlope: {x: 0, y: 0, z: 0}
|
||||
tangentMode: 0
|
||||
weightedMode: 0
|
||||
inWeight: {x: 0.33333334, y: 0.33333334, z: 0.33333334}
|
||||
outWeight: {x: 0.33333334, y: 0.33333334, z: 0.33333334}
|
||||
m_PreInfinity: 2
|
||||
m_PostInfinity: 2
|
||||
m_RotationOrder: 4
|
||||
path:
|
||||
m_PositionCurves: []
|
||||
m_ScaleCurves: []
|
||||
m_FloatCurves: []
|
||||
m_PPtrCurves: []
|
||||
m_SampleRate: 60
|
||||
m_WrapMode: 0
|
||||
m_Bounds:
|
||||
m_Center: {x: 0, y: 0, z: 0}
|
||||
m_Extent: {x: 0, y: 0, z: 0}
|
||||
m_ClipBindingConstant:
|
||||
genericBindings:
|
||||
- serializedVersion: 2
|
||||
path: 0
|
||||
attribute: 4
|
||||
script: {fileID: 0}
|
||||
typeID: 4
|
||||
customType: 4
|
||||
isPPtrCurve: 0
|
||||
pptrCurveMapping: []
|
||||
m_AnimationClipSettings:
|
||||
serializedVersion: 2
|
||||
m_AdditiveReferencePoseClip: {fileID: 0}
|
||||
m_AdditiveReferencePoseTime: 0
|
||||
m_StartTime: 0
|
||||
m_StopTime: 1
|
||||
m_OrientationOffsetY: 0
|
||||
m_Level: 0
|
||||
m_CycleOffset: 0
|
||||
m_HasAdditiveReferencePose: 0
|
||||
m_LoopTime: 1
|
||||
m_LoopBlend: 0
|
||||
m_LoopBlendOrientation: 0
|
||||
m_LoopBlendPositionY: 0
|
||||
m_LoopBlendPositionXZ: 0
|
||||
m_KeepOriginalOrientation: 0
|
||||
m_KeepOriginalPositionY: 1
|
||||
m_KeepOriginalPositionXZ: 0
|
||||
m_HeightFromFeet: 0
|
||||
m_Mirror: 0
|
||||
m_EditorCurves:
|
||||
- curve:
|
||||
serializedVersion: 2
|
||||
m_Curve:
|
||||
- serializedVersion: 3
|
||||
time: 0
|
||||
value: 0
|
||||
inSlope: 0
|
||||
outSlope: 0
|
||||
tangentMode: 136
|
||||
weightedMode: 0
|
||||
inWeight: 0.33333334
|
||||
outWeight: 0.33333334
|
||||
- serializedVersion: 3
|
||||
time: 1
|
||||
value: 0
|
||||
inSlope: 0
|
||||
outSlope: 0
|
||||
tangentMode: 136
|
||||
weightedMode: 0
|
||||
inWeight: 0.33333334
|
||||
outWeight: 0.33333334
|
||||
m_PreInfinity: 2
|
||||
m_PostInfinity: 2
|
||||
m_RotationOrder: 4
|
||||
attribute: localEulerAnglesRaw.x
|
||||
path:
|
||||
classID: 4
|
||||
script: {fileID: 0}
|
||||
- curve:
|
||||
serializedVersion: 2
|
||||
m_Curve:
|
||||
- serializedVersion: 3
|
||||
time: 0
|
||||
value: 0
|
||||
inSlope: 0
|
||||
outSlope: 0
|
||||
tangentMode: 136
|
||||
weightedMode: 0
|
||||
inWeight: 0.33333334
|
||||
outWeight: 0.33333334
|
||||
- serializedVersion: 3
|
||||
time: 1
|
||||
value: 0
|
||||
inSlope: 0
|
||||
outSlope: 0
|
||||
tangentMode: 136
|
||||
weightedMode: 0
|
||||
inWeight: 0.33333334
|
||||
outWeight: 0.33333334
|
||||
m_PreInfinity: 2
|
||||
m_PostInfinity: 2
|
||||
m_RotationOrder: 4
|
||||
attribute: localEulerAnglesRaw.y
|
||||
path:
|
||||
classID: 4
|
||||
script: {fileID: 0}
|
||||
- curve:
|
||||
serializedVersion: 2
|
||||
m_Curve:
|
||||
- serializedVersion: 3
|
||||
time: 0
|
||||
value: 0
|
||||
inSlope: 0
|
||||
outSlope: 360
|
||||
tangentMode: 69
|
||||
weightedMode: 0
|
||||
inWeight: 0.33333334
|
||||
outWeight: 0.33333334
|
||||
- serializedVersion: 3
|
||||
time: 1
|
||||
value: 360
|
||||
inSlope: 360
|
||||
outSlope: 0
|
||||
tangentMode: 69
|
||||
weightedMode: 0
|
||||
inWeight: 0.33333334
|
||||
outWeight: 0.33333334
|
||||
m_PreInfinity: 2
|
||||
m_PostInfinity: 2
|
||||
m_RotationOrder: 4
|
||||
attribute: localEulerAnglesRaw.z
|
||||
path:
|
||||
classID: 4
|
||||
script: {fileID: 0}
|
||||
m_EulerEditorCurves:
|
||||
- curve:
|
||||
serializedVersion: 2
|
||||
m_Curve: []
|
||||
m_PreInfinity: 2
|
||||
m_PostInfinity: 2
|
||||
m_RotationOrder: 4
|
||||
attribute: m_LocalEulerAngles.x
|
||||
path:
|
||||
classID: 4
|
||||
script: {fileID: 0}
|
||||
- curve:
|
||||
serializedVersion: 2
|
||||
m_Curve: []
|
||||
m_PreInfinity: 2
|
||||
m_PostInfinity: 2
|
||||
m_RotationOrder: 4
|
||||
attribute: m_LocalEulerAngles.y
|
||||
path:
|
||||
classID: 4
|
||||
script: {fileID: 0}
|
||||
- curve:
|
||||
serializedVersion: 2
|
||||
m_Curve: []
|
||||
m_PreInfinity: 2
|
||||
m_PostInfinity: 2
|
||||
m_RotationOrder: 4
|
||||
attribute: m_LocalEulerAngles.z
|
||||
path:
|
||||
classID: 4
|
||||
script: {fileID: 0}
|
||||
m_HasGenericRootTransform: 1
|
||||
m_HasMotionFloatCurves: 0
|
||||
m_GenerateMotionCurves: 0
|
||||
m_Events: []
|
|
@ -0,0 +1,8 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 369af09a6286845af89edd5fb87ea4ab
|
||||
NativeFormatImporter:
|
||||
externalObjects: {}
|
||||
mainObjectFileID: 7400000
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,69 @@
|
|||
%YAML 1.1
|
||||
%TAG !u! tag:unity3d.com,2011:
|
||||
--- !u!91 &9100000
|
||||
AnimatorController:
|
||||
m_ObjectHideFlags: 0
|
||||
m_PrefabParentObject: {fileID: 0}
|
||||
m_PrefabInternal: {fileID: 0}
|
||||
m_Name: Robot
|
||||
serializedVersion: 5
|
||||
m_AnimatorParameters: []
|
||||
m_AnimatorLayers:
|
||||
- serializedVersion: 5
|
||||
m_Name: Base Layer
|
||||
m_StateMachine: {fileID: 1107790489636618392}
|
||||
m_Mask: {fileID: 0}
|
||||
m_Motions: []
|
||||
m_Behaviours: []
|
||||
m_BlendingMode: 0
|
||||
m_SyncedLayerIndex: -1
|
||||
m_DefaultWeight: 0
|
||||
m_IKPass: 0
|
||||
m_SyncedLayerAffectsTiming: 0
|
||||
m_Controller: {fileID: 9100000}
|
||||
--- !u!1102 &1102928324420026016
|
||||
AnimatorState:
|
||||
serializedVersion: 5
|
||||
m_ObjectHideFlags: 1
|
||||
m_PrefabParentObject: {fileID: 0}
|
||||
m_PrefabInternal: {fileID: 0}
|
||||
m_Name: RobotSpawn
|
||||
m_Speed: 1
|
||||
m_CycleOffset: 0
|
||||
m_Transitions: []
|
||||
m_StateMachineBehaviours: []
|
||||
m_Position: {x: 50, y: 50, z: 0}
|
||||
m_IKOnFeet: 0
|
||||
m_WriteDefaultValues: 1
|
||||
m_Mirror: 0
|
||||
m_SpeedParameterActive: 0
|
||||
m_MirrorParameterActive: 0
|
||||
m_CycleOffsetParameterActive: 0
|
||||
m_TimeParameterActive: 0
|
||||
m_Motion: {fileID: 7400000, guid: e0cdbf2bd85184df4876857725a99162, type: 2}
|
||||
m_Tag:
|
||||
m_SpeedParameter:
|
||||
m_MirrorParameter:
|
||||
m_CycleOffsetParameter:
|
||||
m_TimeParameter:
|
||||
--- !u!1107 &1107790489636618392
|
||||
AnimatorStateMachine:
|
||||
serializedVersion: 5
|
||||
m_ObjectHideFlags: 1
|
||||
m_PrefabParentObject: {fileID: 0}
|
||||
m_PrefabInternal: {fileID: 0}
|
||||
m_Name: Base Layer
|
||||
m_ChildStates:
|
||||
- serializedVersion: 1
|
||||
m_State: {fileID: 1102928324420026016}
|
||||
m_Position: {x: 200, y: 0, z: 0}
|
||||
m_ChildStateMachines: []
|
||||
m_AnyStateTransitions: []
|
||||
m_EntryTransitions: []
|
||||
m_StateMachineTransitions: {}
|
||||
m_StateMachineBehaviours: []
|
||||
m_AnyStatePosition: {x: 50, y: 20, z: 0}
|
||||
m_EntryPosition: {x: 50, y: 120, z: 0}
|
||||
m_ExitPosition: {x: 800, y: 120, z: 0}
|
||||
m_ParentStateMachinePosition: {x: 800, y: 20, z: 0}
|
||||
m_DefaultState: {fileID: 1102928324420026016}
|
|
@ -0,0 +1,8 @@
|
|||
fileFormatVersion: 2
|
||||
guid: fcb592e7f51614bc6be3d2034b632324
|
||||
NativeFormatImporter:
|
||||
externalObjects: {}
|
||||
mainObjectFileID: 9100000
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,116 @@
|
|||
%YAML 1.1
|
||||
%TAG !u! tag:unity3d.com,2011:
|
||||
--- !u!74 &7400000
|
||||
AnimationClip:
|
||||
m_ObjectHideFlags: 0
|
||||
m_PrefabParentObject: {fileID: 0}
|
||||
m_PrefabInternal: {fileID: 0}
|
||||
m_Name: RobotSpawn
|
||||
serializedVersion: 6
|
||||
m_Legacy: 0
|
||||
m_Compressed: 0
|
||||
m_UseHighQualityCurve: 1
|
||||
m_RotationCurves: []
|
||||
m_CompressedRotationCurves: []
|
||||
m_EulerCurves: []
|
||||
m_PositionCurves: []
|
||||
m_ScaleCurves: []
|
||||
m_FloatCurves:
|
||||
- curve:
|
||||
serializedVersion: 2
|
||||
m_Curve:
|
||||
- serializedVersion: 3
|
||||
time: 0
|
||||
value: 0
|
||||
inSlope: 0
|
||||
outSlope: 0
|
||||
tangentMode: 136
|
||||
weightedMode: 0
|
||||
inWeight: 0.33333334
|
||||
outWeight: 0.33333334
|
||||
- serializedVersion: 3
|
||||
time: 1
|
||||
value: 1
|
||||
inSlope: 0
|
||||
outSlope: 0
|
||||
tangentMode: 136
|
||||
weightedMode: 0
|
||||
inWeight: 0.33333334
|
||||
outWeight: 0.33333334
|
||||
m_PreInfinity: 2
|
||||
m_PostInfinity: 2
|
||||
m_RotationOrder: 4
|
||||
attribute: m_Color.a
|
||||
path:
|
||||
classID: 212
|
||||
script: {fileID: 0}
|
||||
m_PPtrCurves: []
|
||||
m_SampleRate: 60
|
||||
m_WrapMode: 0
|
||||
m_Bounds:
|
||||
m_Center: {x: 0, y: 0, z: 0}
|
||||
m_Extent: {x: 0, y: 0, z: 0}
|
||||
m_ClipBindingConstant:
|
||||
genericBindings:
|
||||
- serializedVersion: 2
|
||||
path: 0
|
||||
attribute: 304273561
|
||||
script: {fileID: 0}
|
||||
typeID: 212
|
||||
customType: 0
|
||||
isPPtrCurve: 0
|
||||
pptrCurveMapping: []
|
||||
m_AnimationClipSettings:
|
||||
serializedVersion: 2
|
||||
m_AdditiveReferencePoseClip: {fileID: 0}
|
||||
m_AdditiveReferencePoseTime: 0
|
||||
m_StartTime: 0
|
||||
m_StopTime: 1
|
||||
m_OrientationOffsetY: 0
|
||||
m_Level: 0
|
||||
m_CycleOffset: 0
|
||||
m_HasAdditiveReferencePose: 0
|
||||
m_LoopTime: 0
|
||||
m_LoopBlend: 0
|
||||
m_LoopBlendOrientation: 0
|
||||
m_LoopBlendPositionY: 0
|
||||
m_LoopBlendPositionXZ: 0
|
||||
m_KeepOriginalOrientation: 0
|
||||
m_KeepOriginalPositionY: 1
|
||||
m_KeepOriginalPositionXZ: 0
|
||||
m_HeightFromFeet: 0
|
||||
m_Mirror: 0
|
||||
m_EditorCurves:
|
||||
- curve:
|
||||
serializedVersion: 2
|
||||
m_Curve:
|
||||
- serializedVersion: 3
|
||||
time: 0
|
||||
value: 0
|
||||
inSlope: 0
|
||||
outSlope: 0
|
||||
tangentMode: 136
|
||||
weightedMode: 0
|
||||
inWeight: 0.33333334
|
||||
outWeight: 0.33333334
|
||||
- serializedVersion: 3
|
||||
time: 1
|
||||
value: 1
|
||||
inSlope: 0
|
||||
outSlope: 0
|
||||
tangentMode: 136
|
||||
weightedMode: 0
|
||||
inWeight: 0.33333334
|
||||
outWeight: 0.33333334
|
||||
m_PreInfinity: 2
|
||||
m_PostInfinity: 2
|
||||
m_RotationOrder: 4
|
||||
attribute: m_Color.a
|
||||
path:
|
||||
classID: 212
|
||||
script: {fileID: 0}
|
||||
m_EulerEditorCurves: []
|
||||
m_HasGenericRootTransform: 0
|
||||
m_HasMotionFloatCurves: 0
|
||||
m_GenerateMotionCurves: 0
|
||||
m_Events: []
|
|
@ -0,0 +1,8 @@
|
|||
fileFormatVersion: 2
|
||||
guid: e0cdbf2bd85184df4876857725a99162
|
||||
NativeFormatImporter:
|
||||
externalObjects: {}
|
||||
mainObjectFileID: 7400000
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,69 @@
|
|||
%YAML 1.1
|
||||
%TAG !u! tag:unity3d.com,2011:
|
||||
--- !u!91 &9100000
|
||||
AnimatorController:
|
||||
m_ObjectHideFlags: 0
|
||||
m_PrefabParentObject: {fileID: 0}
|
||||
m_PrefabInternal: {fileID: 0}
|
||||
m_Name: Spawner
|
||||
serializedVersion: 5
|
||||
m_AnimatorParameters: []
|
||||
m_AnimatorLayers:
|
||||
- serializedVersion: 5
|
||||
m_Name: Base Layer
|
||||
m_StateMachine: {fileID: 1107650806890895214}
|
||||
m_Mask: {fileID: 0}
|
||||
m_Motions: []
|
||||
m_Behaviours: []
|
||||
m_BlendingMode: 0
|
||||
m_SyncedLayerIndex: -1
|
||||
m_DefaultWeight: 0
|
||||
m_IKPass: 0
|
||||
m_SyncedLayerAffectsTiming: 0
|
||||
m_Controller: {fileID: 9100000}
|
||||
--- !u!1102 &1102004645330244398
|
||||
AnimatorState:
|
||||
serializedVersion: 5
|
||||
m_ObjectHideFlags: 1
|
||||
m_PrefabParentObject: {fileID: 0}
|
||||
m_PrefabInternal: {fileID: 0}
|
||||
m_Name: PortalSpin
|
||||
m_Speed: 0.1
|
||||
m_CycleOffset: 0
|
||||
m_Transitions: []
|
||||
m_StateMachineBehaviours: []
|
||||
m_Position: {x: 50, y: 50, z: 0}
|
||||
m_IKOnFeet: 0
|
||||
m_WriteDefaultValues: 1
|
||||
m_Mirror: 0
|
||||
m_SpeedParameterActive: 0
|
||||
m_MirrorParameterActive: 0
|
||||
m_CycleOffsetParameterActive: 0
|
||||
m_TimeParameterActive: 0
|
||||
m_Motion: {fileID: 7400000, guid: 369af09a6286845af89edd5fb87ea4ab, type: 2}
|
||||
m_Tag:
|
||||
m_SpeedParameter:
|
||||
m_MirrorParameter:
|
||||
m_CycleOffsetParameter:
|
||||
m_TimeParameter:
|
||||
--- !u!1107 &1107650806890895214
|
||||
AnimatorStateMachine:
|
||||
serializedVersion: 5
|
||||
m_ObjectHideFlags: 1
|
||||
m_PrefabParentObject: {fileID: 0}
|
||||
m_PrefabInternal: {fileID: 0}
|
||||
m_Name: Base Layer
|
||||
m_ChildStates:
|
||||
- serializedVersion: 1
|
||||
m_State: {fileID: 1102004645330244398}
|
||||
m_Position: {x: 288, y: 12, z: 0}
|
||||
m_ChildStateMachines: []
|
||||
m_AnyStateTransitions: []
|
||||
m_EntryTransitions: []
|
||||
m_StateMachineTransitions: {}
|
||||
m_StateMachineBehaviours: []
|
||||
m_AnyStatePosition: {x: 50, y: 20, z: 0}
|
||||
m_EntryPosition: {x: 50, y: 120, z: 0}
|
||||
m_ExitPosition: {x: 800, y: 120, z: 0}
|
||||
m_ParentStateMachinePosition: {x: 800, y: 20, z: 0}
|
||||
m_DefaultState: {fileID: 1102004645330244398}
|
|
@ -0,0 +1,8 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 218385955853b4c2aa8e61d73c9ccf9a
|
||||
NativeFormatImporter:
|
||||
externalObjects: {}
|
||||
mainObjectFileID: 9100000
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,7 @@
|
|||
fileFormatVersion: 2
|
||||
guid: cbc636f930f78c841a91c76a805bdfec
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,8 @@
|
|||
fileFormatVersion: 2
|
||||
guid: bc50aa7d3c68e401fb3939c922f370de
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,76 @@
|
|||
%YAML 1.1
|
||||
%TAG !u! tag:unity3d.com,2011:
|
||||
--- !u!21 &2100000
|
||||
Material:
|
||||
serializedVersion: 6
|
||||
m_ObjectHideFlags: 0
|
||||
m_PrefabParentObject: {fileID: 0}
|
||||
m_PrefabInternal: {fileID: 0}
|
||||
m_Name: Wall
|
||||
m_Shader: {fileID: 10755, guid: 0000000000000000f000000000000000, type: 0}
|
||||
m_ShaderKeywords:
|
||||
m_LightmapFlags: 4
|
||||
m_EnableInstancingVariants: 0
|
||||
m_DoubleSidedGI: 0
|
||||
m_CustomRenderQueue: -1
|
||||
stringTagMap: {}
|
||||
disabledShaderPasses: []
|
||||
m_SavedProperties:
|
||||
serializedVersion: 3
|
||||
m_TexEnvs:
|
||||
- _BumpMap:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- _DetailAlbedoMap:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- _DetailMask:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- _DetailNormalMap:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- _EmissionMap:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- _MainTex:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- _MetallicGlossMap:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- _OcclusionMap:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- _ParallaxMap:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
m_Floats:
|
||||
- _BumpScale: 1
|
||||
- _Cutoff: 0.5
|
||||
- _DetailNormalMapScale: 1
|
||||
- _DstBlend: 0
|
||||
- _GlossMapScale: 1
|
||||
- _Glossiness: 0.5
|
||||
- _GlossyReflections: 1
|
||||
- _Metallic: 0
|
||||
- _Mode: 0
|
||||
- _OcclusionStrength: 1
|
||||
- _Parallax: 0.02
|
||||
- _SmoothnessTextureChannel: 0
|
||||
- _SpecularHighlights: 1
|
||||
- _SrcBlend: 1
|
||||
- _UVSec: 0
|
||||
- _ZWrite: 1
|
||||
m_Colors:
|
||||
- _Color: {r: 0, g: 0, b: 0, a: 1}
|
||||
- _EmissionColor: {r: 0, g: 0, b: 0, a: 1}
|
|
@ -0,0 +1,8 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 74fff7569131340688b27f2f282eee79
|
||||
NativeFormatImporter:
|
||||
externalObjects: {}
|
||||
mainObjectFileID: 2100000
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,8 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 58f99f13eb6344631a9c68dc36ae0da2
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,8 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 936e24cdf062b45d7a0d2fecc1c4645f
|
||||
NativeFormatImporter:
|
||||
externalObjects: {}
|
||||
mainObjectFileID: 100100000
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,8 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 6aaea0b280ad247e6b395b06007de823
|
||||
NativeFormatImporter:
|
||||
externalObjects: {}
|
||||
mainObjectFileID: 100100000
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,10 @@
|
|||
{
|
||||
"name": "QFSW.QC.Demo",
|
||||
"references": [
|
||||
"QFSW.QC"
|
||||
],
|
||||
"optionalUnityReferences": [],
|
||||
"includePlatforms": [],
|
||||
"excludePlatforms": [],
|
||||
"allowUnsafeCode": false
|
||||
}
|
|
@ -0,0 +1,7 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 81dcdc43a74004ddaa6ad1d5df1941d9
|
||||
AssemblyDefinitionImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,8 @@
|
|||
fileFormatVersion: 2
|
||||
guid: c52af6b1dac954e92b05a602b0bd809e
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,15 @@
|
|||
using UnityEngine;
|
||||
|
||||
namespace QFSW.QC.Demo
|
||||
{
|
||||
[CommandPrefix("demo.gate.")]
|
||||
public class Gate : MonoBehaviour
|
||||
{
|
||||
[Command("opened")]
|
||||
private bool IsOpened
|
||||
{
|
||||
get { return GetComponent<Animator>().GetBool("opened"); }
|
||||
set { GetComponent<Animator>().SetBool("opened", value); }
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 06154700427c64e98af05ecbe66cac48
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,63 @@
|
|||
using QFSW.QC.Actions;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
namespace QFSW.QC.Demo
|
||||
{
|
||||
[CommandPrefix("demo.robot.")]
|
||||
public class Robot : MonoBehaviour
|
||||
{
|
||||
[SerializeField] private GameObject deathFX = null;
|
||||
|
||||
[Command("speed")]
|
||||
private static float robotSpeed = 25f;
|
||||
|
||||
[Command("rotation-speed")]
|
||||
private static float robotRotationSpeed = 40f;
|
||||
|
||||
private Vector2 direction;
|
||||
|
||||
private void Start()
|
||||
{
|
||||
SpriteRenderer rend = GetComponent<SpriteRenderer>();
|
||||
rend.color = new Color(Random.Range(0f, 1f), Random.Range(0f, 1f), Random.Range(0f, 1f), 1);
|
||||
|
||||
float size = Random.Range(0.8f, 1.2f);
|
||||
transform.localScale = new Vector3(size, size, size);
|
||||
|
||||
direction = Quaternion.Euler(0, 0, Random.Range(0, 306f)) * Vector3.up;
|
||||
}
|
||||
|
||||
private void FixedUpdate()
|
||||
{
|
||||
GetComponent<Rigidbody2D>().AddForce(direction * robotSpeed * Time.fixedDeltaTime, ForceMode2D.Force);
|
||||
direction = Quaternion.Euler(0, 0, robotRotationSpeed * Time.fixedDeltaTime) * direction;
|
||||
}
|
||||
|
||||
[Command("kill")]
|
||||
private static IEnumerator<ICommandAction> KillAction()
|
||||
{
|
||||
Robot robot = default;
|
||||
IEnumerable<Robot> robots = InvocationTargetFactory.FindTargets<Robot>(MonoTargetType.All);
|
||||
|
||||
yield return new Value("Please select a robot");
|
||||
yield return new Choice<Robot>(robots, r => robot = r);
|
||||
|
||||
robot.Die();
|
||||
yield return new Typewriter($"{robot.name} has been killed");
|
||||
}
|
||||
|
||||
[Command("kill-all", MonoTargetType.All)]
|
||||
public void Die()
|
||||
{
|
||||
Destroy(gameObject);
|
||||
Destroy(Instantiate(deathFX, transform.position, Quaternion.identity), 3);
|
||||
}
|
||||
|
||||
[Command("position", MonoTargetType.All)]
|
||||
private Vector3 GetPosition()
|
||||
{
|
||||
return transform.position;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 0b1afda062bbc4058bf752265765c413
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,32 @@
|
|||
using QFSW.QC.Utilities;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
|
||||
namespace QFSW.QC.Demo
|
||||
{
|
||||
public class RobotCollector : MonoBehaviour
|
||||
{
|
||||
[SerializeField] private Text text = null;
|
||||
[SerializeField] private QuantumTheme theme = null;
|
||||
|
||||
public int RescueCount { [Command("demo.rescue-count")] get; set; }
|
||||
|
||||
private void Start() { UpdateText(); }
|
||||
private void UpdateText()
|
||||
{
|
||||
if (!theme) { text.text = $"{RescueCount} robots saved"; }
|
||||
else { text.text = $"{RescueCount.ToString().ColorText(theme.DefaultReturnValueColor)} robots saved"; }
|
||||
}
|
||||
|
||||
private void OnCollisionEnter2D(Collision2D collision)
|
||||
{
|
||||
if (collision.gameObject.CompareTag("Player"))
|
||||
{
|
||||
Robot robot = collision.gameObject.GetComponent<Robot>();
|
||||
robot.Die();
|
||||
RescueCount++;
|
||||
UpdateText();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 8089849882bad4d37821d7ee458144e3
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,41 @@
|
|||
using QFSW.QC.Utilities;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
|
||||
namespace QFSW.QC.Demo
|
||||
{
|
||||
public class RobotSpawner : MonoBehaviour
|
||||
{
|
||||
[SerializeField] private Robot robotPrefab = null;
|
||||
[SerializeField] private Text text = null;
|
||||
[SerializeField] private QuantumTheme theme = null;
|
||||
|
||||
public int SpawnCount { [Command("demo.spawn-count")] get; private set; }
|
||||
|
||||
private void Start()
|
||||
{
|
||||
UpdateText();
|
||||
SpawnRobot(3);
|
||||
}
|
||||
|
||||
private void UpdateText()
|
||||
{
|
||||
if (!theme) { text.text = $"{SpawnCount} robots spawned"; }
|
||||
else { text.text = $"{SpawnCount.ToString().ColorText(theme.DefaultReturnValueColor)} robots spawned"; }
|
||||
}
|
||||
|
||||
[Command("demo.spawn-robot", MonoTargetType.Single)]
|
||||
private void SpawnRobot(int count = 1)
|
||||
{
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
SpawnCount++;
|
||||
Vector3 position = transform.position;
|
||||
position += new Vector3(Random.Range(-1f, 1f), Random.Range(-1f, 1f));
|
||||
Instantiate(robotPrefab, position, Quaternion.identity).name = $"Robot {SpawnCount}";
|
||||
}
|
||||
|
||||
UpdateText();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: d5db368681e5f4c6eb1e484e8d786e27
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,8 @@
|
|||
fileFormatVersion: 2
|
||||
guid: b260e8963b08448ca8ae2d294cd86a9d
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
After Width: | Height: | Size: 9.6 KiB |
|
@ -0,0 +1,106 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 21fb6714fde0b41b9ba9639d03f5a2a6
|
||||
TextureImporter:
|
||||
fileIDToRecycleName: {}
|
||||
externalObjects: {}
|
||||
serializedVersion: 5
|
||||
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
|
||||
isReadable: 0
|
||||
grayScaleToAlpha: 0
|
||||
generateCubemap: 6
|
||||
cubemapConvolution: 0
|
||||
seamlessCubemap: 0
|
||||
textureFormat: 1
|
||||
maxTextureSize: 2048
|
||||
textureSettings:
|
||||
serializedVersion: 2
|
||||
filterMode: -1
|
||||
aniso: -1
|
||||
mipBias: -1
|
||||
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: 250
|
||||
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
|
||||
spriteGenerateFallbackPhysicsShape: 1
|
||||
alphaUsage: 1
|
||||
alphaIsTransparency: 1
|
||||
spriteTessellationDetail: -1
|
||||
textureType: 8
|
||||
textureShape: 1
|
||||
singleChannelComponent: 0
|
||||
maxTextureSizeSet: 0
|
||||
compressionQualitySet: 0
|
||||
textureFormatSet: 0
|
||||
platformSettings:
|
||||
- serializedVersion: 2
|
||||
buildTarget: DefaultTexturePlatform
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
- serializedVersion: 2
|
||||
buildTarget: Standalone
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
- serializedVersion: 2
|
||||
buildTarget: WebGL
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
spriteSheet:
|
||||
serializedVersion: 2
|
||||
sprites: []
|
||||
outline: []
|
||||
physicsShape: []
|
||||
bones: []
|
||||
spriteID: 74ba36e6ac0d745c797b45b2c532ddd4
|
||||
vertices: []
|
||||
indices:
|
||||
edges: []
|
||||
weights: []
|
||||
spritePackingTag:
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
After Width: | Height: | Size: 29 KiB |
|
@ -0,0 +1,106 @@
|
|||
fileFormatVersion: 2
|
||||
guid: c1df40d40cc814a5695dee0e707cc03a
|
||||
TextureImporter:
|
||||
fileIDToRecycleName: {}
|
||||
externalObjects: {}
|
||||
serializedVersion: 5
|
||||
mipmaps:
|
||||
mipMapMode: 0
|
||||
enableMipMap: 1
|
||||
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
|
||||
isReadable: 0
|
||||
grayScaleToAlpha: 0
|
||||
generateCubemap: 6
|
||||
cubemapConvolution: 0
|
||||
seamlessCubemap: 0
|
||||
textureFormat: 1
|
||||
maxTextureSize: 2048
|
||||
textureSettings:
|
||||
serializedVersion: 2
|
||||
filterMode: 2
|
||||
aniso: -1
|
||||
mipBias: -1
|
||||
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
|
||||
maxTextureSizeSet: 0
|
||||
compressionQualitySet: 0
|
||||
textureFormatSet: 0
|
||||
platformSettings:
|
||||
- serializedVersion: 2
|
||||
buildTarget: DefaultTexturePlatform
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 2
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
- serializedVersion: 2
|
||||
buildTarget: Standalone
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 2
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
- serializedVersion: 2
|
||||
buildTarget: WebGL
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 2
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
spriteSheet:
|
||||
serializedVersion: 2
|
||||
sprites: []
|
||||
outline: []
|
||||
physicsShape: []
|
||||
bones: []
|
||||
spriteID: 23ecb33d1ab634744b034264cd11fdc3
|
||||
vertices: []
|
||||
indices:
|
||||
edges: []
|
||||
weights: []
|
||||
spritePackingTag:
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
After Width: | Height: | Size: 1.6 KiB |
|
@ -0,0 +1,106 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 8cc6f758dd676460aac0a91f8280a09d
|
||||
TextureImporter:
|
||||
fileIDToRecycleName: {}
|
||||
externalObjects: {}
|
||||
serializedVersion: 5
|
||||
mipmaps:
|
||||
mipMapMode: 0
|
||||
enableMipMap: 1
|
||||
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
|
||||
isReadable: 0
|
||||
grayScaleToAlpha: 0
|
||||
generateCubemap: 6
|
||||
cubemapConvolution: 0
|
||||
seamlessCubemap: 0
|
||||
textureFormat: 1
|
||||
maxTextureSize: 2048
|
||||
textureSettings:
|
||||
serializedVersion: 2
|
||||
filterMode: -1
|
||||
aniso: -1
|
||||
mipBias: -1
|
||||
wrapU: 1
|
||||
wrapV: 1
|
||||
wrapW: 1
|
||||
nPOTScale: 0
|
||||
lightmap: 0
|
||||
compressionQuality: 50
|
||||
spriteMode: 3
|
||||
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
|
||||
maxTextureSizeSet: 0
|
||||
compressionQualitySet: 0
|
||||
textureFormatSet: 0
|
||||
platformSettings:
|
||||
- serializedVersion: 2
|
||||
buildTarget: DefaultTexturePlatform
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
- serializedVersion: 2
|
||||
buildTarget: Standalone
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
- serializedVersion: 2
|
||||
buildTarget: WebGL
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
spriteSheet:
|
||||
serializedVersion: 2
|
||||
sprites: []
|
||||
outline: []
|
||||
physicsShape: []
|
||||
bones: []
|
||||
spriteID: 3feb5bdcb77204fdd9c897cd167575ea
|
||||
vertices: []
|
||||
indices:
|
||||
edges: []
|
||||
weights: []
|
||||
spritePackingTag:
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
After Width: | Height: | Size: 3.2 KiB |
|
@ -0,0 +1,106 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 19ace80b238594f46b6f69852fb1f584
|
||||
TextureImporter:
|
||||
fileIDToRecycleName: {}
|
||||
externalObjects: {}
|
||||
serializedVersion: 5
|
||||
mipmaps:
|
||||
mipMapMode: 0
|
||||
enableMipMap: 1
|
||||
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
|
||||
isReadable: 0
|
||||
grayScaleToAlpha: 0
|
||||
generateCubemap: 6
|
||||
cubemapConvolution: 0
|
||||
seamlessCubemap: 0
|
||||
textureFormat: 1
|
||||
maxTextureSize: 2048
|
||||
textureSettings:
|
||||
serializedVersion: 2
|
||||
filterMode: -1
|
||||
aniso: -1
|
||||
mipBias: -1
|
||||
wrapU: 1
|
||||
wrapV: 1
|
||||
wrapW: 1
|
||||
nPOTScale: 0
|
||||
lightmap: 0
|
||||
compressionQuality: 50
|
||||
spriteMode: 3
|
||||
spriteExtrude: 1
|
||||
spriteMeshType: 1
|
||||
alignment: 0
|
||||
spritePivot: {x: 0.5, y: 0.5}
|
||||
spritePixelsToUnits: 200
|
||||
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
|
||||
spriteGenerateFallbackPhysicsShape: 1
|
||||
alphaUsage: 1
|
||||
alphaIsTransparency: 1
|
||||
spriteTessellationDetail: -1
|
||||
textureType: 8
|
||||
textureShape: 1
|
||||
singleChannelComponent: 0
|
||||
maxTextureSizeSet: 0
|
||||
compressionQualitySet: 0
|
||||
textureFormatSet: 0
|
||||
platformSettings:
|
||||
- serializedVersion: 2
|
||||
buildTarget: DefaultTexturePlatform
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
- serializedVersion: 2
|
||||
buildTarget: Standalone
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
- serializedVersion: 2
|
||||
buildTarget: WebGL
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
spriteSheet:
|
||||
serializedVersion: 2
|
||||
sprites: []
|
||||
outline: []
|
||||
physicsShape: []
|
||||
bones: []
|
||||
spriteID: 5e7a1b038cc18484292116f59906d7b7
|
||||
vertices: []
|
||||
indices:
|
||||
edges: []
|
||||
weights: []
|
||||
spritePackingTag:
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,8 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 952ba3bc3099845f7b7ba6943e79ce9f
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,14 @@
|
|||
using UnityEngine;
|
||||
|
||||
namespace QFSW.QC.Extras
|
||||
{
|
||||
public static class ApplicationCommands
|
||||
{
|
||||
[Command("quit", "Quits the player application")]
|
||||
[CommandPlatform(Platform.AllPlatforms ^ (Platform.EditorPlatforms | Platform.WebGLPlayer))]
|
||||
private static void Quit()
|
||||
{
|
||||
Application.Quit();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: e9da7f85fdcb033409727f504fdda906
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,24 @@
|
|||
using System;
|
||||
using System.Collections;
|
||||
using UnityEngine;
|
||||
|
||||
namespace QFSW.QC.Extras
|
||||
{
|
||||
[AddComponentMenu("")]
|
||||
public class CoroutineCommands : MonoBehaviour
|
||||
{
|
||||
[Command("start-coroutine", "starts the supplied command as a coroutine", MonoTargetType.Singleton)]
|
||||
private void StartCoroutineCommand(string coroutineCommand)
|
||||
{
|
||||
object coroutineReturn = QuantumConsoleProcessor.InvokeCommand(coroutineCommand);
|
||||
if (coroutineReturn is IEnumerator)
|
||||
{
|
||||
StartCoroutine(coroutineReturn as IEnumerator);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new ArgumentException($"{coroutineCommand} is not a coroutine");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 1a0d171dbb1da05489c852d95745226f
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,115 @@
|
|||
#if UNITY_EDITOR
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
|
||||
namespace QFSW.QC.Extras
|
||||
{
|
||||
internal static class EditorCommands
|
||||
{
|
||||
private static IEnumerable<GameObject> LoadPrefabs(string prefabName, params PrefabAssetType[] prefabTypes)
|
||||
{
|
||||
string filter = $"{prefabName} t:GameObject";
|
||||
string[] guids = AssetDatabase.FindAssets(filter);
|
||||
|
||||
foreach (string guid in guids)
|
||||
{
|
||||
string path = AssetDatabase.GUIDToAssetPath(guid);
|
||||
GameObject obj = AssetDatabase.LoadAssetAtPath<GameObject>(path);
|
||||
|
||||
if (obj.name == prefabName)
|
||||
{
|
||||
if (prefabTypes.Contains(PrefabUtility.GetPrefabAssetType(obj)))
|
||||
{
|
||||
yield return obj;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static T ForceSingle<T>(IEnumerable<T> stream, string errorMessage, string warningMessage)
|
||||
{
|
||||
bool singleFound = false;
|
||||
T single = default;
|
||||
foreach (T item in stream)
|
||||
{
|
||||
if (singleFound)
|
||||
{
|
||||
Debug.LogWarning(warningMessage);
|
||||
break;
|
||||
}
|
||||
|
||||
single = item;
|
||||
singleFound = true;
|
||||
}
|
||||
|
||||
if (singleFound)
|
||||
{
|
||||
return single;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new ArgumentException(errorMessage);
|
||||
}
|
||||
}
|
||||
|
||||
private static GameObject LoadPrefab(string prefabName)
|
||||
{
|
||||
IEnumerable<GameObject> prefabs = LoadPrefabs(prefabName, PrefabAssetType.Regular, PrefabAssetType.Variant);
|
||||
return ForceSingle(prefabs, $"No prefab with the name {prefabName} could be found.", $"Multiple prefabs with the name {prefabName} were found");
|
||||
}
|
||||
|
||||
private static GameObject LoadModel(string modelName)
|
||||
{
|
||||
IEnumerable<GameObject> models = LoadPrefabs(modelName, PrefabAssetType.Model);
|
||||
return ForceSingle(models, $"No model with the name {modelName} could be found.", $"Multiple models with the name {modelName} were found");
|
||||
}
|
||||
|
||||
[Command("instantiate-prefab", "Instantiates a GameObject from the specified prefab", Platform.EditorPlatforms)]
|
||||
private static void InstantiateGOFromPrefab(
|
||||
[CommandParameterDescription("The name of the prefab to instantiate a copy of.")]string prefabName,
|
||||
[CommandParameterDescription("The position of the instantiated GameObject.")]Vector3 position,
|
||||
[CommandParameterDescription("The rotation of the instantiated GameObject.")]Quaternion rotation)
|
||||
{
|
||||
GameObject.Instantiate(LoadPrefab(prefabName), position, rotation);
|
||||
}
|
||||
|
||||
[Command("instantiate-prefab", "Instantiates a GameObject from the specified prefab", Platform.EditorPlatforms)]
|
||||
private static void InstantiateGOFromPrefab(string prefabName, Vector3 position)
|
||||
{
|
||||
GameObject prefab = LoadPrefab(prefabName);
|
||||
GameObject.Instantiate(prefab, position, prefab.transform.rotation);
|
||||
}
|
||||
|
||||
[Command("instantiate-prefab", "Instantiates a GameObject from the specified prefab", Platform.EditorPlatforms)]
|
||||
private static void InstantiateGOFromPrefab(string prefabName)
|
||||
{
|
||||
GameObject.Instantiate(LoadPrefab(prefabName));
|
||||
}
|
||||
|
||||
[Command("instantiate-model", "Instantiates a GameObject from the specified model prefab", Platform.EditorPlatforms)]
|
||||
private static void InstantiateGOFromModelPrefab(
|
||||
[CommandParameterDescription("The name of the model to instantiate a copy of.")]string modelName,
|
||||
[CommandParameterDescription("The position of the instantiated GameObject.")]Vector3 position,
|
||||
[CommandParameterDescription("The rotation of the instantiated GameObject.")]Quaternion rotation)
|
||||
{
|
||||
GameObject.Instantiate(LoadModel(modelName), position, rotation);
|
||||
}
|
||||
|
||||
[Command("instantiate-model", "Instantiates a GameObject from the specified model prefab", Platform.EditorPlatforms)]
|
||||
private static void InstantiateGOFromModelPrefab(string modelName, Vector3 position)
|
||||
{
|
||||
GameObject prefab = LoadModel(modelName);
|
||||
GameObject.Instantiate(prefab, position, prefab.transform.rotation);
|
||||
}
|
||||
|
||||
[Command("instantiate-model", "Instantiates a GameObject from the specified model prefab", Platform.EditorPlatforms)]
|
||||
private static void InstantiateGOFromModelPrefab(string modelName)
|
||||
{
|
||||
GameObject.Instantiate(LoadModel(modelName));
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 15cc172f9ab7e744ebb12f0ac6965c79
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,31 @@
|
|||
using System.IO;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace QFSW.QC.Extras
|
||||
{
|
||||
public static class FileCommands
|
||||
{
|
||||
[Command("write-file", Platform.AllPlatforms ^ Platform.WebGLPlayer)]
|
||||
[CommandDescription("Writes the provided data to a file at the provided path")]
|
||||
private static async Task WriteFile(string path, string data)
|
||||
{
|
||||
FileInfo file = new FileInfo(path);
|
||||
file.Directory?.Create();
|
||||
|
||||
using (StreamWriter writer = new StreamWriter(path))
|
||||
{
|
||||
await writer.WriteAsync(data);
|
||||
}
|
||||
}
|
||||
|
||||
[Command("read-file", Platform.AllPlatforms ^ Platform.WebGLPlayer)]
|
||||
[CommandDescription("Reads the contents of the file at the provided path")]
|
||||
private static string ReadFile(string path)
|
||||
{
|
||||
using (StreamReader reader = new StreamReader(path))
|
||||
{
|
||||
return reader.ReadToEnd();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 4e0016aee4d4b3348a733339a47a9bab
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,28 @@
|
|||
using UnityEngine;
|
||||
|
||||
namespace QFSW.QC.Extras
|
||||
{
|
||||
public static class GraphicsCommands
|
||||
{
|
||||
[Command("max-fps", "the maximum FPS imposed on the application. Set to -1 for unlimited.")]
|
||||
private static int MaxFPS
|
||||
{
|
||||
get => Application.targetFrameRate;
|
||||
set => Application.targetFrameRate = value;
|
||||
}
|
||||
|
||||
[Command("vsync", "enables or disables vsync for the application.")]
|
||||
private static bool VSync
|
||||
{
|
||||
get => QualitySettings.vSyncCount > 0;
|
||||
set => QualitySettings.vSyncCount = value ? 1 : 0;
|
||||
}
|
||||
|
||||
[Command("msaa", "Gets or sets the number of msaa samples in use. Valid values are 0, 2, 4 and 8.")]
|
||||
private static int MSAA
|
||||
{
|
||||
get => QualitySettings.antiAliasing;
|
||||
set => QualitySettings.antiAliasing = value;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 7f64c9104d262446583f03a81c2947fe
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,48 @@
|
|||
using System.Net.Http;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace QFSW.QC.Extras
|
||||
{
|
||||
[CommandPrefix("http.")]
|
||||
public static class HttpCommands
|
||||
{
|
||||
private static readonly HttpClient _client = new HttpClient();
|
||||
|
||||
[Command("get", "Sends a GET request to the specified URL.")]
|
||||
private static async Task<string> Get(string url)
|
||||
{
|
||||
HttpResponseMessage response = await _client.GetAsync(url);
|
||||
|
||||
return await response.Content.ReadAsStringAsync();
|
||||
}
|
||||
|
||||
[Command("delete", "Sends a DELETE request to the specified URL.")]
|
||||
private static async Task<string> Delete(string url)
|
||||
{
|
||||
HttpResponseMessage response = await _client.DeleteAsync(url);
|
||||
|
||||
return await response.Content.ReadAsStringAsync();
|
||||
}
|
||||
|
||||
[Command("post", "Sends a POST request to the specified URL. " +
|
||||
"A body may be sent with the request, with a default mediaType of text/plain.")]
|
||||
private static async Task<string> Post(string url, string content = "", string mediaType = "text/plain")
|
||||
{
|
||||
HttpContent body = new StringContent(content, Encoding.Default, mediaType);
|
||||
HttpResponseMessage response = await _client.PostAsync(url, body);
|
||||
|
||||
return await response.Content.ReadAsStringAsync();
|
||||
}
|
||||
|
||||
[Command("put", "Sends a PUT request to the specified URL. " +
|
||||
"A body may be sent with the request, with a default mediaType of text/plain.")]
|
||||
private static async Task<string> Put(string url, string content = "", string mediaType = "text/plain")
|
||||
{
|
||||
HttpContent body = new StringContent(content, Encoding.Default, mediaType);
|
||||
HttpResponseMessage response = await _client.PutAsync(url, body);
|
||||
|
||||
return await response.Content.ReadAsStringAsync();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: bc59abfc03e45b542947d9dc45bd1e72
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,98 @@
|
|||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using UnityEngine;
|
||||
|
||||
namespace QFSW.QC.Extras
|
||||
{
|
||||
public class KeyBinderModule : MonoBehaviour
|
||||
{
|
||||
private readonly struct Binding
|
||||
{
|
||||
public readonly KeyCode Key;
|
||||
public readonly string Command;
|
||||
|
||||
public Binding(KeyCode key, string command)
|
||||
{
|
||||
Key = key;
|
||||
Command = command;
|
||||
}
|
||||
}
|
||||
|
||||
private readonly List<Binding> _bindings = new List<Binding>();
|
||||
private QuantumConsole _consoleInstance;
|
||||
private bool _blocked = false;
|
||||
|
||||
private void BlockInput() { _blocked = true; }
|
||||
private void UnblockInput() { _blocked = false; }
|
||||
|
||||
private void BindToConsoleInstance()
|
||||
{
|
||||
if (!_consoleInstance) { _consoleInstance = FindObjectOfType<QuantumConsole>(); }
|
||||
if (_consoleInstance)
|
||||
{
|
||||
_consoleInstance.OnActivate += BlockInput;
|
||||
_consoleInstance.OnDeactivate += UnblockInput;
|
||||
|
||||
_blocked = _consoleInstance.IsActive;
|
||||
}
|
||||
else
|
||||
{
|
||||
UnblockInput();
|
||||
}
|
||||
}
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
BindToConsoleInstance();
|
||||
}
|
||||
|
||||
private void Update()
|
||||
{
|
||||
if (!_blocked)
|
||||
{
|
||||
foreach (Binding binding in _bindings)
|
||||
{
|
||||
if (InputHelper.GetKeyDown(binding.Key))
|
||||
{
|
||||
try
|
||||
{
|
||||
QuantumConsoleProcessor.InvokeCommand(binding.Command);
|
||||
}
|
||||
catch (System.Exception e) { Debug.LogException(e); }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[Command("bind", MonoTargetType.Singleton)]
|
||||
[CommandDescription("Binds a given command to a given key, so that every time the key is pressed, the command is invoked.")]
|
||||
private void AddBinding(KeyCode key, string command)
|
||||
{
|
||||
_bindings.Add(new Binding(key, command));
|
||||
}
|
||||
|
||||
[Command("unbind", MonoTargetType.Singleton)]
|
||||
[CommandDescription("Removes every binding for the given key")]
|
||||
private void RemoveBindings(KeyCode key)
|
||||
{
|
||||
_bindings.RemoveAll(x => x.Key == key);
|
||||
}
|
||||
|
||||
[Command("unbind-all", MonoTargetType.Singleton)]
|
||||
[CommandDescription("Unbinds every existing key binding")]
|
||||
private void RemoveAllBindings()
|
||||
{
|
||||
_bindings.Clear();
|
||||
}
|
||||
|
||||
[Command("display-bindings", MonoTargetType.Singleton)]
|
||||
[CommandDescription("Displays all existing bindings on the key binder")]
|
||||
private IEnumerable<object> DisplayAllBindings()
|
||||
{
|
||||
foreach (Binding binding in _bindings.OrderBy(x => x.Key))
|
||||
{
|
||||
yield return new KeyValuePair<KeyCode, string>(binding.Key, binding.Command);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: fb5d29f1db8b3ac41bea9c4355331a1f
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,249 @@
|
|||
using QFSW.QC.Utilities;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
|
||||
namespace QFSW.QC.Extras
|
||||
{
|
||||
public static class MegaCommands
|
||||
{
|
||||
private static readonly QuantumSerializer Serializer = new QuantumSerializer();
|
||||
private static readonly QuantumParser Parser = new QuantumParser();
|
||||
|
||||
private static MethodInfo[] ExtractMethods(Type type, string name)
|
||||
{
|
||||
const BindingFlags flags = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.InvokeMethod |
|
||||
BindingFlags.Static | BindingFlags.Instance | BindingFlags.FlattenHierarchy;
|
||||
|
||||
MethodInfo[] methods = type.GetMethods(flags).Where(x => x.Name == name).ToArray();
|
||||
if (!methods.Any())
|
||||
{
|
||||
PropertyInfo property = type.GetProperty(name, flags);
|
||||
if (property != null)
|
||||
{
|
||||
methods = new[] {property.GetMethod, property.SetMethod}.Where(x => x != null).ToArray();
|
||||
if (methods.Length > 0)
|
||||
{
|
||||
return methods;
|
||||
}
|
||||
}
|
||||
|
||||
throw new ArgumentException($"No method or property named {name} could be found in class {Serializer.SerializeFormatted(type)}");
|
||||
}
|
||||
|
||||
return methods;
|
||||
}
|
||||
|
||||
private static string GenerateSignature(MethodInfo method)
|
||||
{
|
||||
IEnumerable<string> paramParts = method.GetParameters()
|
||||
.Select(x => (x.Name, x.ParameterType))
|
||||
.Select(x => $"{x.ParameterType.GetDisplayName()} {x.Name}");
|
||||
|
||||
string paramSignature = string.Join(", ", paramParts);
|
||||
return $"{method.Name}({paramSignature})";
|
||||
}
|
||||
|
||||
private static MethodInfo GetIdealOverload(MethodInfo[] methods, bool isStatic, int argc)
|
||||
{
|
||||
methods = methods.Where(x => x.IsStatic == isStatic).ToArray();
|
||||
|
||||
if (methods.Length == 0)
|
||||
{
|
||||
throw new ArgumentException($"No {(isStatic ? "static" : "non-static")} overloads could be found.");
|
||||
}
|
||||
|
||||
if (methods.Length == 1)
|
||||
{
|
||||
return methods[0];
|
||||
}
|
||||
|
||||
methods = methods.Where(x => !x.IsGenericMethod).ToArray();
|
||||
if (methods.Length == 0)
|
||||
{
|
||||
throw new ArgumentException("Generic methods are not supported.");
|
||||
}
|
||||
|
||||
MethodInfo[] argcMatches = methods.Where(x => x.GetParameters().Length == argc).ToArray();
|
||||
if (argcMatches.Length == 1)
|
||||
{
|
||||
return argcMatches[0];
|
||||
}
|
||||
else if (argcMatches.Length == 0)
|
||||
{
|
||||
IEnumerable<string> signatures = methods.Select(GenerateSignature);
|
||||
string combinedSignatures = string.Join("\n", signatures);
|
||||
throw new ArgumentException($"No overloads with {argc} arguments were found. the following overloads are available:\n{combinedSignatures}");
|
||||
}
|
||||
else
|
||||
{
|
||||
IEnumerable<string> signatures = argcMatches.Select(GenerateSignature);
|
||||
string combinedSignatures = string.Join("\n", signatures);
|
||||
throw new ArgumentException($"Multiple overloads with the same argument count were found: please specify the types explicitly.\n{combinedSignatures}");
|
||||
}
|
||||
}
|
||||
|
||||
private static MethodInfo GetIdealOverload(MethodInfo[] methods, bool isStatic, Type[] argTypes)
|
||||
{
|
||||
// Exact matching
|
||||
foreach (MethodInfo method in methods)
|
||||
{
|
||||
if (method.IsStatic == isStatic)
|
||||
{
|
||||
IEnumerable<Type> methodParamTypes = method.GetParameters().Select(x => x.ParameterType);
|
||||
if (methodParamTypes.SequenceEqual(argTypes))
|
||||
{
|
||||
return method;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Polymorphic matching
|
||||
foreach (MethodInfo method in methods)
|
||||
{
|
||||
if (method.IsStatic == isStatic)
|
||||
{
|
||||
ParameterInfo[] methodParams = method.GetParameters();
|
||||
if (methodParams.Length == argTypes.Length)
|
||||
{
|
||||
bool isMatch = methodParams
|
||||
.Select(x => x.ParameterType)
|
||||
.Zip(argTypes, (x, y) => (x, y))
|
||||
.All(pair => pair.x.IsAssignableFrom(pair.y));
|
||||
|
||||
if (isMatch)
|
||||
{
|
||||
return method;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
throw new ArgumentException("No overload with the supplied argument types could be found.");
|
||||
}
|
||||
|
||||
private static object[] CreateArgs(MethodInfo method, string[] rawArgs)
|
||||
{
|
||||
ParameterInfo[] methodParams = method.GetParameters();
|
||||
Type[] argTypes = methodParams.Select(x => x.ParameterType).ToArray();
|
||||
return CreateArgs(method, argTypes, rawArgs);
|
||||
}
|
||||
|
||||
private static object[] CreateArgs(MethodInfo method, Type[] argTypes, string[] rawArgs)
|
||||
{
|
||||
ParameterInfo[] methodParams = method.GetParameters();
|
||||
int defaultArgs = methodParams.Count(x => x.HasDefaultValue);
|
||||
|
||||
if (rawArgs.Length < argTypes.Length - defaultArgs || rawArgs.Length > argTypes.Length)
|
||||
{
|
||||
throw new ArgumentException($"Incorrect number ({rawArgs.Length}) of arguments supplied for {Serializer.SerializeFormatted(method.DeclaringType)}.{method.Name}" +
|
||||
$", expected {argTypes.Length}");
|
||||
}
|
||||
|
||||
object[] parsedArgs = new object[argTypes.Length];
|
||||
for (int i = 0; i < parsedArgs.Length; i++)
|
||||
{
|
||||
if (i < rawArgs.Length)
|
||||
{
|
||||
parsedArgs[i] = Parser.Parse(rawArgs[i], argTypes[i]);
|
||||
}
|
||||
else
|
||||
{
|
||||
parsedArgs[i] = methodParams[i].DefaultValue;
|
||||
}
|
||||
}
|
||||
|
||||
return parsedArgs;
|
||||
}
|
||||
|
||||
private static object InvokeAndUnwrapException(this MethodInfo method, object[] args)
|
||||
{
|
||||
try
|
||||
{
|
||||
return method.Invoke(null, args);
|
||||
}
|
||||
catch (TargetInvocationException e)
|
||||
{
|
||||
throw e.InnerException;
|
||||
}
|
||||
}
|
||||
|
||||
private static object InvokeAndUnwrapException(this MethodInfo method, IEnumerable<object> targets, object[] args)
|
||||
{
|
||||
try
|
||||
{
|
||||
return InvocationTargetFactory.InvokeOnTargets(method, targets, args);
|
||||
}
|
||||
catch (TargetInvocationException e)
|
||||
{
|
||||
throw e.InnerException;
|
||||
}
|
||||
}
|
||||
|
||||
[Command("call-static")]
|
||||
private static object CallStatic(Type classType, string funcName)
|
||||
{
|
||||
return CallStatic(classType, funcName, Array.Empty<string>());
|
||||
}
|
||||
|
||||
[Command("call-static")]
|
||||
private static object CallStatic(Type classType, string funcName, string[] args)
|
||||
{
|
||||
MethodInfo[] methods = ExtractMethods(classType, funcName);
|
||||
MethodInfo method = GetIdealOverload(methods, true, args.Length);
|
||||
|
||||
object[] parsedArgs = CreateArgs(method, args);
|
||||
return method.InvokeAndUnwrapException(parsedArgs);
|
||||
}
|
||||
|
||||
[Command("call-static")]
|
||||
[CommandDescription("Invokes the specified static method or property with the provided arguments. Provide [argTypes] if there are ambiguous overloads")]
|
||||
private static object CallStatic(
|
||||
[CommandParameterDescription("Namespace qualified typename of the class.")] Type classType,
|
||||
[CommandParameterDescription("Name of the method or property.")] string funcName,
|
||||
[CommandParameterDescription("The arguments for the function call.")] string[] args,
|
||||
[CommandParameterDescription("The types of the arguments to resolve ambiguous overloads.")] Type[] argTypes)
|
||||
{
|
||||
MethodInfo[] methods = ExtractMethods(classType, funcName);
|
||||
MethodInfo method = GetIdealOverload(methods, true, argTypes);
|
||||
|
||||
object[] parsedArgs = CreateArgs(method, argTypes, args);
|
||||
return method.InvokeAndUnwrapException(parsedArgs);
|
||||
}
|
||||
|
||||
[Command("call-instance")]
|
||||
private static object CallInstance(Type classType, string funcName, MonoTargetType targetType)
|
||||
{
|
||||
return CallInstance(classType, funcName, targetType, Array.Empty<string>());
|
||||
}
|
||||
|
||||
[Command("call-instance")]
|
||||
private static object CallInstance(Type classType, string funcName, MonoTargetType targetType, string[] args)
|
||||
{
|
||||
MethodInfo[] methods = ExtractMethods(classType, funcName);
|
||||
MethodInfo method = GetIdealOverload(methods, false, args.Length);
|
||||
|
||||
object[] parsedArgs = CreateArgs(method, args);
|
||||
IEnumerable<object> targets = InvocationTargetFactory.FindTargets(classType, targetType);
|
||||
return method.InvokeAndUnwrapException(targets, parsedArgs);
|
||||
}
|
||||
|
||||
[Command("call-instance")]
|
||||
[CommandDescription("Invokes the specified non-static method or property with the provided arguments. Provide [argTypes] if there are ambiguous overloads")]
|
||||
private static object CallInstance(
|
||||
[CommandParameterDescription("Namespace qualified typename of the class.")] Type classType,
|
||||
[CommandParameterDescription("Name of the method or property.")] string funcName,
|
||||
[CommandParameterDescription("The MonoTargetType used to find the target instances.")] MonoTargetType targetType,
|
||||
[CommandParameterDescription("The arguments for the function call.")] string[] args,
|
||||
[CommandParameterDescription("The types of the arguments to resolve ambiguous overloads.")] Type[] argTypes)
|
||||
{
|
||||
MethodInfo[] methods = ExtractMethods(classType, funcName);
|
||||
MethodInfo method = GetIdealOverload(methods, false, argTypes);
|
||||
|
||||
object[] parsedArgs = CreateArgs(method, argTypes, args);
|
||||
IEnumerable<object> targets = InvocationTargetFactory.FindTargets(classType, targetType);
|
||||
return method.InvokeAndUnwrapException(targets, parsedArgs);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 0ed09ce9eedb9c04fb9915469f53d71a
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,8 @@
|
|||
{
|
||||
"name": "QFSW.QC.Extras",
|
||||
"references": [
|
||||
"QFSW.QC"
|
||||
],
|
||||
"includePlatforms": [],
|
||||
"excludePlatforms": []
|
||||
}
|
|
@ -0,0 +1,7 @@
|
|||
fileFormatVersion: 2
|
||||
guid: dbe7cf6698bd54a63bc00412d71f8b48
|
||||
AssemblyDefinitionImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,101 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using UnityEngine;
|
||||
using UnityEngine.SceneManagement;
|
||||
|
||||
namespace QFSW.QC.Extras
|
||||
{
|
||||
public static class SceneCommands
|
||||
{
|
||||
private static async Task PollUntilAsync(int pollInterval, Func<bool> predicate)
|
||||
{
|
||||
while (!predicate())
|
||||
{
|
||||
await Task.Delay(pollInterval);
|
||||
}
|
||||
}
|
||||
|
||||
[Command("load-scene", "loads a scene by name into the game")]
|
||||
private static async Task LoadScene(string sceneName,
|
||||
[CommandParameterDescription("'Single' mode replaces the current scene with the new scene, whereas 'Additive' merges them")]LoadSceneMode loadMode = LoadSceneMode.Single)
|
||||
{
|
||||
AsyncOperation asyncOperation = SceneManager.LoadSceneAsync(sceneName, loadMode);
|
||||
await PollUntilAsync(16, () => asyncOperation.isDone);
|
||||
}
|
||||
|
||||
[Command("load-scene-index", "loads a scene by index into the game")]
|
||||
private static async Task LoadScene(int sceneIndex,
|
||||
[CommandParameterDescription("'Single' mode replaces the current scene with the new scene, whereas 'Additive' merges them")]LoadSceneMode loadMode = LoadSceneMode.Single)
|
||||
{
|
||||
AsyncOperation asyncOperation = SceneManager.LoadSceneAsync(sceneIndex, loadMode);
|
||||
await PollUntilAsync(16, () => asyncOperation.isDone);
|
||||
}
|
||||
|
||||
[Command("unload-scene", "unloads a scene by name")]
|
||||
private static async Task UnloadScene(string sceneName)
|
||||
{
|
||||
AsyncOperation asyncOperation = SceneManager.UnloadSceneAsync(sceneName);
|
||||
await PollUntilAsync(16, () => asyncOperation.isDone);
|
||||
}
|
||||
|
||||
[Command("unload-scene-index", "unloads a scene by index")]
|
||||
private static async Task UnloadScene(int sceneIndex)
|
||||
{
|
||||
AsyncOperation asyncOperation = SceneManager.UnloadSceneAsync(sceneIndex);
|
||||
await PollUntilAsync(16, () => asyncOperation.isDone);
|
||||
}
|
||||
|
||||
private static IEnumerable<Scene> GetScenesInBuild()
|
||||
{
|
||||
int sceneCount = SceneManager.sceneCountInBuildSettings;
|
||||
for (int i = 0; i < sceneCount; i++)
|
||||
{
|
||||
Scene scene = SceneManager.GetSceneByBuildIndex(i);
|
||||
yield return scene;
|
||||
}
|
||||
}
|
||||
|
||||
[Command("all-scenes", "gets the name and index of every scene included in the build")]
|
||||
private static Dictionary<int, string> GetAllScenes()
|
||||
{
|
||||
Dictionary<int, string> sceneData = new Dictionary<int, string>();
|
||||
int sceneCount = SceneManager.sceneCountInBuildSettings;
|
||||
for (int i = 0; i < sceneCount; i++)
|
||||
{
|
||||
int sceneIndex = i;
|
||||
string scenePath = SceneUtility.GetScenePathByBuildIndex(sceneIndex);
|
||||
string sceneName = System.IO.Path.GetFileNameWithoutExtension(scenePath);
|
||||
|
||||
sceneData.Add(sceneIndex, sceneName);
|
||||
}
|
||||
|
||||
return sceneData;
|
||||
}
|
||||
|
||||
[Command("loaded-scenes", "gets the name and index of every scene currently loaded")]
|
||||
private static Dictionary<int, string> GetLoadedScenes()
|
||||
{
|
||||
IEnumerable<Scene> loadedScenes = GetScenesInBuild().Where(x => x.isLoaded);
|
||||
Dictionary<int, string> sceneData = loadedScenes.ToDictionary(x => x.buildIndex, x => x.name);
|
||||
return sceneData;
|
||||
}
|
||||
|
||||
[Command("active-scene", "gets the name of the active primary scene")]
|
||||
private static string GetCurrentScene()
|
||||
{
|
||||
Scene scene = SceneManager.GetActiveScene();
|
||||
return scene.name;
|
||||
}
|
||||
|
||||
[Command("set-active-scene", "sets the active scene to the scene with name 'sceneName'")]
|
||||
private static void SetActiveScene(string sceneName)
|
||||
{
|
||||
Scene scene = SceneManager.GetSceneByName(sceneName);
|
||||
if (!scene.isLoaded) { throw new ArgumentException($"Scene {sceneName} must be loaded before it can be set active"); }
|
||||
|
||||
SceneManager.SetActiveScene(scene);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: dc7a6d8b121ac49c8a37e3d393a51518
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,72 @@
|
|||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
namespace QFSW.QC.Extras
|
||||
{
|
||||
public static class ScreenCommands
|
||||
{
|
||||
[Command("fullscreen", "fullscreen state of the application.")]
|
||||
private static bool Fullscreen
|
||||
{
|
||||
get => Screen.fullScreen;
|
||||
set => Screen.fullScreen = value;
|
||||
}
|
||||
|
||||
[Command("screen-dpi", "dpi of the current device's screen.")]
|
||||
private static float DPI => Screen.dpi;
|
||||
|
||||
[Command("screen-orientation", "the orientation of the screen.")]
|
||||
[CommandPlatform(Platform.MobilePlatforms)]
|
||||
private static ScreenOrientation Orientation
|
||||
{
|
||||
get => Screen.orientation;
|
||||
set => Screen.orientation = value;
|
||||
}
|
||||
|
||||
[Command("current-resolution", "current resolution of the application or window.")]
|
||||
private static Resolution GetCurrentResolution()
|
||||
{
|
||||
Resolution resolution = new Resolution
|
||||
{
|
||||
width = Screen.width,
|
||||
height = Screen.height,
|
||||
refreshRate = Screen.currentResolution.refreshRate
|
||||
};
|
||||
|
||||
return resolution;
|
||||
}
|
||||
|
||||
[Command("supported-resolutions", "all resolutions supported by this device in fullscreen mode.")]
|
||||
[CommandPlatform(Platform.AllPlatforms ^ Platform.WebGLPlayer)]
|
||||
private static IEnumerable<Resolution> GetSupportedResolutions()
|
||||
{
|
||||
foreach (Resolution resolution in Screen.resolutions)
|
||||
{
|
||||
yield return resolution;
|
||||
}
|
||||
}
|
||||
|
||||
[Command("set-resolution")]
|
||||
private static void SetResolution(int x, int y)
|
||||
{
|
||||
SetResolution(x, y, Screen.fullScreen);
|
||||
}
|
||||
|
||||
[Command("set-resolution", "sets the resolution of the current application, optionally setting the fullscreen state too.")]
|
||||
private static void SetResolution(int x, int y, bool fullscreen)
|
||||
{
|
||||
Screen.SetResolution(x, y, fullscreen);
|
||||
}
|
||||
|
||||
[Command("capture-screenshot")]
|
||||
[CommandDescription("Captures a screenshot and saves it to the supplied file path as a PNG.\n" +
|
||||
"If superSize is supplied the screenshot will be captured at a higher than native resolution.")]
|
||||
private static void CaptureScreenshot(
|
||||
[CommandParameterDescription("The name of the file to save the screenshot in")] string filename,
|
||||
[CommandParameterDescription("Factor by which to increase resolution")] int superSize = 1
|
||||
)
|
||||
{
|
||||
ScreenCapture.CaptureScreenshot(filename, superSize);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 937752cbc170542b8ae4a31a025b7cf2
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,14 @@
|
|||
using UnityEngine;
|
||||
|
||||
namespace QFSW.QC.Extras
|
||||
{
|
||||
public static class TimeCommands
|
||||
{
|
||||
[Command("time-scale", "the scale at which time is passing by.")]
|
||||
private static float TimeScale
|
||||
{
|
||||
get => Time.timeScale;
|
||||
set => Time.timeScale = value;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 816d2412b2b594778a0e42b669424332
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,25 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace QFSW.QC.Extras
|
||||
{
|
||||
public static class TypeCommands
|
||||
{
|
||||
[Command("enum-info", "gets all of the numeric values and value names for the specified enum type.")]
|
||||
private static IEnumerable<object> GetEnumInfo(Type enumType)
|
||||
{
|
||||
if (!enumType.IsEnum) { throw new ArgumentException($"Supplied type '{enumType}' must be an enum type"); }
|
||||
|
||||
Type enumInnerType = enumType.GetEnumUnderlyingType();
|
||||
Array vals = enumType.GetEnumValues();
|
||||
|
||||
for (int i = 0; i < vals.Length; i++)
|
||||
{
|
||||
object name = vals.GetValue(i);
|
||||
object val = Convert.ChangeType(name, enumInnerType);
|
||||
KeyValuePair<object, object> pair = new KeyValuePair<object, object>(val, name);
|
||||
yield return pair;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: fa2f2993809854c998bd8a5842582d5c
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,170 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using UnityEngine;
|
||||
using UnityEngine.SceneManagement;
|
||||
|
||||
namespace QFSW.QC.Extras
|
||||
{
|
||||
public static class UtilCommands
|
||||
{
|
||||
private static readonly Pool<StringBuilder> _builderPool = new Pool<StringBuilder>();
|
||||
|
||||
[Command("get-object-info", "Finds the specified GameObject and displays its transform and component data")]
|
||||
private static string ExtractObjectInfo(GameObject target)
|
||||
{
|
||||
StringBuilder builder = _builderPool.GetObject();
|
||||
builder.Clear();
|
||||
|
||||
builder.AppendLine($"Extracted info for object '{target.name}'");
|
||||
builder.AppendLine("Transform data:");
|
||||
builder.AppendLine($" - position: {target.transform.position}");
|
||||
builder.AppendLine($" - rotation: {target.transform.localRotation}");
|
||||
builder.AppendLine($" - scale: {target.transform.localScale}");
|
||||
if (target.transform.childCount > 0) { builder.AppendLine($" - child count: {target.transform.childCount}"); }
|
||||
if (target.transform.parent) { builder.AppendLine($" - parent: {target.transform.parent.name}"); }
|
||||
|
||||
Component[] components = target.GetComponents<Component>().OrderBy(x => x.GetType().Name).ToArray();
|
||||
|
||||
if (components.Length > 0)
|
||||
{
|
||||
builder.AppendLine("Component data:");
|
||||
for (int i = 0; i < components.Length; i++)
|
||||
{
|
||||
int componentCount = 1;
|
||||
Type componentType = components[i].GetType();
|
||||
builder.AppendLine($" - {componentType.Name}");
|
||||
while (i + 1 < components.Length && components[i + 1].GetType() == componentType)
|
||||
{
|
||||
componentCount++;
|
||||
i++;
|
||||
}
|
||||
|
||||
if (componentCount > 1) { builder.Append($" ({componentCount})"); }
|
||||
}
|
||||
}
|
||||
|
||||
if (target.transform.childCount > 0)
|
||||
{
|
||||
builder.AppendLine("Children:");
|
||||
|
||||
int childCount = target.transform.childCount;
|
||||
for (int i = 0; i < childCount; i++)
|
||||
{
|
||||
builder.AppendLine($" - {target.transform.GetChild(i).name}");
|
||||
}
|
||||
}
|
||||
|
||||
string info = builder.ToString();
|
||||
_builderPool.Release(builder);
|
||||
return info;
|
||||
}
|
||||
|
||||
[Command("get-scene-hierarchy", "Renders the GameObject hierarchy of the currently open scenes")]
|
||||
private static string GetSceneHierarchy()
|
||||
{
|
||||
List<GameObject> objects = new List<GameObject>();
|
||||
StringBuilder buffer = _builderPool.GetObject();
|
||||
buffer.Clear();
|
||||
|
||||
int sceneCount = SceneManager.sceneCountInBuildSettings;
|
||||
for (int i = 0; i < sceneCount; i++)
|
||||
{
|
||||
Scene scene = SceneManager.GetSceneByBuildIndex(i);
|
||||
if (scene.isLoaded)
|
||||
{
|
||||
objects.Clear();
|
||||
scene.GetRootGameObjects(objects);
|
||||
|
||||
buffer.AppendLine(scene.name);
|
||||
GetSceneHierarchy(objects.Select(x => x.transform).ToArray(), 0, buffer, new List<bool>());
|
||||
}
|
||||
}
|
||||
|
||||
string result = buffer.ToString();
|
||||
_builderPool.Release(buffer);
|
||||
return result;
|
||||
}
|
||||
|
||||
private static IEnumerable<Transform> GetChildren(this Transform transform)
|
||||
{
|
||||
for (int i = 0; i < transform.childCount; i++)
|
||||
{
|
||||
yield return transform.GetChild(i);
|
||||
}
|
||||
}
|
||||
|
||||
private static void GetSceneHierarchy(IList<Transform> roots, int depth, StringBuilder buffer, IList<bool> drawVertical)
|
||||
{
|
||||
const char terminalSymbol = '|';
|
||||
const char verticalSplitSymbol = '|';
|
||||
const char verticalSymbol = '|';
|
||||
const char horizontalSymbol = '-';
|
||||
const int indentation = 3;
|
||||
|
||||
for (int i = 0; i < roots.Count; i++)
|
||||
{
|
||||
Transform root = roots[i];
|
||||
|
||||
for (int j = 0; j < depth; j++)
|
||||
{
|
||||
buffer.Append(drawVertical[j] ? verticalSymbol : ' ');
|
||||
buffer.Append(' ', indentation - 1);
|
||||
}
|
||||
|
||||
bool terminal = i == roots.Count - 1;
|
||||
drawVertical.Add(!terminal);
|
||||
|
||||
buffer.Append(terminal ? terminalSymbol : verticalSplitSymbol);
|
||||
buffer.Append(horizontalSymbol, indentation - 1);
|
||||
buffer.AppendLine(root.name);
|
||||
|
||||
GetSceneHierarchy(root.GetChildren().ToList(), depth + 1, buffer, drawVertical);
|
||||
drawVertical.RemoveAt(drawVertical.Count - 1);
|
||||
}
|
||||
}
|
||||
|
||||
[Command("add-component", "Adds a component of type T to the specified GameObject")]
|
||||
private static void AddComponent<T>(GameObject target) where T : Component { target.AddComponent<T>(); }
|
||||
|
||||
[Command("destroy-component", "Destroys the component of type T on the specified GameObject")]
|
||||
private static void DestroyComponent<T>(T target) where T : Component { GameObject.Destroy(target); }
|
||||
|
||||
[Command("destroy", "Destroys a GameObject")]
|
||||
private static void DestroyGO(GameObject target) { GameObject.Destroy(target); }
|
||||
|
||||
[Command("instantiate", "Instantiates a GameObject")]
|
||||
private static void InstantiateGO(
|
||||
[CommandParameterDescription("The original GameObject to instantiate a copy of.")] GameObject original,
|
||||
[CommandParameterDescription("The position of the instantiated GameObject.")] Vector3 position,
|
||||
[CommandParameterDescription("The rotation of the instantiated GameObject.")] Quaternion rotation)
|
||||
{
|
||||
GameObject.Instantiate(original, position, rotation);
|
||||
}
|
||||
|
||||
[Command("instantiate", "Instantiates a GameObject")]
|
||||
private static void InstantiateGO(GameObject original, Vector3 position) { GameObject.Instantiate(original).transform.position = position; }
|
||||
|
||||
[Command("instantiate", "Instantiates a GameObject")]
|
||||
private static void InstantiateGO(GameObject original) { GameObject.Instantiate(original); }
|
||||
|
||||
[Command("teleport", "Teleports a GameObject")]
|
||||
private static void TeleportGO(GameObject target, Vector3 position) { target.transform.position = position; }
|
||||
|
||||
[Command("teleport-relative", "Teleports a GameObject by a relative offset to its current position")]
|
||||
private static void TeleportRelativeGO(GameObject target, Vector3 offset) { target.transform.Translate(offset); }
|
||||
|
||||
[Command("rotate", "Rotates a GameObject")]
|
||||
private static void RotateGO(GameObject target, Quaternion rotation) { target.transform.Rotate(rotation.eulerAngles); }
|
||||
|
||||
[Command("set-active", "Activates/deactivates a GameObject")]
|
||||
private static void SetGOActive(GameObject target, bool active) { target.SetActive(active); }
|
||||
|
||||
[Command("set-parent", "Sets the parent of the targert transform.")]
|
||||
private static void SetGOParent(Transform target, Transform parentTarget) { target.SetParent(parentTarget); }
|
||||
|
||||
[Command("send-message", "Calls the method named 'methodName' on every MonoBehaviour in the target GameObject")]
|
||||
private static void SendGOMessage(GameObject target, string methodName) { target.SendMessage(methodName); }
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 75e1e5918b90b4de5907e9e5bdf0d9b4
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,9 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 496cffde696095c439db4ee329062978
|
||||
folderAsset: yes
|
||||
timeCreated: 1553955817
|
||||
licenseType: Store
|
||||
DefaultImporter:
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,8 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 015e5afa17239334c8f085479673d346
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,153 @@
|
|||
#if NET_4_6 && !NET_STANDARD_2_0
|
||||
#define QC_SUPPORTED
|
||||
#endif
|
||||
|
||||
using Mono.CSharp;
|
||||
using System;
|
||||
using System.CodeDom;
|
||||
using System.CodeDom.Compiler;
|
||||
using System.IO;
|
||||
using System.Reflection.Emit;
|
||||
using System.Text;
|
||||
|
||||
#if QC_SUPPORTED
|
||||
namespace CSharpCompiler
|
||||
{
|
||||
public class CodeCompiler : ICodeCompiler
|
||||
{
|
||||
static long assemblyCounter = 0;
|
||||
|
||||
public CompilerResults CompileAssemblyFromDom(CompilerParameters options, CodeCompileUnit compilationUnit)
|
||||
{
|
||||
return CompileAssemblyFromDomBatch(options, new[] { compilationUnit });
|
||||
}
|
||||
|
||||
public CompilerResults CompileAssemblyFromDomBatch(CompilerParameters options, CodeCompileUnit[] ea)
|
||||
{
|
||||
if (options == null)
|
||||
{
|
||||
throw new ArgumentNullException("options");
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
return CompileFromDomBatch(options, ea);
|
||||
}
|
||||
finally
|
||||
{
|
||||
options.TempFiles.Delete();
|
||||
}
|
||||
}
|
||||
|
||||
private CompilerResults CompileFromDomBatch(CompilerParameters options, CodeCompileUnit[] ea)
|
||||
{
|
||||
throw new NotImplementedException("sorry ICodeGenerator is not implemented, feel free to fix it and request merge");
|
||||
}
|
||||
|
||||
public CompilerResults CompileAssemblyFromFile(CompilerParameters options, string fileName)
|
||||
{
|
||||
return CompileAssemblyFromFileBatch(options, new[] { fileName });
|
||||
}
|
||||
|
||||
public CompilerResults CompileAssemblyFromFileBatch(CompilerParameters options, string[] fileNames)
|
||||
{
|
||||
var settings = ParamsToSettings(options);
|
||||
|
||||
foreach (var fileName in fileNames)
|
||||
{
|
||||
string path = Path.GetFullPath(fileName);
|
||||
var unit = new SourceFile(fileName, path, settings.SourceFiles.Count + 1);
|
||||
settings.SourceFiles.Add(unit);
|
||||
}
|
||||
|
||||
return CompileFromCompilerSettings(settings, options.GenerateInMemory);
|
||||
}
|
||||
|
||||
public CompilerResults CompileAssemblyFromSource(CompilerParameters options, string source)
|
||||
{
|
||||
return CompileAssemblyFromSourceBatch(options, new[] { source });
|
||||
}
|
||||
|
||||
public CompilerResults CompileAssemblyFromSourceBatch(CompilerParameters options, string[] sources)
|
||||
{
|
||||
var settings = ParamsToSettings(options);
|
||||
|
||||
int i = 0;
|
||||
foreach (var _source in sources)
|
||||
{
|
||||
var source = _source;
|
||||
Func<Stream> getStream = () => { return new MemoryStream(Encoding.UTF8.GetBytes(source ?? "")); };
|
||||
var fileName = i.ToString();
|
||||
var unit = new SourceFile(fileName, fileName, settings.SourceFiles.Count + 1, getStream);
|
||||
settings.SourceFiles.Add(unit);
|
||||
i++;
|
||||
}
|
||||
|
||||
return CompileFromCompilerSettings(settings, options.GenerateInMemory);
|
||||
}
|
||||
|
||||
|
||||
CompilerResults CompileFromCompilerSettings(CompilerSettings settings, bool generateInMemory)
|
||||
{
|
||||
var compilerResults = new CompilerResults(new TempFileCollection(Path.GetTempPath()));
|
||||
var driver = new CustomDynamicDriver(new CompilerContext(settings, new CustomReportPrinter(compilerResults)));
|
||||
|
||||
AssemblyBuilder outAssembly = null;
|
||||
try
|
||||
{
|
||||
driver.Compile(out outAssembly, AppDomain.CurrentDomain, generateInMemory);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
compilerResults.Errors.Add(new CompilerError()
|
||||
{
|
||||
IsWarning = false,
|
||||
ErrorText = e.Message,
|
||||
});
|
||||
}
|
||||
compilerResults.CompiledAssembly = outAssembly;
|
||||
|
||||
return compilerResults;
|
||||
}
|
||||
|
||||
|
||||
CompilerSettings ParamsToSettings(CompilerParameters parameters)
|
||||
{
|
||||
var settings = new CompilerSettings();
|
||||
|
||||
|
||||
foreach (var assembly in parameters.ReferencedAssemblies) settings.AssemblyReferences.Add(assembly);
|
||||
|
||||
settings.Encoding = System.Text.Encoding.UTF8;
|
||||
settings.GenerateDebugInfo = parameters.IncludeDebugInformation;
|
||||
settings.MainClass = parameters.MainClass;
|
||||
settings.Platform = Platform.AnyCPU;
|
||||
settings.StdLibRuntimeVersion = RuntimeVersion.v4;
|
||||
if (parameters.GenerateExecutable)
|
||||
{
|
||||
settings.Target = Target.Exe;
|
||||
settings.TargetExt = ".exe";
|
||||
}
|
||||
else
|
||||
{
|
||||
settings.Target = Target.Library;
|
||||
settings.TargetExt = ".dll";
|
||||
}
|
||||
if (parameters.GenerateInMemory) settings.Target = Target.Library;
|
||||
|
||||
if (string.IsNullOrEmpty(parameters.OutputAssembly))
|
||||
{
|
||||
parameters.OutputAssembly = settings.OutputFile = "DynamicAssembly_" + assemblyCounter + settings.TargetExt;
|
||||
assemblyCounter++;
|
||||
}
|
||||
settings.OutputFile = parameters.OutputAssembly; // if it is not being outputted, we use this to set name of the dynamic assembly
|
||||
|
||||
settings.Version = LanguageVersion.Default;
|
||||
settings.WarningLevel = parameters.WarningLevel;
|
||||
settings.WarningsAreErrors = parameters.TreatWarningsAsErrors;
|
||||
|
||||
return settings;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
|
@ -0,0 +1,12 @@
|
|||
fileFormatVersion: 2
|
||||
guid: f3f2a9227250eeb43a8e3c138ce1a6a1
|
||||
timeCreated: 1438909233
|
||||
licenseType: Store
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,317 @@
|
|||
// modified version of Mono.CSharp.Driver
|
||||
|
||||
// driver.cs: The compiler command line driver.
|
||||
//
|
||||
// Authors:
|
||||
// Miguel de Icaza (miguel@gnu.org)
|
||||
// Marek Safar (marek.safar@gmail.com)
|
||||
//
|
||||
// Dual licensed under the terms of the MIT X11 or GNU GPL
|
||||
//
|
||||
// Copyright 2001, 2002, 2003 Ximian, Inc (http://www.ximian.com)
|
||||
// Copyright 2004, 2005, 2006, 2007, 2008 Novell, Inc
|
||||
// Copyright 2011 Xamarin Inc
|
||||
//
|
||||
|
||||
#if NET_4_6 && !NET_STANDARD_2_0
|
||||
#define QC_SUPPORTED
|
||||
#endif
|
||||
|
||||
#if QC_SUPPORTED
|
||||
using Mono.CSharp;
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Reflection.Emit;
|
||||
|
||||
namespace CSharpCompiler
|
||||
{
|
||||
/// <summary>
|
||||
/// The compiler driver.
|
||||
/// </summary>
|
||||
public class CustomDynamicDriver
|
||||
{
|
||||
readonly CompilerContext ctx;
|
||||
|
||||
public CustomDynamicDriver(CompilerContext ctx)
|
||||
{
|
||||
this.ctx = ctx;
|
||||
}
|
||||
|
||||
public Report Report
|
||||
{
|
||||
get
|
||||
{
|
||||
return ctx.Report;
|
||||
}
|
||||
}
|
||||
|
||||
void tokenize_file(SourceFile sourceFile, ModuleContainer module, ParserSession session)
|
||||
{
|
||||
Stream input;
|
||||
|
||||
try
|
||||
{
|
||||
input = sourceFile.GetDataStream();
|
||||
}
|
||||
catch
|
||||
{
|
||||
Report.Error(2001, "Source file `" + sourceFile.Name + "' could not be found");
|
||||
return;
|
||||
}
|
||||
|
||||
using (input)
|
||||
{
|
||||
SeekableStreamReader reader = new SeekableStreamReader(input, ctx.Settings.Encoding);
|
||||
var file = new CompilationSourceFile(module, sourceFile);
|
||||
|
||||
Tokenizer lexer = new Tokenizer(reader, file, session, ctx.Report);
|
||||
int token, tokens = 0, errors = 0;
|
||||
|
||||
while ((token = lexer.token()) != Token.EOF)
|
||||
{
|
||||
tokens++;
|
||||
if (token == Token.ERROR)
|
||||
errors++;
|
||||
}
|
||||
Console.WriteLine("Tokenized: " + tokens + " found " + errors + " errors");
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
public void Parse(ModuleContainer module)
|
||||
{
|
||||
bool tokenize_only = module.Compiler.Settings.TokenizeOnly;
|
||||
var sources = module.Compiler.SourceFiles;
|
||||
|
||||
Location.Initialize(sources);
|
||||
|
||||
var session = new ParserSession
|
||||
{
|
||||
UseJayGlobalArrays = true,
|
||||
LocatedTokens = new LocatedToken[15000]
|
||||
};
|
||||
|
||||
for (int i = 0; i < sources.Count; ++i)
|
||||
{
|
||||
if (tokenize_only)
|
||||
{
|
||||
tokenize_file(sources[i], module, session);
|
||||
}
|
||||
else
|
||||
{
|
||||
Parse(sources[i], module, session, Report);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void Parse(SourceFile file, ModuleContainer module, ParserSession session, Report report)
|
||||
{
|
||||
Stream input;
|
||||
|
||||
try
|
||||
{
|
||||
input = file.GetDataStream();
|
||||
}
|
||||
catch
|
||||
{
|
||||
report.Error(2001, "Source file `{0}' could not be found", file.Name);
|
||||
return;
|
||||
}
|
||||
|
||||
// Check 'MZ' header
|
||||
if (input.ReadByte() == 77 && input.ReadByte() == 90)
|
||||
{
|
||||
|
||||
report.Error(2015, "Source file `{0}' is a binary file and not a text file", file.Name);
|
||||
input.Close();
|
||||
return;
|
||||
}
|
||||
|
||||
input.Position = 0;
|
||||
SeekableStreamReader reader = new SeekableStreamReader(input, ctx.Settings.Encoding, session.StreamReaderBuffer);
|
||||
|
||||
Parse(reader, file, module, session, report);
|
||||
|
||||
if (ctx.Settings.GenerateDebugInfo && report.Errors == 0 && !file.HasChecksum)
|
||||
{
|
||||
input.Position = 0;
|
||||
var checksum = session.GetChecksumAlgorithm();
|
||||
file.SetChecksum(checksum.ComputeHash(input));
|
||||
}
|
||||
|
||||
reader.Dispose();
|
||||
input.Close();
|
||||
}
|
||||
|
||||
public static void Parse(SeekableStreamReader reader, SourceFile sourceFile, ModuleContainer module, ParserSession session, Report report)
|
||||
{
|
||||
var file = new CompilationSourceFile(module, sourceFile);
|
||||
module.AddTypeContainer(file);
|
||||
|
||||
CSharpParser parser = new CSharpParser(reader, file, report, session);
|
||||
parser.parse();
|
||||
}
|
||||
|
||||
|
||||
|
||||
//
|
||||
// Main compilation method
|
||||
//
|
||||
public bool Compile(out AssemblyBuilder outAssembly, AppDomain domain, bool generateInMemory)
|
||||
{
|
||||
var settings = ctx.Settings;
|
||||
|
||||
outAssembly = null;
|
||||
//
|
||||
// If we are an exe, require a source file for the entry point or
|
||||
// if there is nothing to put in the assembly, and we are not a library
|
||||
//
|
||||
if (settings.FirstSourceFile == null &&
|
||||
((settings.Target == Target.Exe || settings.Target == Target.WinExe || settings.Target == Target.Module) ||
|
||||
settings.Resources == null))
|
||||
{
|
||||
Report.Error(2008, "No files to compile were specified");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (settings.Platform == Platform.AnyCPU32Preferred && (settings.Target == Target.Library || settings.Target == Target.Module))
|
||||
{
|
||||
Report.Error(4023, "Platform option `anycpu32bitpreferred' is valid only for executables");
|
||||
return false;
|
||||
}
|
||||
|
||||
TimeReporter tr = new TimeReporter(settings.Timestamps);
|
||||
ctx.TimeReporter = tr;
|
||||
tr.StartTotal();
|
||||
|
||||
var module = new ModuleContainer(ctx);
|
||||
RootContext.ToplevelTypes = module;
|
||||
|
||||
tr.Start(TimeReporter.TimerType.ParseTotal);
|
||||
Parse(module);
|
||||
tr.Stop(TimeReporter.TimerType.ParseTotal);
|
||||
|
||||
if (Report.Errors > 0)
|
||||
return false;
|
||||
|
||||
if (settings.TokenizeOnly || settings.ParseOnly)
|
||||
{
|
||||
tr.StopTotal();
|
||||
tr.ShowStats();
|
||||
return true;
|
||||
}
|
||||
|
||||
var output_file = settings.OutputFile;
|
||||
string output_file_name;
|
||||
/* if (output_file == null)
|
||||
{
|
||||
var source_file = settings.FirstSourceFile;
|
||||
|
||||
if (source_file == null)
|
||||
{
|
||||
Report.Error(1562, "If no source files are specified you must specify the output file with -out:");
|
||||
return false;
|
||||
}
|
||||
|
||||
output_file_name = source_file.Name;
|
||||
int pos = output_file_name.LastIndexOf('.');
|
||||
|
||||
if (pos > 0)
|
||||
output_file_name = output_file_name.Substring(0, pos);
|
||||
|
||||
output_file_name += settings.TargetExt;
|
||||
output_file = output_file_name;
|
||||
}
|
||||
else
|
||||
{*/
|
||||
output_file_name = Path.GetFileName(output_file);
|
||||
|
||||
/* if (string.IsNullOrEmpty(Path.GetFileNameWithoutExtension(output_file_name)) ||
|
||||
output_file_name.IndexOfAny(Path.GetInvalidFileNameChars()) >= 0)
|
||||
{
|
||||
Report.Error(2021, "Output file name is not valid");
|
||||
return false;
|
||||
}
|
||||
}*/
|
||||
|
||||
|
||||
var assembly = new AssemblyDefinitionDynamic(module, output_file_name, output_file);
|
||||
module.SetDeclaringAssembly(assembly);
|
||||
|
||||
var importer = new ReflectionImporter(module, ctx.BuiltinTypes);
|
||||
assembly.Importer = importer;
|
||||
|
||||
var loader = new DynamicLoader(importer, ctx);
|
||||
loader.LoadReferences(module);
|
||||
|
||||
if (!ctx.BuiltinTypes.CheckDefinitions(module))
|
||||
return false;
|
||||
|
||||
if (!assembly.Create(domain, AssemblyBuilderAccess.RunAndSave))
|
||||
return false;
|
||||
|
||||
module.CreateContainer();
|
||||
|
||||
loader.LoadModules(assembly, module.GlobalRootNamespace);
|
||||
|
||||
module.InitializePredefinedTypes();
|
||||
|
||||
if (settings.GetResourceStrings != null)
|
||||
module.LoadGetResourceStrings(settings.GetResourceStrings);
|
||||
|
||||
tr.Start(TimeReporter.TimerType.ModuleDefinitionTotal);
|
||||
module.Define();
|
||||
tr.Stop(TimeReporter.TimerType.ModuleDefinitionTotal);
|
||||
|
||||
if (Report.Errors > 0)
|
||||
return false;
|
||||
|
||||
if (settings.DocumentationFile != null)
|
||||
{
|
||||
var doc = new DocumentationBuilder(module);
|
||||
doc.OutputDocComment(output_file, settings.DocumentationFile);
|
||||
}
|
||||
|
||||
assembly.Resolve();
|
||||
|
||||
if (Report.Errors > 0)
|
||||
return false;
|
||||
|
||||
|
||||
tr.Start(TimeReporter.TimerType.EmitTotal);
|
||||
assembly.Emit();
|
||||
tr.Stop(TimeReporter.TimerType.EmitTotal);
|
||||
|
||||
if (Report.Errors > 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
tr.Start(TimeReporter.TimerType.CloseTypes);
|
||||
module.CloseContainer();
|
||||
tr.Stop(TimeReporter.TimerType.CloseTypes);
|
||||
|
||||
tr.Start(TimeReporter.TimerType.Resouces);
|
||||
if (!settings.WriteMetadataOnly)
|
||||
assembly.EmbedResources();
|
||||
tr.Stop(TimeReporter.TimerType.Resouces);
|
||||
|
||||
if (Report.Errors > 0)
|
||||
return false;
|
||||
|
||||
|
||||
if (!generateInMemory) assembly.Save();
|
||||
outAssembly = assembly.Builder;
|
||||
|
||||
|
||||
tr.StopTotal();
|
||||
tr.ShowStats();
|
||||
|
||||
return Report.Errors == 0;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
#endif
|
|
@ -0,0 +1,12 @@
|
|||
fileFormatVersion: 2
|
||||
guid: e389d8a5b0e25ae44a841060cecca276
|
||||
timeCreated: 1435446720
|
||||
licenseType: Store
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,53 @@
|
|||
#if NET_4_6 && !NET_STANDARD_2_0
|
||||
#define QC_SUPPORTED
|
||||
#endif
|
||||
|
||||
using Mono.CSharp;
|
||||
using System.CodeDom.Compiler;
|
||||
|
||||
#if QC_SUPPORTED
|
||||
namespace CSharpCompiler
|
||||
{
|
||||
|
||||
public class CustomReportPrinter : ReportPrinter
|
||||
{
|
||||
|
||||
readonly CompilerResults compilerResults;
|
||||
#region Properties
|
||||
|
||||
public new int ErrorsCount { get; protected set; }
|
||||
|
||||
public new int WarningsCount { get; private set; }
|
||||
|
||||
#endregion
|
||||
public CustomReportPrinter(CompilerResults compilerResults)
|
||||
{
|
||||
this.compilerResults = compilerResults;
|
||||
}
|
||||
|
||||
public override void Print(AbstractMessage msg, bool showFullPath)
|
||||
{
|
||||
if (msg.IsWarning)
|
||||
{
|
||||
++WarningsCount;
|
||||
}
|
||||
else
|
||||
{
|
||||
++ErrorsCount;
|
||||
}
|
||||
compilerResults.Errors.Add(new CompilerError()
|
||||
{
|
||||
IsWarning = msg.IsWarning,
|
||||
Column = msg.Location.Column,
|
||||
Line = msg.Location.Row,
|
||||
ErrorNumber = msg.Code.ToString(),
|
||||
ErrorText = msg.Text,
|
||||
FileName = showFullPath ? msg.Location.SourceFile.FullPathName : msg.Location.SourceFile.Name,
|
||||
// msg.RelatedSymbols // extra info
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
#endif
|
|
@ -0,0 +1,12 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 39ec208e78505e342a2829289445b934
|
||||
timeCreated: 1438909233
|
||||
licenseType: Store
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,99 @@
|
|||
/*
|
||||
Implementation of ISynchronizeInvoke for Unity3D game engine.
|
||||
Can be used to invoke anything on main Unity thread.
|
||||
ISynchronizeInvoke is used extensively in .NET forms it's is elegant and quite useful in Unity as well.
|
||||
I implemented it so i can use it with System.IO.FileSystemWatcher.SynchronizingObject.
|
||||
|
||||
help from: http://www.codeproject.com/Articles/12082/A-DelegateQueue-Class
|
||||
example usage: https://gist.github.com/aeroson/90bf21be3fdc4829e631
|
||||
|
||||
license: WTFPL (http://www.wtfpl.net/)
|
||||
contact: aeroson (theaeroson @gmail.com)
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Reflection;
|
||||
using System.Threading;
|
||||
|
||||
public class DeferredSynchronizeInvoke : ISynchronizeInvoke
|
||||
{
|
||||
Queue<UnityAsyncResult> fifoToExecute = new Queue<UnityAsyncResult>();
|
||||
Thread mainThread;
|
||||
public bool InvokeRequired { get { return mainThread.ManagedThreadId != Thread.CurrentThread.ManagedThreadId; } }
|
||||
|
||||
public DeferredSynchronizeInvoke()
|
||||
{
|
||||
mainThread = Thread.CurrentThread;
|
||||
}
|
||||
public IAsyncResult BeginInvoke(Delegate method, object[] args)
|
||||
{
|
||||
var asyncResult = new UnityAsyncResult()
|
||||
{
|
||||
method = method,
|
||||
args = args,
|
||||
IsCompleted = false,
|
||||
AsyncWaitHandle = new ManualResetEvent(false),
|
||||
};
|
||||
lock (fifoToExecute)
|
||||
{
|
||||
fifoToExecute.Enqueue(asyncResult);
|
||||
}
|
||||
return asyncResult;
|
||||
}
|
||||
public object EndInvoke(IAsyncResult result)
|
||||
{
|
||||
if (!result.IsCompleted)
|
||||
{
|
||||
result.AsyncWaitHandle.WaitOne();
|
||||
}
|
||||
return result.AsyncState;
|
||||
}
|
||||
public object Invoke(Delegate method, object[] args)
|
||||
{
|
||||
if (InvokeRequired)
|
||||
{
|
||||
var asyncResult = BeginInvoke(method, args);
|
||||
return EndInvoke(asyncResult);
|
||||
}
|
||||
else
|
||||
{
|
||||
return method.DynamicInvoke(args);
|
||||
}
|
||||
}
|
||||
public void ProcessQueue()
|
||||
{
|
||||
if (Thread.CurrentThread != mainThread)
|
||||
{
|
||||
throw new TargetException(
|
||||
this.GetType() + "." + MethodBase.GetCurrentMethod().Name + "() " +
|
||||
"must be called from the same thread it was created on " +
|
||||
"(created on thread id: " + mainThread.ManagedThreadId + ", called from thread id: " + Thread.CurrentThread.ManagedThreadId
|
||||
);
|
||||
}
|
||||
bool loop = true;
|
||||
UnityAsyncResult data = null;
|
||||
while (loop)
|
||||
{
|
||||
lock (fifoToExecute)
|
||||
{
|
||||
loop = fifoToExecute.Count > 0;
|
||||
if (!loop) break;
|
||||
data = fifoToExecute.Dequeue();
|
||||
}
|
||||
|
||||
data.AsyncState = Invoke(data.method, data.args);
|
||||
data.IsCompleted = true;
|
||||
}
|
||||
}
|
||||
class UnityAsyncResult : IAsyncResult
|
||||
{
|
||||
public Delegate method;
|
||||
public object[] args;
|
||||
public bool IsCompleted { get; set; }
|
||||
public WaitHandle AsyncWaitHandle { get; internal set; }
|
||||
public object AsyncState { get; set; }
|
||||
public bool CompletedSynchronously { get { return IsCompleted; } }
|
||||
}
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
fileFormatVersion: 2
|
||||
guid: f6228134abfaad746965d9639b73908a
|
||||
timeCreated: 1435576341
|
||||
licenseType: Store
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,21 @@
|
|||
Copyright (c) 2001, 2002, 2003 Ximian, Inc and the individuals listed
|
||||
on the ChangeLog entries.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the
|
||||
"Software"), to deal in the Software without restriction, including
|
||||
without limitation the rights to use, copy, modify, merge, publish,
|
||||
distribute, sublicense, and/or sell copies of the Software, and to
|
||||
permit persons to whom the Software is furnished to do so, subject to
|
||||
the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be
|
||||
included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
@ -0,0 +1,7 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 09298e73731a3b64fbedf483cf7d4e42
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,9 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 2ce9bfedd125d1c49adb5c65c9e8ce53
|
||||
folderAsset: yes
|
||||
timeCreated: 1435432572
|
||||
licenseType: Store
|
||||
DefaultImporter:
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,30 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 0447405aaa6f3bd4c96d4c64631542fd
|
||||
PluginImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
iconMap: {}
|
||||
executionOrder: {}
|
||||
isPreloaded: 0
|
||||
isOverridable: 0
|
||||
platformData:
|
||||
- first:
|
||||
Any:
|
||||
second:
|
||||
enabled: 1
|
||||
settings: {}
|
||||
- first:
|
||||
Editor: Editor
|
||||
second:
|
||||
enabled: 0
|
||||
settings:
|
||||
DefaultValueInitialized: true
|
||||
- first:
|
||||
Windows Store Apps: WindowsStoreApps
|
||||
second:
|
||||
enabled: 0
|
||||
settings:
|
||||
CPU: AnyCPU
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,172 @@
|
|||
#if NET_4_6 && !NET_STANDARD_2_0
|
||||
#define QC_SUPPORTED
|
||||
#endif
|
||||
|
||||
using System;
|
||||
using System.CodeDom.Compiler;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
|
||||
#if QC_SUPPORTED
|
||||
namespace CSharpCompiler
|
||||
{
|
||||
public class ScriptBundleLoader
|
||||
{
|
||||
public Func<Type, object> createInstance = (Type type) => { return Activator.CreateInstance(type); };
|
||||
public Action<object> destroyInstance = delegate { };
|
||||
|
||||
public TextWriter logWriter = Console.Out;
|
||||
|
||||
ISynchronizeInvoke synchronizedInvoke;
|
||||
List<ScriptBundle> allFilesBundle = new List<ScriptBundle>();
|
||||
|
||||
public ScriptBundleLoader(ISynchronizeInvoke synchronizedInvoke)
|
||||
{
|
||||
this.synchronizedInvoke = synchronizedInvoke;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="fileSources"></param>
|
||||
/// <returns>true on success, false on failure</returns>
|
||||
public ScriptBundle LoadAndWatchScriptsBundle(IEnumerable<string> fileSources)
|
||||
{
|
||||
var bundle = new ScriptBundle(this, fileSources);
|
||||
allFilesBundle.Add(bundle);
|
||||
return bundle;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Manages a bundle of files which form one assembly, if one file changes entire assembly is recompiled.
|
||||
/// </summary>
|
||||
public class ScriptBundle
|
||||
{
|
||||
Assembly assembly;
|
||||
IEnumerable<string> filePaths;
|
||||
List<FileSystemWatcher> fileSystemWatchers = new List<FileSystemWatcher>();
|
||||
List<object> instances = new List<object>();
|
||||
ScriptBundleLoader manager;
|
||||
|
||||
string[] assemblyReferences;
|
||||
public ScriptBundle(ScriptBundleLoader manager, IEnumerable<string> filePaths)
|
||||
{
|
||||
this.filePaths = filePaths.Select(x => Path.GetFullPath(x));
|
||||
this.manager = manager;
|
||||
|
||||
var domain = System.AppDomain.CurrentDomain;
|
||||
this.assemblyReferences = domain
|
||||
.GetAssemblies()
|
||||
.Where(a => !(a is System.Reflection.Emit.AssemblyBuilder) && !string.IsNullOrEmpty(a.Location))
|
||||
.Select(a => a.Location)
|
||||
.ToArray();
|
||||
|
||||
manager.logWriter.WriteLine("loading " + string.Join(", ", filePaths.ToArray()));
|
||||
CompileFiles();
|
||||
CreateFileWatchers();
|
||||
CreateNewInstances();
|
||||
}
|
||||
|
||||
void CompileFiles()
|
||||
{
|
||||
filePaths = filePaths.Where(x => File.Exists(x)).ToArray();
|
||||
|
||||
var options = new CompilerParameters();
|
||||
options.GenerateExecutable = false;
|
||||
options.GenerateInMemory = true;
|
||||
options.ReferencedAssemblies.AddRange(assemblyReferences);
|
||||
|
||||
var compiler = new CodeCompiler();
|
||||
var result = compiler.CompileAssemblyFromFileBatch(options, filePaths.ToArray());
|
||||
|
||||
foreach (var err in result.Errors)
|
||||
{
|
||||
manager.logWriter.WriteLine(err);
|
||||
}
|
||||
|
||||
this.assembly = result.CompiledAssembly;
|
||||
}
|
||||
void CreateFileWatchers()
|
||||
{
|
||||
foreach (var filePath in filePaths)
|
||||
{
|
||||
FileSystemWatcher watcher = new FileSystemWatcher();
|
||||
fileSystemWatchers.Add(watcher);
|
||||
watcher.Path = Path.GetDirectoryName(filePath);
|
||||
/* Watch for changes in LastAccess and LastWrite times, and
|
||||
the renaming of files or directories. */
|
||||
watcher.NotifyFilter = NotifyFilters.LastWrite
|
||||
| NotifyFilters.FileName | NotifyFilters.DirectoryName;
|
||||
watcher.Filter = Path.GetFileName(filePath);
|
||||
|
||||
// Add event handlers.
|
||||
watcher.Changed += new FileSystemEventHandler((object o, FileSystemEventArgs a) => { Reload(recreateWatchers: false); });
|
||||
//watcher.Created += new FileSystemEventHandler((object o, FileSystemEventArgs a) => { });
|
||||
watcher.Deleted += new FileSystemEventHandler((object o, FileSystemEventArgs a) => { Reload(recreateWatchers: false); });
|
||||
watcher.Renamed += new RenamedEventHandler((object o, RenamedEventArgs a) =>
|
||||
{
|
||||
filePaths = filePaths.Select(x =>
|
||||
{
|
||||
if (x == a.OldFullPath) return a.FullPath;
|
||||
else return x;
|
||||
});
|
||||
Reload(recreateWatchers: true);
|
||||
});
|
||||
watcher.SynchronizingObject = manager.synchronizedInvoke;
|
||||
// Begin watching.
|
||||
watcher.EnableRaisingEvents = true;
|
||||
}
|
||||
}
|
||||
void StopFileWatchers()
|
||||
{
|
||||
foreach (var w in fileSystemWatchers)
|
||||
{
|
||||
w.EnableRaisingEvents = false;
|
||||
w.Dispose();
|
||||
}
|
||||
fileSystemWatchers.Clear();
|
||||
}
|
||||
void Reload(bool recreateWatchers = false)
|
||||
{
|
||||
manager.logWriter.WriteLine("reloading " + string.Join(", ", filePaths.ToArray()));
|
||||
StopInstances();
|
||||
CompileFiles();
|
||||
CreateNewInstances();
|
||||
if (recreateWatchers)
|
||||
{
|
||||
StopFileWatchers();
|
||||
CreateFileWatchers();
|
||||
}
|
||||
}
|
||||
void CreateNewInstances()
|
||||
{
|
||||
if (assembly == null) return;
|
||||
foreach (var type in assembly.GetTypes())
|
||||
{
|
||||
manager.synchronizedInvoke.Invoke((System.Action)(() =>
|
||||
{
|
||||
instances.Add(manager.createInstance(type));
|
||||
}), null);
|
||||
}
|
||||
}
|
||||
void StopInstances()
|
||||
{
|
||||
foreach (var instance in instances)
|
||||
{
|
||||
manager.synchronizedInvoke.Invoke((System.Action)(() =>
|
||||
{
|
||||
manager.destroyInstance(instance);
|
||||
}), null);
|
||||
}
|
||||
instances.Clear();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
#endif
|
|
@ -0,0 +1,12 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 3dfc88ca39a87dc46bc7fd337be863bb
|
||||
timeCreated: 1440503653
|
||||
licenseType: Store
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,110 @@
|
|||
#if NET_4_6 && !NET_STANDARD_2_0
|
||||
#define QC_SUPPORTED
|
||||
#endif
|
||||
|
||||
#if QC_SUPPORTED
|
||||
using System;
|
||||
using System.CodeDom.Compiler;
|
||||
using System.IO;
|
||||
using System.Reflection;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace QFSW.QC
|
||||
{
|
||||
public static class DynamicCodeCommands
|
||||
{
|
||||
private const Platform execAvailability = Platform.AllPlatforms ^ (Platform.WebGLPlayer | Platform.IPhonePlayer | Platform.XboxOne | Platform.PS4 | Platform.Switch);
|
||||
|
||||
[CommandDescription("Loads the code at the specified file and compiles it to C# which will then be executed. Use with caution as no safety checks will be performed. Not supported in AOT (IL2CPP) builds." +
|
||||
"\n\nBy default, boiler plate code will NOT be inserted around the code you provide. Please see 'exec' for more information about boilerplate insertion")]
|
||||
[Command("exec-extern", execAvailability)]
|
||||
private static async Task ExecuteExternalArbitaryCodeAsync(string filePath, bool insertBoilerplate = false)
|
||||
{
|
||||
if (!File.Exists(filePath)) { throw new ArgumentException($"file at the specified path '{filePath}' did not exist."); }
|
||||
string code = File.ReadAllText(filePath);
|
||||
await ExecuteArbitaryCodeAsync(code.Replace("”", "\"").Replace("“", "\""), insertBoilerplate);
|
||||
}
|
||||
|
||||
[CommandDescription("Compiles the given code to C# which will then be executed. Use with caution as no safety checks will be performed. Not supported in AOT (IL2CPP) builds." +
|
||||
"\n\nBy default, boiler plate code will be inserted around the code you provide. This means various namespaces will be included, and the main class and main function entry point will " +
|
||||
"provided. In this case, the code you provide should be code that would exist within the body of the main function, and thus cannot contain things such as class definition. If you " +
|
||||
"disable boiler plate insertion, you can write whatever code you want, however you must provide a static entry point called Main in a static class called Program")]
|
||||
[Command("exec", execAvailability)]
|
||||
private static async Task ExecuteArbitaryCodeAsync(string code, bool insertBoilerplate = true)
|
||||
{
|
||||
#if !UNITY_EDITOR && ENABLE_IL2CPP
|
||||
await Task.FromException(new Exception("exec is not supported on AOT platforms such as IL2CPP and requires JIT (Mono)."));
|
||||
#else
|
||||
MethodInfo entryPoint = await Task.Run(() =>
|
||||
{
|
||||
string fullCode = string.Empty;
|
||||
if (insertBoilerplate)
|
||||
{
|
||||
string[] includedNamespaces = new string[] { "System", "System.Collections", "System.Collections.Generic",
|
||||
"System.Reflection", "System.Linq", "System.Text", "System.Globalization",
|
||||
"UnityEngine", "UnityEngine.Events", "UnityEngine.EventSystems", "UnityEngine.UI" };
|
||||
|
||||
for (int i = 0; i < includedNamespaces.Length; i++) { fullCode += $"using {includedNamespaces[i]};\n"; }
|
||||
fullCode += @"
|
||||
public class Program
|
||||
{
|
||||
public static void Main()
|
||||
{"
|
||||
+ code +
|
||||
@"}
|
||||
}";
|
||||
}
|
||||
else { fullCode = code; }
|
||||
|
||||
Assembly assembly = CompileCode(fullCode);
|
||||
BindingFlags searchFlags = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static;
|
||||
Type program = assembly.GetType("Program");
|
||||
if (program == null) { throw new ArgumentException("Code Execution Failure - required static class Program could not be found"); }
|
||||
entryPoint = program.GetMethod("Main", searchFlags);
|
||||
if (entryPoint == null) { throw new ArgumentException("Code Execution Failure - required static entry point Main could not be found"); }
|
||||
return entryPoint;
|
||||
});
|
||||
|
||||
entryPoint.Invoke(null, null);
|
||||
#endif
|
||||
}
|
||||
|
||||
private static Assembly CompileCode(string code)
|
||||
{
|
||||
#if !UNITY_EDITOR && ENABLE_IL2CPP
|
||||
throw new Exception("Code compilation is not supported on AOT platforms such as IL2CPP and requires JIT (Mono).");
|
||||
#else
|
||||
CSharpCompiler.CodeCompiler compiler = new CSharpCompiler.CodeCompiler();
|
||||
CompilerParameters compilerParams = new CompilerParameters();
|
||||
Assembly[] allLoadedAssemblies = AppDomain.CurrentDomain.GetAssemblies();
|
||||
|
||||
compilerParams.GenerateExecutable = false;
|
||||
compilerParams.GenerateInMemory = true;
|
||||
for (int i = 0; i < allLoadedAssemblies.Length; i++)
|
||||
{
|
||||
if (!allLoadedAssemblies[i].IsDynamic)
|
||||
{
|
||||
string dllName = allLoadedAssemblies[i].Location;
|
||||
compilerParams.ReferencedAssemblies.Add(dllName);
|
||||
}
|
||||
}
|
||||
|
||||
CompilerResults compiledCode = compiler.CompileAssemblyFromSource(compilerParams, code);
|
||||
|
||||
if (compiledCode.Errors.HasErrors)
|
||||
{
|
||||
string errorMessage = "Code Compilation Failure";
|
||||
for (int i = 0; i < compiledCode.Errors.Count; i++)
|
||||
{
|
||||
errorMessage += $"\n{compiledCode.Errors[i].ErrorNumber} - {compiledCode.Errors[i].ErrorText}";
|
||||
}
|
||||
|
||||
throw new ArgumentException(errorMessage);
|
||||
}
|
||||
|
||||
return compiledCode.CompiledAssembly;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
|
@ -0,0 +1,12 @@
|
|||
fileFormatVersion: 2
|
||||
guid: e32a67fb03a2f6548b653203ff9fedf3
|
||||
timeCreated: 1553955853
|
||||
licenseType: Store
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,8 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 62f36e9490c247741aa6c9b5e545f9be
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,111 @@
|
|||
|
||||
SIL Open Font License v1.1
|
||||
---------------------------------------
|
||||
|
||||
This Font Software is licensed under the SIL Open Font License, Version 1.1
|
||||
This license is also available with a FAQ at: http://scripts.sil.org/OFL
|
||||
|
||||
Reserved font name: "Office Code Pro"
|
||||
|
||||
Copyright © 2015 Nathan Rutzky ( www.nath.co )
|
||||
Copyright © 2015 Adobe Systems ( www.adobe.com )
|
||||
|
||||
All Rights Reserved.
|
||||
|
||||
|
||||
PREAMBLE
|
||||
---------------------------------------
|
||||
|
||||
The goals of the Open Font License (OFL) are to stimulate worldwide
|
||||
development of collaborative font projects, to support the font creation
|
||||
efforts of academic and linguistic communities, and to provide a free and
|
||||
open framework in which fonts may be shared and improved in partnership
|
||||
with others.
|
||||
|
||||
The OFL allows the licensed fonts to be used, studied, modified and
|
||||
redistributed freely as long as they are not sold by themselves. The
|
||||
fonts, including any derivative works, can be bundled, embedded,
|
||||
redistributed and/or sold with any software provided that any reserved
|
||||
names are not used by derivative works. The fonts and derivatives,
|
||||
however, cannot be released under any other type of license. The
|
||||
requirement for fonts to remain under this license does not apply
|
||||
to any document created using the fonts or their derivatives.
|
||||
|
||||
|
||||
DEFINITIONS
|
||||
---------------------------------------
|
||||
|
||||
`"Font Software"` refers to the set of files released by the Copyright
|
||||
Holder(s) under this license and clearly marked as such. This may
|
||||
include source files, build scripts and documentation.
|
||||
|
||||
`"Reserved Font Name"` refers to any names specified as such after the
|
||||
copyright statement(s).
|
||||
|
||||
`"Original Version"` refers to the collection of Font Software components as
|
||||
distributed by the Copyright Holder(s).
|
||||
|
||||
`"Modified Version"` refers to any derivative made by adding to, deleting,
|
||||
or substituting -- in part or in whole -- any of the components of the
|
||||
Original Version, by changing formats or by porting the Font Software to a
|
||||
new environment.
|
||||
|
||||
`"Author"` refers to any designer, engineer, programmer, technical
|
||||
writer or other person who contributed to the Font Software.
|
||||
|
||||
|
||||
PERMISSION & CONDITIONS
|
||||
---------------------------------------
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of the Font Software, to use, study, copy, merge, embed, modify,
|
||||
redistribute, and sell modified and unmodified copies of the Font
|
||||
Software, subject to the following conditions:
|
||||
|
||||
1. Neither the Font Software nor any of its individual components,
|
||||
in Original or Modified Versions, may be sold by itself.
|
||||
|
||||
2. Original or Modified Versions of the Font Software may be bundled,
|
||||
redistributed and/or sold with any software, provided that each copy
|
||||
contains the above copyright notice and this license. These can be
|
||||
included either as stand-alone text files, human-readable headers or
|
||||
in the appropriate machine-readable metadata fields within text or
|
||||
binary files as long as those fields can be easily viewed by the user.
|
||||
|
||||
3. No Modified Version of the Font Software may use the Reserved Font
|
||||
Name(s) unless explicit written permission is granted by the corresponding
|
||||
Copyright Holder. This restriction only applies to the primary font name as
|
||||
presented to the users.
|
||||
|
||||
4. The name(s) of the Copyright Holder(s) or the Author(s) of the Font
|
||||
Software shall not be used to promote, endorse or advertise any
|
||||
Modified Version, except to acknowledge the contribution(s) of the
|
||||
Copyright Holder(s) and the Author(s) or with their explicit written
|
||||
permission.
|
||||
|
||||
5. The Font Software, modified or unmodified, in part or in whole,
|
||||
must be distributed entirely under this license, and must not be
|
||||
distributed under any other license. The requirement for fonts to
|
||||
remain under this license does not apply to any document created
|
||||
using the Font Software.
|
||||
|
||||
|
||||
TERMINATION
|
||||
---------------------------------------
|
||||
|
||||
This license becomes null and void if any of the above conditions are
|
||||
not met.
|
||||
|
||||
|
||||
DISCLAIMER
|
||||
---------------------------------------
|
||||
|
||||
THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
|
||||
OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
|
||||
COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
|
||||
DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
|
||||
OTHER DEALINGS IN THE FONT SOFTWARE.
|
|
@ -0,0 +1,7 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 5cfab2462b62dee47ba1dc3ebb9eb955
|
||||
TextScriptImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,27 @@
|
|||
fileFormatVersion: 2
|
||||
guid: d0fb8e3996ea8e7419e719f298606d45
|
||||
TrueTypeFontImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 4
|
||||
fontSize: 16
|
||||
forceTextureCase: -2
|
||||
characterSpacing: 0
|
||||
characterPadding: 1
|
||||
includeFontData: 1
|
||||
fontName: Office Code Pro
|
||||
fontNames:
|
||||
- Office Code Pro
|
||||
fallbackFontReferences:
|
||||
- {fileID: 12800000, guid: 4b7d48f1a9584dc4a978e5413f2f0cdc, type: 3}
|
||||
- {fileID: 12800000, guid: 999b9956011029e489cf8670db0e3da1, type: 3}
|
||||
- {fileID: 12800000, guid: 5e9f3008ed4fcd44abfab02627813be7, type: 3}
|
||||
- {fileID: 12800000, guid: 32c1196d211019546904eb4ea3890aec, type: 3}
|
||||
- {fileID: 12800000, guid: 7b29088eb3cae8e4dac72276f32da198, type: 3}
|
||||
customCharacters:
|
||||
fontRenderingMode: 0
|
||||
ascentCalculationMode: 1
|
||||
useLegacyBoundsCalculation: 0
|
||||
shouldRoundAdvanceValue: 1
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,22 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 32c1196d211019546904eb4ea3890aec
|
||||
TrueTypeFontImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 4
|
||||
fontSize: 16
|
||||
forceTextureCase: -2
|
||||
characterSpacing: 0
|
||||
characterPadding: 1
|
||||
includeFontData: 1
|
||||
fontName: Office Code Pro
|
||||
fontNames:
|
||||
- Office Code Pro
|
||||
fallbackFontReferences: []
|
||||
customCharacters:
|
||||
fontRenderingMode: 0
|
||||
ascentCalculationMode: 1
|
||||
useLegacyBoundsCalculation: 0
|
||||
shouldRoundAdvanceValue: 1
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,23 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 4b7d48f1a9584dc4a978e5413f2f0cdc
|
||||
TrueTypeFontImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 4
|
||||
fontSize: 16
|
||||
forceTextureCase: -2
|
||||
characterSpacing: 0
|
||||
characterPadding: 1
|
||||
includeFontData: 1
|
||||
fontName: Office Code Pro
|
||||
fontNames:
|
||||
- Office Code Pro
|
||||
fallbackFontReferences:
|
||||
- {fileID: 12800000, guid: 32c1196d211019546904eb4ea3890aec, type: 3}
|
||||
customCharacters:
|
||||
fontRenderingMode: 0
|
||||
ascentCalculationMode: 1
|
||||
useLegacyBoundsCalculation: 0
|
||||
shouldRoundAdvanceValue: 1
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,25 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 7b29088eb3cae8e4dac72276f32da198
|
||||
TrueTypeFontImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 4
|
||||
fontSize: 16
|
||||
forceTextureCase: -2
|
||||
characterSpacing: 0
|
||||
characterPadding: 1
|
||||
includeFontData: 1
|
||||
fontName: Office Code Pro
|
||||
fontNames:
|
||||
- Office Code Pro
|
||||
fallbackFontReferences:
|
||||
- {fileID: 12800000, guid: 4b7d48f1a9584dc4a978e5413f2f0cdc, type: 3}
|
||||
- {fileID: 12800000, guid: 5e9f3008ed4fcd44abfab02627813be7, type: 3}
|
||||
- {fileID: 12800000, guid: 32c1196d211019546904eb4ea3890aec, type: 3}
|
||||
customCharacters:
|
||||
fontRenderingMode: 0
|
||||
ascentCalculationMode: 1
|
||||
useLegacyBoundsCalculation: 0
|
||||
shouldRoundAdvanceValue: 1
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,28 @@
|
|||
fileFormatVersion: 2
|
||||
guid: e7f9c7e4780a90b45b581308e8a2f94a
|
||||
TrueTypeFontImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 4
|
||||
fontSize: 16
|
||||
forceTextureCase: -2
|
||||
characterSpacing: 0
|
||||
characterPadding: 1
|
||||
includeFontData: 1
|
||||
fontName: Office Code Pro
|
||||
fontNames:
|
||||
- Office Code Pro
|
||||
fallbackFontReferences:
|
||||
- {fileID: 12800000, guid: 4b7d48f1a9584dc4a978e5413f2f0cdc, type: 3}
|
||||
- {fileID: 12800000, guid: 999b9956011029e489cf8670db0e3da1, type: 3}
|
||||
- {fileID: 12800000, guid: 5e9f3008ed4fcd44abfab02627813be7, type: 3}
|
||||
- {fileID: 12800000, guid: d0fb8e3996ea8e7419e719f298606d45, type: 3}
|
||||
- {fileID: 12800000, guid: 32c1196d211019546904eb4ea3890aec, type: 3}
|
||||
- {fileID: 12800000, guid: 7b29088eb3cae8e4dac72276f32da198, type: 3}
|
||||
customCharacters:
|
||||
fontRenderingMode: 0
|
||||
ascentCalculationMode: 1
|
||||
useLegacyBoundsCalculation: 0
|
||||
shouldRoundAdvanceValue: 1
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,26 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 999b9956011029e489cf8670db0e3da1
|
||||
TrueTypeFontImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 4
|
||||
fontSize: 16
|
||||
forceTextureCase: -2
|
||||
characterSpacing: 0
|
||||
characterPadding: 1
|
||||
includeFontData: 1
|
||||
fontName: Office Code Pro
|
||||
fontNames:
|
||||
- Office Code Pro
|
||||
fallbackFontReferences:
|
||||
- {fileID: 12800000, guid: 4b7d48f1a9584dc4a978e5413f2f0cdc, type: 3}
|
||||
- {fileID: 12800000, guid: 5e9f3008ed4fcd44abfab02627813be7, type: 3}
|
||||
- {fileID: 12800000, guid: 32c1196d211019546904eb4ea3890aec, type: 3}
|
||||
- {fileID: 12800000, guid: 7b29088eb3cae8e4dac72276f32da198, type: 3}
|
||||
customCharacters:
|
||||
fontRenderingMode: 0
|
||||
ascentCalculationMode: 1
|
||||
useLegacyBoundsCalculation: 0
|
||||
shouldRoundAdvanceValue: 1
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,29 @@
|
|||
fileFormatVersion: 2
|
||||
guid: eb42c3b8bd49c574bb98289bb3ea122c
|
||||
TrueTypeFontImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 4
|
||||
fontSize: 16
|
||||
forceTextureCase: -2
|
||||
characterSpacing: 0
|
||||
characterPadding: 1
|
||||
includeFontData: 1
|
||||
fontName: Office Code Pro
|
||||
fontNames:
|
||||
- Office Code Pro
|
||||
fallbackFontReferences:
|
||||
- {fileID: 12800000, guid: 4b7d48f1a9584dc4a978e5413f2f0cdc, type: 3}
|
||||
- {fileID: 12800000, guid: e7f9c7e4780a90b45b581308e8a2f94a, type: 3}
|
||||
- {fileID: 12800000, guid: 999b9956011029e489cf8670db0e3da1, type: 3}
|
||||
- {fileID: 12800000, guid: 5e9f3008ed4fcd44abfab02627813be7, type: 3}
|
||||
- {fileID: 12800000, guid: d0fb8e3996ea8e7419e719f298606d45, type: 3}
|
||||
- {fileID: 12800000, guid: 32c1196d211019546904eb4ea3890aec, type: 3}
|
||||
- {fileID: 12800000, guid: 7b29088eb3cae8e4dac72276f32da198, type: 3}
|
||||
customCharacters:
|
||||
fontRenderingMode: 0
|
||||
ascentCalculationMode: 1
|
||||
useLegacyBoundsCalculation: 0
|
||||
shouldRoundAdvanceValue: 1
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,24 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 5e9f3008ed4fcd44abfab02627813be7
|
||||
TrueTypeFontImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 4
|
||||
fontSize: 16
|
||||
forceTextureCase: -2
|
||||
characterSpacing: 0
|
||||
characterPadding: 1
|
||||
includeFontData: 1
|
||||
fontName: Office Code Pro
|
||||
fontNames:
|
||||
- Office Code Pro
|
||||
fallbackFontReferences:
|
||||
- {fileID: 12800000, guid: 4b7d48f1a9584dc4a978e5413f2f0cdc, type: 3}
|
||||
- {fileID: 12800000, guid: 32c1196d211019546904eb4ea3890aec, type: 3}
|
||||
customCharacters:
|
||||
fontRenderingMode: 0
|
||||
ascentCalculationMode: 1
|
||||
useLegacyBoundsCalculation: 0
|
||||
shouldRoundAdvanceValue: 1
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,8 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 683b46b9fd7bc7f4f8bda19cacf1c25d
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,8 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 03667487b095d134cb5d244fc285c9d1
|
||||
NativeFormatImporter:
|
||||
externalObjects: {}
|
||||
mainObjectFileID: 11400000
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,8 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 82a04213dfb8df0418ea8f3f47099dc5
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,131 @@
|
|||
%YAML 1.1
|
||||
%TAG !u! tag:unity3d.com,2011:
|
||||
--- !u!21 &2100000
|
||||
Material:
|
||||
serializedVersion: 8
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_Name: Blur Panel
|
||||
m_Shader: {fileID: 4800000, guid: 933532a4fcc9baf4fa0491de14d08ed7, type: 3}
|
||||
m_ValidKeywords: []
|
||||
m_InvalidKeywords: []
|
||||
m_LightmapFlags: 4
|
||||
m_EnableInstancingVariants: 0
|
||||
m_DoubleSidedGI: 0
|
||||
m_CustomRenderQueue: -1
|
||||
stringTagMap:
|
||||
RenderType: Opaque
|
||||
disabledShaderPasses: []
|
||||
m_SavedProperties:
|
||||
serializedVersion: 3
|
||||
m_TexEnvs:
|
||||
- _BaseMap:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- _BumpMap:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- _DetailAlbedoMap:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- _DetailMask:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- _DetailNormalMap:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- _EmissionMap:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- _MainTex:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- _MetallicGlossMap:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- _OcclusionMap:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- _ParallaxMap:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- _SpecGlossMap:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- unity_Lightmaps:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- unity_LightmapsInd:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- unity_ShadowMasks:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
m_Ints: []
|
||||
m_Floats:
|
||||
- _AlphaClip: 0
|
||||
- _Blend: 0
|
||||
- _BumpAmt: 10
|
||||
- _BumpScale: 1
|
||||
- _ClearCoatMask: 0
|
||||
- _ClearCoatSmoothness: 0
|
||||
- _Cull: 2
|
||||
- _Cutoff: 0.5
|
||||
- _DetailAlbedoMapScale: 1
|
||||
- _DetailNormalMapScale: 1
|
||||
- _DstBlend: 0
|
||||
- _EnvironmentReflections: 1
|
||||
- _GlossMapScale: 1
|
||||
- _Glossiness: 0.5
|
||||
- _GlossyReflections: 1
|
||||
- _Metallic: 0
|
||||
- _Mode: 0
|
||||
- _OcclusionStrength: 1
|
||||
- _Parallax: 0.02
|
||||
- _QueueOffset: 0
|
||||
- _Radius: 3
|
||||
- _ReceiveShadows: 1
|
||||
- _Smoothness: 0.5
|
||||
- _SmoothnessTextureChannel: 0
|
||||
- _SpecularHighlights: 1
|
||||
- _SrcBlend: 1
|
||||
- _Surface: 0
|
||||
- _UVSec: 0
|
||||
- _WorkflowMode: 1
|
||||
- _ZWrite: 1
|
||||
m_Colors:
|
||||
- _BaseColor: {r: 0.11320752, g: 0.11320752, b: 0.11320752, a: 1}
|
||||
- _Color: {r: 0.1132075, g: 0.1132075, b: 0.1132075, a: 1}
|
||||
- _EmissionColor: {r: 0, g: 0, b: 0, a: 1}
|
||||
- _OverlayColor: {r: 0.0754902, g: 0.1237255, b: 0.19607843, a: 0.16862746}
|
||||
- _SpecColor: {r: 0.19999996, g: 0.19999996, b: 0.19999996, a: 1}
|
||||
m_BuildTextureStacks: []
|
||||
--- !u!114 &2339474354693369228
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 11
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 0}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: d0353a89b1f911e48b9e16bdc9f2e058, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
version: 5
|
|
@ -0,0 +1,8 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 3f5fb7a53313bca46bc093dae10de6e4
|
||||
NativeFormatImporter:
|
||||
externalObjects: {}
|
||||
mainObjectFileID: 2100000
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,8 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 6040c682eb70bbf418ab42e0fe8f1fb9
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,62 @@
|
|||
%YAML 1.1
|
||||
%TAG !u! tag:unity3d.com,2011:
|
||||
--- !u!114 &11400000
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 0}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: a59acf1affd56c94fa937563dd75c947, type: 3}
|
||||
m_Name: Default Key Config
|
||||
m_EditorClassIdentifier:
|
||||
SubmitCommandKey: 13
|
||||
ShowConsoleKey:
|
||||
Key: 0
|
||||
Ctrl: 0
|
||||
Alt: 0
|
||||
Shift: 0
|
||||
HideConsoleKey:
|
||||
Key: 0
|
||||
Ctrl: 0
|
||||
Alt: 0
|
||||
Shift: 0
|
||||
ToggleConsoleVisibilityKey:
|
||||
Key: 113
|
||||
Ctrl: 0
|
||||
Alt: 0
|
||||
Shift: 0
|
||||
ZoomInKey:
|
||||
Key: 61
|
||||
Ctrl: 1
|
||||
Alt: 0
|
||||
Shift: 0
|
||||
ZoomOutKey:
|
||||
Key: 45
|
||||
Ctrl: 1
|
||||
Alt: 0
|
||||
Shift: 0
|
||||
DragConsoleKey:
|
||||
Key: 323
|
||||
Ctrl: 0
|
||||
Alt: 0
|
||||
Shift: 1
|
||||
SuggestNextCommandKey:
|
||||
Key: 9
|
||||
Ctrl: 0
|
||||
Alt: 0
|
||||
Shift: 0
|
||||
SuggestPreviousCommandKey:
|
||||
Key: 9
|
||||
Ctrl: 0
|
||||
Alt: 0
|
||||
Shift: 1
|
||||
NextCommandKey: 273
|
||||
PreviousCommandKey: 274
|
||||
CancelActionsKey:
|
||||
Key: 99
|
||||
Ctrl: 1
|
||||
Alt: 0
|
||||
Shift: 0
|
|
@ -0,0 +1,8 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 090da11157287de47ae5c615b8ed3cf9
|
||||
NativeFormatImporter:
|
||||
externalObjects: {}
|
||||
mainObjectFileID: 11400000
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,58 @@
|
|||
%YAML 1.1
|
||||
%TAG !u! tag:unity3d.com,2011:
|
||||
--- !u!114 &11400000
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 0}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: 49e15215dd5c7444aa955d9a8a83fea0, type: 3}
|
||||
m_Name: Default Theme (SRP)
|
||||
m_EditorClassIdentifier:
|
||||
Font: {fileID: 11400000, guid: 03667487b095d134cb5d244fc285c9d1, type: 2}
|
||||
PanelMaterial: {fileID: 0}
|
||||
PanelColor: {r: 0.105882354, g: 0.1254902, b: 0.14901961, a: 0.9411765}
|
||||
CommandLogColor: {r: 0, g: 1, b: 1, a: 1}
|
||||
SelectedSuggestionColor: {r: 1, g: 1, b: 0.427, a: 1}
|
||||
SuggestionColor: {r: 0.601, g: 0.601, b: 0.601, a: 1}
|
||||
ErrorColor: {r: 1, g: 0, b: 0, a: 1}
|
||||
WarningColor: {r: 1, g: 0.5, b: 0, a: 1}
|
||||
SuccessColor: {r: 0, g: 1, b: 0, a: 1}
|
||||
TimestampFormat: '[{0:00}:{1:00}:{2:00}]'
|
||||
DefaultReturnValueColor: {r: 1, g: 0.7372549, b: 0.54901963, a: 1}
|
||||
TypeFormatters:
|
||||
- _type: System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
|
||||
Color: {r: 1, g: 1, b: 1, a: 1}
|
||||
- _type: System.Collections.IEnumerable, mscorlib, Version=4.0.0.0, Culture=neutral,
|
||||
PublicKeyToken=b77a5c561934e089
|
||||
Color: {r: 0.99215686, g: 0.9490196, b: 0.4117647, a: 1}
|
||||
- _type: System.Collections.Generic.KeyValuePair`2, mscorlib, Version=4.0.0.0, Culture=neutral,
|
||||
PublicKeyToken=b77a5c561934e089
|
||||
Color: {r: 0.7311321, g: 1, b: 0.9315609, a: 1}
|
||||
- _type: System.Collections.DictionaryEntry, mscorlib, Version=4.0.0.0, Culture=neutral,
|
||||
PublicKeyToken=b77a5c561934e089
|
||||
Color: {r: 0.7294118, g: 1, b: 0.93333334, a: 1}
|
||||
- _type: System.Enum, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
|
||||
Color: {r: 0.7698444, g: 1, b: 0.54901963, a: 1}
|
||||
- _type: UnityEngine.Object, UnityEngine.CoreModule, Version=0.0.0.0, Culture=neutral,
|
||||
PublicKeyToken=null
|
||||
Color: {r: 0.96862745, g: 0.6, b: 1, a: 1}
|
||||
CollectionFormatters:
|
||||
- _type: System.Collections.Generic.Dictionary`2, mscorlib, Version=4.0.0.0, Culture=neutral,
|
||||
PublicKeyToken=b77a5c561934e089
|
||||
SeperatorString: \n
|
||||
LeftScoper:
|
||||
RightScoper:
|
||||
- _type: System.Collections.ICollection, mscorlib, Version=4.0.0.0, Culture=neutral,
|
||||
PublicKeyToken=b77a5c561934e089
|
||||
SeperatorString: ', '
|
||||
LeftScoper: '['
|
||||
RightScoper: ']'
|
||||
- _type: System.Collections.IEnumerable, mscorlib, Version=4.0.0.0, Culture=neutral,
|
||||
PublicKeyToken=b77a5c561934e089
|
||||
SeperatorString: \n
|
||||
LeftScoper:
|
||||
RightScoper:
|
|
@ -0,0 +1,8 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 769f3deee63c82a4c9896ac917227625
|
||||
NativeFormatImporter:
|
||||
externalObjects: {}
|
||||
mainObjectFileID: 0
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,58 @@
|
|||
%YAML 1.1
|
||||
%TAG !u! tag:unity3d.com,2011:
|
||||
--- !u!114 &11400000
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 0}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: 49e15215dd5c7444aa955d9a8a83fea0, type: 3}
|
||||
m_Name: Default Theme
|
||||
m_EditorClassIdentifier:
|
||||
Font: {fileID: 11400000, guid: 03667487b095d134cb5d244fc285c9d1, type: 2}
|
||||
PanelMaterial: {fileID: 2100000, guid: 3f5fb7a53313bca46bc093dae10de6e4, type: 2}
|
||||
PanelColor: {r: 1, g: 1, b: 1, a: 1}
|
||||
CommandLogColor: {r: 0, g: 1, b: 1, a: 1}
|
||||
SelectedSuggestionColor: {r: 1, g: 1, b: 0.427, a: 1}
|
||||
SuggestionColor: {r: 0.601, g: 0.601, b: 0.601, a: 1}
|
||||
ErrorColor: {r: 1, g: 0, b: 0, a: 1}
|
||||
WarningColor: {r: 1, g: 0.5, b: 0, a: 1}
|
||||
SuccessColor: {r: 0, g: 1, b: 0, a: 1}
|
||||
TimestampFormat: '[{0:00}:{1:00}:{2:00}]'
|
||||
DefaultReturnValueColor: {r: 1, g: 0.7372549, b: 0.54901963, a: 1}
|
||||
TypeFormatters:
|
||||
- _type: System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
|
||||
Color: {r: 1, g: 1, b: 1, a: 1}
|
||||
- _type: System.Collections.IEnumerable, mscorlib, Version=4.0.0.0, Culture=neutral,
|
||||
PublicKeyToken=b77a5c561934e089
|
||||
Color: {r: 0.99215686, g: 0.9490196, b: 0.4117647, a: 1}
|
||||
- _type: System.Collections.Generic.KeyValuePair`2, mscorlib, Version=4.0.0.0, Culture=neutral,
|
||||
PublicKeyToken=b77a5c561934e089
|
||||
Color: {r: 0.7311321, g: 1, b: 0.9315609, a: 1}
|
||||
- _type: System.Collections.DictionaryEntry, mscorlib, Version=4.0.0.0, Culture=neutral,
|
||||
PublicKeyToken=b77a5c561934e089
|
||||
Color: {r: 0.7294118, g: 1, b: 0.93333334, a: 1}
|
||||
- _type: System.Enum, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
|
||||
Color: {r: 0.7698444, g: 1, b: 0.54901963, a: 1}
|
||||
- _type: UnityEngine.Object, UnityEngine.CoreModule, Version=0.0.0.0, Culture=neutral,
|
||||
PublicKeyToken=null
|
||||
Color: {r: 0.96862745, g: 0.6, b: 1, a: 1}
|
||||
CollectionFormatters:
|
||||
- _type: System.Collections.Generic.Dictionary`2, mscorlib, Version=4.0.0.0, Culture=neutral,
|
||||
PublicKeyToken=b77a5c561934e089
|
||||
SeperatorString: \n
|
||||
LeftScoper:
|
||||
RightScoper:
|
||||
- _type: System.Collections.ICollection, mscorlib, Version=4.0.0.0, Culture=neutral,
|
||||
PublicKeyToken=b77a5c561934e089
|
||||
SeperatorString: ', '
|
||||
LeftScoper: '['
|
||||
RightScoper: ']'
|
||||
- _type: System.Collections.IEnumerable, mscorlib, Version=4.0.0.0, Culture=neutral,
|
||||
PublicKeyToken=b77a5c561934e089
|
||||
SeperatorString: \n
|
||||
LeftScoper:
|
||||
RightScoper:
|
|
@ -0,0 +1,8 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 5a19be32700ef4a13bfa337a662ef25b
|
||||
NativeFormatImporter:
|
||||
externalObjects: {}
|
||||
mainObjectFileID: 11400000
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,481 @@
|
|||
%YAML 1.1
|
||||
%TAG !u! tag:unity3d.com,2011:
|
||||
--- !u!1001 &4621155404233898149
|
||||
PrefabInstance:
|
||||
m_ObjectHideFlags: 0
|
||||
serializedVersion: 2
|
||||
m_Modification:
|
||||
m_TransformParent: {fileID: 0}
|
||||
m_Modifications:
|
||||
- target: {fileID: 1263217620473054, guid: 9ed2a051c32b4fe47a5e4fb95c20b03f, type: 3}
|
||||
propertyPath: m_Name
|
||||
value: Quantum Console (SRP)
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 224130951485110974, guid: 9ed2a051c32b4fe47a5e4fb95c20b03f,
|
||||
type: 3}
|
||||
propertyPath: m_SizeDelta.y
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 224130951485110974, guid: 9ed2a051c32b4fe47a5e4fb95c20b03f,
|
||||
type: 3}
|
||||
propertyPath: m_AnchoredPosition.y
|
||||
value: -517
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 224296548220470038, guid: 9ed2a051c32b4fe47a5e4fb95c20b03f,
|
||||
type: 3}
|
||||
propertyPath: m_LocalPosition.x
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 224296548220470038, guid: 9ed2a051c32b4fe47a5e4fb95c20b03f,
|
||||
type: 3}
|
||||
propertyPath: m_LocalPosition.y
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 224296548220470038, guid: 9ed2a051c32b4fe47a5e4fb95c20b03f,
|
||||
type: 3}
|
||||
propertyPath: m_RootOrder
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 224296548220470038, guid: 9ed2a051c32b4fe47a5e4fb95c20b03f,
|
||||
type: 3}
|
||||
propertyPath: m_LocalEulerAnglesHint.x
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 224296548220470038, guid: 9ed2a051c32b4fe47a5e4fb95c20b03f,
|
||||
type: 3}
|
||||
propertyPath: m_LocalEulerAnglesHint.y
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 224296548220470038, guid: 9ed2a051c32b4fe47a5e4fb95c20b03f,
|
||||
type: 3}
|
||||
propertyPath: m_LocalEulerAnglesHint.z
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 224005418473288314, guid: 9ed2a051c32b4fe47a5e4fb95c20b03f,
|
||||
type: 3}
|
||||
propertyPath: m_AnchorMax.x
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 224005418473288314, guid: 9ed2a051c32b4fe47a5e4fb95c20b03f,
|
||||
type: 3}
|
||||
propertyPath: m_AnchorMax.y
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 114689057623555238, guid: 9ed2a051c32b4fe47a5e4fb95c20b03f,
|
||||
type: 3}
|
||||
propertyPath: m_Size
|
||||
value: 1
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 224711696876568682, guid: 9ed2a051c32b4fe47a5e4fb95c20b03f,
|
||||
type: 3}
|
||||
propertyPath: m_AnchorMin.y
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 224711696876568682, guid: 9ed2a051c32b4fe47a5e4fb95c20b03f,
|
||||
type: 3}
|
||||
propertyPath: m_AnchorMax.y
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 224711696876568682, guid: 9ed2a051c32b4fe47a5e4fb95c20b03f,
|
||||
type: 3}
|
||||
propertyPath: m_AnchoredPosition.x
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 224711696876568682, guid: 9ed2a051c32b4fe47a5e4fb95c20b03f,
|
||||
type: 3}
|
||||
propertyPath: m_SizeDelta.x
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 224711696876568682, guid: 9ed2a051c32b4fe47a5e4fb95c20b03f,
|
||||
type: 3}
|
||||
propertyPath: m_SizeDelta.y
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 224166536479716514, guid: 9ed2a051c32b4fe47a5e4fb95c20b03f,
|
||||
type: 3}
|
||||
propertyPath: m_AnchorMin.y
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 224166536479716514, guid: 9ed2a051c32b4fe47a5e4fb95c20b03f,
|
||||
type: 3}
|
||||
propertyPath: m_AnchorMax.y
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 224166536479716514, guid: 9ed2a051c32b4fe47a5e4fb95c20b03f,
|
||||
type: 3}
|
||||
propertyPath: m_AnchoredPosition.x
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 224166536479716514, guid: 9ed2a051c32b4fe47a5e4fb95c20b03f,
|
||||
type: 3}
|
||||
propertyPath: m_AnchoredPosition.y
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 224166536479716514, guid: 9ed2a051c32b4fe47a5e4fb95c20b03f,
|
||||
type: 3}
|
||||
propertyPath: m_SizeDelta.x
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 224166536479716514, guid: 9ed2a051c32b4fe47a5e4fb95c20b03f,
|
||||
type: 3}
|
||||
propertyPath: m_SizeDelta.y
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 224773539050736570, guid: 9ed2a051c32b4fe47a5e4fb95c20b03f,
|
||||
type: 3}
|
||||
propertyPath: m_AnchorMin.y
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 224773539050736570, guid: 9ed2a051c32b4fe47a5e4fb95c20b03f,
|
||||
type: 3}
|
||||
propertyPath: m_AnchorMax.y
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 224773539050736570, guid: 9ed2a051c32b4fe47a5e4fb95c20b03f,
|
||||
type: 3}
|
||||
propertyPath: m_AnchoredPosition.x
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 224773539050736570, guid: 9ed2a051c32b4fe47a5e4fb95c20b03f,
|
||||
type: 3}
|
||||
propertyPath: m_AnchoredPosition.y
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 224773539050736570, guid: 9ed2a051c32b4fe47a5e4fb95c20b03f,
|
||||
type: 3}
|
||||
propertyPath: m_SizeDelta.x
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 224091110387865490, guid: 9ed2a051c32b4fe47a5e4fb95c20b03f,
|
||||
type: 3}
|
||||
propertyPath: m_AnchorMin.y
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 224091110387865490, guid: 9ed2a051c32b4fe47a5e4fb95c20b03f,
|
||||
type: 3}
|
||||
propertyPath: m_AnchorMax.y
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 224091110387865490, guid: 9ed2a051c32b4fe47a5e4fb95c20b03f,
|
||||
type: 3}
|
||||
propertyPath: m_AnchoredPosition.x
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 224091110387865490, guid: 9ed2a051c32b4fe47a5e4fb95c20b03f,
|
||||
type: 3}
|
||||
propertyPath: m_AnchoredPosition.y
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 224091110387865490, guid: 9ed2a051c32b4fe47a5e4fb95c20b03f,
|
||||
type: 3}
|
||||
propertyPath: m_SizeDelta.x
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 224484317424158076, guid: 9ed2a051c32b4fe47a5e4fb95c20b03f,
|
||||
type: 3}
|
||||
propertyPath: m_AnchorMin.y
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 224484317424158076, guid: 9ed2a051c32b4fe47a5e4fb95c20b03f,
|
||||
type: 3}
|
||||
propertyPath: m_AnchorMax.y
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 224484317424158076, guid: 9ed2a051c32b4fe47a5e4fb95c20b03f,
|
||||
type: 3}
|
||||
propertyPath: m_AnchoredPosition.x
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 224484317424158076, guid: 9ed2a051c32b4fe47a5e4fb95c20b03f,
|
||||
type: 3}
|
||||
propertyPath: m_AnchoredPosition.y
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 224484317424158076, guid: 9ed2a051c32b4fe47a5e4fb95c20b03f,
|
||||
type: 3}
|
||||
propertyPath: m_SizeDelta.x
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 224642173552212536, guid: 9ed2a051c32b4fe47a5e4fb95c20b03f,
|
||||
type: 3}
|
||||
propertyPath: m_AnchorMin.y
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 224642173552212536, guid: 9ed2a051c32b4fe47a5e4fb95c20b03f,
|
||||
type: 3}
|
||||
propertyPath: m_AnchorMax.y
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 224642173552212536, guid: 9ed2a051c32b4fe47a5e4fb95c20b03f,
|
||||
type: 3}
|
||||
propertyPath: m_AnchoredPosition.x
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 224642173552212536, guid: 9ed2a051c32b4fe47a5e4fb95c20b03f,
|
||||
type: 3}
|
||||
propertyPath: m_AnchoredPosition.y
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 224642173552212536, guid: 9ed2a051c32b4fe47a5e4fb95c20b03f,
|
||||
type: 3}
|
||||
propertyPath: m_SizeDelta.x
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 114372194528546136, guid: 9ed2a051c32b4fe47a5e4fb95c20b03f,
|
||||
type: 3}
|
||||
propertyPath: m_Material
|
||||
value:
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 114372194528546136, guid: 9ed2a051c32b4fe47a5e4fb95c20b03f,
|
||||
type: 3}
|
||||
propertyPath: m_Color.r
|
||||
value: 0.105882354
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 114372194528546136, guid: 9ed2a051c32b4fe47a5e4fb95c20b03f,
|
||||
type: 3}
|
||||
propertyPath: m_Color.g
|
||||
value: 0.1254902
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 114372194528546136, guid: 9ed2a051c32b4fe47a5e4fb95c20b03f,
|
||||
type: 3}
|
||||
propertyPath: m_Color.b
|
||||
value: 0.14901961
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 114372194528546136, guid: 9ed2a051c32b4fe47a5e4fb95c20b03f,
|
||||
type: 3}
|
||||
propertyPath: m_Color.a
|
||||
value: 0.9411765
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 114934208999440956, guid: 9ed2a051c32b4fe47a5e4fb95c20b03f,
|
||||
type: 3}
|
||||
propertyPath: m_Material
|
||||
value:
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 114934208999440956, guid: 9ed2a051c32b4fe47a5e4fb95c20b03f,
|
||||
type: 3}
|
||||
propertyPath: m_Color.r
|
||||
value: 0.105882354
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 114934208999440956, guid: 9ed2a051c32b4fe47a5e4fb95c20b03f,
|
||||
type: 3}
|
||||
propertyPath: m_Color.g
|
||||
value: 0.1254902
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 114934208999440956, guid: 9ed2a051c32b4fe47a5e4fb95c20b03f,
|
||||
type: 3}
|
||||
propertyPath: m_Color.b
|
||||
value: 0.14901961
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 114934208999440956, guid: 9ed2a051c32b4fe47a5e4fb95c20b03f,
|
||||
type: 3}
|
||||
propertyPath: m_Color.a
|
||||
value: 0.9411765
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 114478704479367178, guid: 9ed2a051c32b4fe47a5e4fb95c20b03f,
|
||||
type: 3}
|
||||
propertyPath: m_Material
|
||||
value:
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 114478704479367178, guid: 9ed2a051c32b4fe47a5e4fb95c20b03f,
|
||||
type: 3}
|
||||
propertyPath: m_Color.r
|
||||
value: 0.105882354
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 114478704479367178, guid: 9ed2a051c32b4fe47a5e4fb95c20b03f,
|
||||
type: 3}
|
||||
propertyPath: m_Color.g
|
||||
value: 0.1254902
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 114478704479367178, guid: 9ed2a051c32b4fe47a5e4fb95c20b03f,
|
||||
type: 3}
|
||||
propertyPath: m_Color.b
|
||||
value: 0.14901961
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 114478704479367178, guid: 9ed2a051c32b4fe47a5e4fb95c20b03f,
|
||||
type: 3}
|
||||
propertyPath: m_Color.a
|
||||
value: 0.9411765
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 114174508808301238, guid: 9ed2a051c32b4fe47a5e4fb95c20b03f,
|
||||
type: 3}
|
||||
propertyPath: m_Material
|
||||
value:
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 114174508808301238, guid: 9ed2a051c32b4fe47a5e4fb95c20b03f,
|
||||
type: 3}
|
||||
propertyPath: m_Color.r
|
||||
value: 0.105882354
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 114174508808301238, guid: 9ed2a051c32b4fe47a5e4fb95c20b03f,
|
||||
type: 3}
|
||||
propertyPath: m_Color.g
|
||||
value: 0.1254902
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 114174508808301238, guid: 9ed2a051c32b4fe47a5e4fb95c20b03f,
|
||||
type: 3}
|
||||
propertyPath: m_Color.b
|
||||
value: 0.14901961
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 114174508808301238, guid: 9ed2a051c32b4fe47a5e4fb95c20b03f,
|
||||
type: 3}
|
||||
propertyPath: m_Color.a
|
||||
value: 0.9411765
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 3005720477010286325, guid: 9ed2a051c32b4fe47a5e4fb95c20b03f,
|
||||
type: 3}
|
||||
propertyPath: m_SizeDelta.x
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 2353330868778903658, guid: 9ed2a051c32b4fe47a5e4fb95c20b03f,
|
||||
type: 3}
|
||||
propertyPath: m_Material
|
||||
value:
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 2353330868778903658, guid: 9ed2a051c32b4fe47a5e4fb95c20b03f,
|
||||
type: 3}
|
||||
propertyPath: m_Color.r
|
||||
value: 0.105882354
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 2353330868778903658, guid: 9ed2a051c32b4fe47a5e4fb95c20b03f,
|
||||
type: 3}
|
||||
propertyPath: m_Color.g
|
||||
value: 0.1254902
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 2353330868778903658, guid: 9ed2a051c32b4fe47a5e4fb95c20b03f,
|
||||
type: 3}
|
||||
propertyPath: m_Color.b
|
||||
value: 0.14901961
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 2353330868778903658, guid: 9ed2a051c32b4fe47a5e4fb95c20b03f,
|
||||
type: 3}
|
||||
propertyPath: m_Color.a
|
||||
value: 0.9411765
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 363657505470348732, guid: 9ed2a051c32b4fe47a5e4fb95c20b03f,
|
||||
type: 3}
|
||||
propertyPath: m_AnchorMin.y
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 363657505470348732, guid: 9ed2a051c32b4fe47a5e4fb95c20b03f,
|
||||
type: 3}
|
||||
propertyPath: m_AnchorMax.y
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 363657505470348732, guid: 9ed2a051c32b4fe47a5e4fb95c20b03f,
|
||||
type: 3}
|
||||
propertyPath: m_AnchoredPosition.x
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 363657505470348732, guid: 9ed2a051c32b4fe47a5e4fb95c20b03f,
|
||||
type: 3}
|
||||
propertyPath: m_AnchoredPosition.y
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 363657505470348732, guid: 9ed2a051c32b4fe47a5e4fb95c20b03f,
|
||||
type: 3}
|
||||
propertyPath: m_SizeDelta.x
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 363657505470348732, guid: 9ed2a051c32b4fe47a5e4fb95c20b03f,
|
||||
type: 3}
|
||||
propertyPath: m_SizeDelta.y
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 4011473737907365368, guid: 9ed2a051c32b4fe47a5e4fb95c20b03f,
|
||||
type: 3}
|
||||
propertyPath: m_AnchorMin.y
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 4011473737907365368, guid: 9ed2a051c32b4fe47a5e4fb95c20b03f,
|
||||
type: 3}
|
||||
propertyPath: m_AnchorMax.y
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 4011473737907365368, guid: 9ed2a051c32b4fe47a5e4fb95c20b03f,
|
||||
type: 3}
|
||||
propertyPath: m_AnchoredPosition.x
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 4011473737907365368, guid: 9ed2a051c32b4fe47a5e4fb95c20b03f,
|
||||
type: 3}
|
||||
propertyPath: m_AnchoredPosition.y
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 4011473737907365368, guid: 9ed2a051c32b4fe47a5e4fb95c20b03f,
|
||||
type: 3}
|
||||
propertyPath: m_SizeDelta.x
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 4011473737907365368, guid: 9ed2a051c32b4fe47a5e4fb95c20b03f,
|
||||
type: 3}
|
||||
propertyPath: m_SizeDelta.y
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 3143326541157679684, guid: 9ed2a051c32b4fe47a5e4fb95c20b03f,
|
||||
type: 3}
|
||||
propertyPath: m_AnchorMin.y
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 3143326541157679684, guid: 9ed2a051c32b4fe47a5e4fb95c20b03f,
|
||||
type: 3}
|
||||
propertyPath: m_AnchorMax.y
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 3143326541157679684, guid: 9ed2a051c32b4fe47a5e4fb95c20b03f,
|
||||
type: 3}
|
||||
propertyPath: m_AnchoredPosition.x
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 3143326541157679684, guid: 9ed2a051c32b4fe47a5e4fb95c20b03f,
|
||||
type: 3}
|
||||
propertyPath: m_AnchoredPosition.y
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 3143326541157679684, guid: 9ed2a051c32b4fe47a5e4fb95c20b03f,
|
||||
type: 3}
|
||||
propertyPath: m_SizeDelta.x
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 3143326541157679684, guid: 9ed2a051c32b4fe47a5e4fb95c20b03f,
|
||||
type: 3}
|
||||
propertyPath: m_SizeDelta.y
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 143246068027918357, guid: 9ed2a051c32b4fe47a5e4fb95c20b03f,
|
||||
type: 3}
|
||||
propertyPath: m_AnchorMin.y
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 143246068027918357, guid: 9ed2a051c32b4fe47a5e4fb95c20b03f,
|
||||
type: 3}
|
||||
propertyPath: m_AnchorMax.y
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 143246068027918357, guid: 9ed2a051c32b4fe47a5e4fb95c20b03f,
|
||||
type: 3}
|
||||
propertyPath: m_AnchoredPosition.x
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 143246068027918357, guid: 9ed2a051c32b4fe47a5e4fb95c20b03f,
|
||||
type: 3}
|
||||
propertyPath: m_AnchoredPosition.y
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 143246068027918357, guid: 9ed2a051c32b4fe47a5e4fb95c20b03f,
|
||||
type: 3}
|
||||
propertyPath: m_SizeDelta.x
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 143246068027918357, guid: 9ed2a051c32b4fe47a5e4fb95c20b03f,
|
||||
type: 3}
|
||||
propertyPath: m_SizeDelta.y
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 114600693638766706, guid: 9ed2a051c32b4fe47a5e4fb95c20b03f,
|
||||
type: 3}
|
||||
propertyPath: _theme
|
||||
value:
|
||||
objectReference: {fileID: 11400000, guid: 769f3deee63c82a4c9896ac917227625,
|
||||
type: 2}
|
||||
m_RemovedComponents: []
|
||||
m_SourcePrefab: {fileID: 100100000, guid: 9ed2a051c32b4fe47a5e4fb95c20b03f, type: 3}
|
|
@ -0,0 +1,7 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 2da3dcc22749e7f4280737786d898334
|
||||
PrefabImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,9 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 9ed2a051c32b4fe47a5e4fb95c20b03f
|
||||
timeCreated: 1541120106
|
||||
licenseType: Store
|
||||
NativeFormatImporter:
|
||||
mainObjectFileID: 100100000
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,8 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 7cd0938e3c7f0d94f978be0829c6cb85
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,8 @@
|
|||
fileFormatVersion: 2
|
||||
guid: a3eaecc6a5f4f974092a4aae01bb5b48
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,78 @@
|
|||
using System;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace QFSW.QC.Actions
|
||||
{
|
||||
/// <summary>
|
||||
/// Converts an async Task into an action.
|
||||
/// </summary>
|
||||
public class Async : ICommandAction
|
||||
{
|
||||
private readonly Task _task;
|
||||
|
||||
public bool IsFinished => _task.IsCompleted ||
|
||||
_task.IsCanceled ||
|
||||
_task.IsFaulted;
|
||||
public bool StartsIdle => false;
|
||||
|
||||
/// <param name="task">The async Task to convert.</param>
|
||||
public Async(Task task)
|
||||
{
|
||||
_task = task;
|
||||
}
|
||||
|
||||
public void Start(ActionContext context) { }
|
||||
|
||||
public void Finalize(ActionContext context)
|
||||
{
|
||||
if (_task.IsFaulted)
|
||||
{
|
||||
throw _task.Exception.InnerException;
|
||||
}
|
||||
if (_task.IsCanceled)
|
||||
{
|
||||
throw new TaskCanceledException();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts an async Task into an action.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The return type of the Task to convert.</typeparam>
|
||||
public class Async<T> : ICommandAction
|
||||
{
|
||||
private readonly Task<T> _task;
|
||||
private readonly Action<T> _onResult;
|
||||
|
||||
public bool IsFinished => _task.IsCompleted ||
|
||||
_task.IsCanceled ||
|
||||
_task.IsFaulted;
|
||||
public bool StartsIdle => false;
|
||||
|
||||
/// <param name="task">The async Task to convert.</param>
|
||||
/// <param name="onResult">The action to invoke when the Task completes.</param>
|
||||
public Async(Task<T> task, Action<T> onResult)
|
||||
{
|
||||
_task = task;
|
||||
_onResult = onResult;
|
||||
}
|
||||
|
||||
public void Start(ActionContext context) { }
|
||||
|
||||
public void Finalize(ActionContext context)
|
||||
{
|
||||
if (_task.IsFaulted)
|
||||
{
|
||||
throw _task.Exception.InnerException;
|
||||
}
|
||||
if (_task.IsCanceled)
|
||||
{
|
||||
throw new TaskCanceledException();
|
||||
}
|
||||
|
||||
_onResult(_task.Result);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: aed3880bc1532c7418a020825bd88a2b
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,97 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using QFSW.QC.Utilities;
|
||||
using UnityEngine;
|
||||
|
||||
namespace QFSW.QC.Actions
|
||||
{
|
||||
/// <summary>
|
||||
/// Give the user a selection of choices which can be made by using the arrow keys and enter key.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The type of the choices.</typeparam>
|
||||
public class Choice<T> : Composite
|
||||
{
|
||||
/// <summary>
|
||||
/// Configuration for the Choice action.
|
||||
/// </summary>
|
||||
public struct Config
|
||||
{
|
||||
public string ItemFormat;
|
||||
public string Delimiter;
|
||||
public Color SelectedColor;
|
||||
|
||||
public static readonly Config Default = new Config
|
||||
{
|
||||
ItemFormat = "{0} [{1}]",
|
||||
Delimiter = " ",
|
||||
SelectedColor = Color.green
|
||||
};
|
||||
}
|
||||
|
||||
/// <param name="choices">The choices to select between.</param>
|
||||
/// <param name="onSelect">Action to invoke when a selection is made.</param>
|
||||
public Choice(IEnumerable<T> choices, Action<T> onSelect)
|
||||
: this(choices, onSelect, Config.Default)
|
||||
{ }
|
||||
|
||||
/// <param name="choices">The choices to select between.</param>
|
||||
/// <param name="onSelect">Action to invoke when a selection is made.</param>
|
||||
/// <param name="config">The configuration to be used.</param>
|
||||
public Choice(IEnumerable<T> choices, Action<T> onSelect, Config config)
|
||||
: base(Generate(choices, onSelect, config))
|
||||
{ }
|
||||
|
||||
private static IEnumerator<ICommandAction> Generate(IEnumerable<T> choices, Action<T> onSelect, Config config)
|
||||
{
|
||||
QuantumConsole console = null;
|
||||
StringBuilder builder = new StringBuilder();
|
||||
|
||||
IReadOnlyList<T> choiceList = choices as IReadOnlyList<T> ?? choices.ToList();
|
||||
KeyCode key = KeyCode.None;
|
||||
int choice = 0;
|
||||
|
||||
yield return new GetContext(ctx => console = ctx.Console);
|
||||
|
||||
ICommandAction DrawRow()
|
||||
{
|
||||
builder.Clear();
|
||||
for (int i = 0; i < choiceList.Count; i++)
|
||||
{
|
||||
string item = console.Serialize(choiceList[i]);
|
||||
builder.Append(i == choice
|
||||
? string.Format(config.ItemFormat, item, 'x').ColorText(config.SelectedColor)
|
||||
: string.Format(config.ItemFormat, item, ' '));
|
||||
|
||||
if (i != choiceList.Count - 1)
|
||||
{
|
||||
builder.Append(config.Delimiter);
|
||||
}
|
||||
}
|
||||
|
||||
return new Value(builder.ToString());
|
||||
}
|
||||
|
||||
yield return DrawRow();
|
||||
while (key != KeyCode.Return)
|
||||
{
|
||||
yield return new GetKey(k => key = k);
|
||||
|
||||
switch (key)
|
||||
{
|
||||
case KeyCode.LeftArrow: choice--; break;
|
||||
case KeyCode.RightArrow: choice++; break;
|
||||
case KeyCode.DownArrow: choice++; break;
|
||||
case KeyCode.UpArrow: choice--; break;
|
||||
}
|
||||
|
||||
choice = (choice + choiceList.Count) % choiceList.Count;
|
||||
yield return new RemoveLog();
|
||||
yield return DrawRow();
|
||||
}
|
||||
|
||||
onSelect(choiceList[choice]);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 629e5579947e6da4688f17d834a20b56
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,35 @@
|
|||
using System.Collections.Generic;
|
||||
|
||||
namespace QFSW.QC.Actions
|
||||
{
|
||||
/// <summary>
|
||||
/// Combines a sequence of actions into a single action.
|
||||
/// </summary>
|
||||
public class Composite : ICommandAction
|
||||
{
|
||||
private ActionContext _context;
|
||||
private readonly IEnumerator<ICommandAction> _actions;
|
||||
|
||||
public bool IsFinished => _actions.Execute(_context) == ActionState.Complete;
|
||||
public bool StartsIdle => false;
|
||||
|
||||
/// <param name="actions">The sequence of actions to create the composite from.</param>
|
||||
public Composite(IEnumerator<ICommandAction> actions)
|
||||
{
|
||||
_actions = actions;
|
||||
}
|
||||
|
||||
/// <param name="actions">The sequence of actions to create the composite from.</param>
|
||||
public Composite(IEnumerable<ICommandAction> actions) : this(actions.GetEnumerator())
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public void Start(ActionContext context)
|
||||
{
|
||||
_context = context;
|
||||
}
|
||||
|
||||
public void Finalize(ActionContext context) { }
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 3ecb8c263614be7489f996de15278bf5
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,8 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 3dba2d4b65cfdad428d18b1bd91c54e7
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,10 @@
|
|||
namespace QFSW.QC
|
||||
{
|
||||
/// <summary>
|
||||
/// The context that an action is being invoked on.
|
||||
/// </summary>
|
||||
public struct ActionContext
|
||||
{
|
||||
public QuantumConsole Console;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 16c86e1b478f19a4fa02d70bd8aafcde
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,53 @@
|
|||
using System.Collections.Generic;
|
||||
|
||||
namespace QFSW.QC
|
||||
{
|
||||
public static class ActionExecuter
|
||||
{
|
||||
/// <summary>
|
||||
/// Executes an action command until it becomes idle.
|
||||
/// </summary>
|
||||
/// <param name="action">The action command to execute.</param>
|
||||
/// <param name="context">The context that the command is being executed on.</param>
|
||||
/// <returns>The current state of the action command.</returns>
|
||||
public static ActionState Execute(this IEnumerator<ICommandAction> action, ActionContext context)
|
||||
{
|
||||
ActionState state = ActionState.Running;
|
||||
bool idle = false;
|
||||
|
||||
void MoveNext()
|
||||
{
|
||||
if (action.MoveNext())
|
||||
{
|
||||
action.Current?.Start(context);
|
||||
idle = action.Current?.StartsIdle ?? false;
|
||||
}
|
||||
else
|
||||
{
|
||||
idle = true;
|
||||
state = ActionState.Complete;
|
||||
action.Dispose();
|
||||
}
|
||||
}
|
||||
|
||||
while (!idle)
|
||||
{
|
||||
if (action.Current == null)
|
||||
{
|
||||
MoveNext();
|
||||
}
|
||||
else if (action.Current.IsFinished)
|
||||
{
|
||||
action.Current.Finalize(context);
|
||||
MoveNext();
|
||||
}
|
||||
else
|
||||
{
|
||||
idle = true;
|
||||
}
|
||||
}
|
||||
|
||||
return state;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: cc98ecd40616cc142a69f2c94957435f
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,12 @@
|
|||
namespace QFSW.QC
|
||||
{
|
||||
/// <summary>
|
||||
/// The execution state of an action.
|
||||
/// </summary>
|
||||
public enum ActionState
|
||||
{
|
||||
Unknown = 0,
|
||||
Running = 1,
|
||||
Complete = 2
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: c68b189efbe61cc41af4263794f5b1b4
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,31 @@
|
|||
namespace QFSW.QC
|
||||
{
|
||||
/// <summary>
|
||||
/// Creates an action that can be yielded in commands.
|
||||
/// </summary>
|
||||
public interface ICommandAction
|
||||
{
|
||||
/// <summary>
|
||||
/// Starts the action.
|
||||
/// </summary>
|
||||
/// <param name="context">The context that the action is being executed on.</param>
|
||||
void Start(ActionContext context);
|
||||
|
||||
/// <summary>
|
||||
/// Finalizes the action. Should not be called unless <c>IsFinished</c> is true.
|
||||
/// </summary>
|
||||
/// <param name="context">The context that the action is being executed on.</param>
|
||||
void Finalize(ActionContext context);
|
||||
|
||||
/// <summary>
|
||||
/// If the action has finished. Should not be called before <c>Start</c>.
|
||||
/// </summary>
|
||||
bool IsFinished { get; }
|
||||
|
||||
/// <summary>
|
||||
/// If the action should start off idle, causing the execution to suspend until executed again.
|
||||
/// It is recommended to make this <c>false</c> if the action should be instant.
|
||||
/// </summary>
|
||||
bool StartsIdle { get; }
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 8ad6ee627978b454d9938922d0e5415c
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,36 @@
|
|||
using System;
|
||||
|
||||
namespace QFSW.QC.Actions
|
||||
{
|
||||
/// <summary>
|
||||
/// Custom action implemented via delegates.
|
||||
/// For more complex actions it is usually recommended to create a new action implementing <c>ICommandAction</c>.
|
||||
/// </summary>
|
||||
public class Custom : ICommandAction
|
||||
{
|
||||
private readonly Func<bool> _isFinished;
|
||||
private readonly Func<bool> _startsIdle;
|
||||
private readonly Action<ActionContext> _start;
|
||||
private readonly Action<ActionContext> _finalize;
|
||||
|
||||
public Custom(
|
||||
Func<bool> isFinished,
|
||||
Func<bool> startsIdle,
|
||||
Action<ActionContext> start,
|
||||
Action<ActionContext> finalize
|
||||
)
|
||||
{
|
||||
_isFinished = isFinished;
|
||||
_startsIdle = startsIdle;
|
||||
_start = start;
|
||||
_finalize = finalize;
|
||||
}
|
||||
|
||||
public bool IsFinished => _isFinished();
|
||||
public bool StartsIdle => _startsIdle();
|
||||
|
||||
public void Start(ActionContext context) { _start(context); }
|
||||
public void Finalize(ActionContext context) { _finalize(context); }
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: b9bd021bf2e291447a56d4cede936d56
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,28 @@
|
|||
using System;
|
||||
|
||||
namespace QFSW.QC.Actions
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the <c>ActionContext</c> that the command is currently being invoked on.
|
||||
/// </summary>
|
||||
public class GetContext : ICommandAction
|
||||
{
|
||||
private readonly Action<ActionContext> _onContext;
|
||||
|
||||
public bool IsFinished => true;
|
||||
public bool StartsIdle => false;
|
||||
|
||||
/// <param name="onContext">Action to invoke when the context is retrieved.</param>
|
||||
public GetContext(Action<ActionContext> onContext)
|
||||
{
|
||||
_onContext = onContext;
|
||||
}
|
||||
|
||||
public void Start(ActionContext context) { }
|
||||
|
||||
public void Finalize(ActionContext context)
|
||||
{
|
||||
_onContext(context);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: a2b0f8e4c27c89e4caac865a57f52f99
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,48 @@
|
|||
using System;
|
||||
using System.Linq;
|
||||
using UnityEngine;
|
||||
|
||||
namespace QFSW.QC.Actions
|
||||
{
|
||||
/// <summary>
|
||||
/// Waits for any key to be pressed and returns the key via the given delegate.
|
||||
/// </summary>
|
||||
public class GetKey : ICommandAction
|
||||
{
|
||||
private KeyCode _key;
|
||||
private readonly Action<KeyCode> _onKey;
|
||||
private static readonly KeyCode[] KeyCodes = Enum.GetValues(typeof(KeyCode))
|
||||
.Cast<KeyCode>()
|
||||
.Where(k => (int)k < (int)KeyCode.Mouse0)
|
||||
.ToArray();
|
||||
|
||||
public bool IsFinished
|
||||
{
|
||||
get
|
||||
{
|
||||
_key = GetCurrentKeyDown();
|
||||
return _key != KeyCode.None;
|
||||
}
|
||||
}
|
||||
|
||||
public bool StartsIdle => true;
|
||||
|
||||
/// <param name="onKey">The action to perform when a key is pressed.</param>
|
||||
public GetKey(Action<KeyCode> onKey)
|
||||
{
|
||||
_onKey = onKey;
|
||||
}
|
||||
|
||||
private KeyCode GetCurrentKeyDown()
|
||||
{
|
||||
return KeyCodes.FirstOrDefault(InputHelper.GetKeyDown);
|
||||
}
|
||||
|
||||
public void Start(ActionContext context) { }
|
||||
|
||||
public void Finalize(ActionContext context)
|
||||
{
|
||||
_onKey(_key);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 3a0a962a9335e7e408af971ed79d4e8e
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,18 @@
|
|||
namespace QFSW.QC.Actions
|
||||
{
|
||||
/// <summary>
|
||||
/// Removes the most recent log from the console.
|
||||
/// </summary>
|
||||
public class RemoveLog : ICommandAction
|
||||
{
|
||||
public bool IsFinished => true;
|
||||
public bool StartsIdle => false;
|
||||
|
||||
public void Start(ActionContext context) { }
|
||||
|
||||
public void Finalize(ActionContext context)
|
||||
{
|
||||
context.Console.RemoveLogTrace();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: a4e97d9251aaa994aa83824d9bccfd59
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,67 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text.RegularExpressions;
|
||||
|
||||
namespace QFSW.QC.Actions
|
||||
{
|
||||
/// <summary>
|
||||
/// Gradually types a message to the console.
|
||||
/// </summary>
|
||||
public class Typewriter : Composite
|
||||
{
|
||||
/// <summary>
|
||||
/// Configuration for the Typewriter action.
|
||||
/// </summary>
|
||||
public struct Config
|
||||
{
|
||||
public enum ChunkType
|
||||
{
|
||||
Character,
|
||||
Word,
|
||||
Line
|
||||
}
|
||||
|
||||
public float PrintInterval;
|
||||
public ChunkType Chunks;
|
||||
|
||||
public static readonly Config Default = new Config
|
||||
{
|
||||
PrintInterval = 0f,
|
||||
Chunks = ChunkType.Character
|
||||
};
|
||||
}
|
||||
|
||||
private static readonly Regex WhiteRegex = new Regex(@"(?<=[\s+])", RegexOptions.Compiled);
|
||||
private static readonly Regex LineRegex = new Regex(@"(?<=[\n+])", RegexOptions.Compiled);
|
||||
|
||||
/// <param name="message">The message to display to the console.</param>
|
||||
public Typewriter(string message)
|
||||
: this(message, Config.Default)
|
||||
{ }
|
||||
|
||||
/// <param name="message">The message to display to the console.</param>
|
||||
/// <param name="config">The configuration to be used.</param>
|
||||
public Typewriter(string message, Config config)
|
||||
: base(Generate(message, config))
|
||||
{ }
|
||||
|
||||
private static IEnumerator<ICommandAction> Generate(string message, Config config)
|
||||
{
|
||||
string[] chunks;
|
||||
switch (config.Chunks)
|
||||
{
|
||||
case Config.ChunkType.Character: chunks = message.Select(c => c.ToString()).ToArray(); break;
|
||||
case Config.ChunkType.Word: chunks = WhiteRegex.Split(message); break;
|
||||
case Config.ChunkType.Line: chunks = LineRegex.Split(message); break;
|
||||
default: throw new ArgumentException($"Chunk type {config.Chunks} is not supported.");
|
||||
}
|
||||
|
||||
for (int i = 0; i < chunks.Length; i++)
|
||||
{
|
||||
yield return new WaitRealtime(config.PrintInterval);
|
||||
yield return new Value(chunks[i], i == 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: ea886313beb68ed45b9b597a71c3514a
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,31 @@
|
|||
namespace QFSW.QC.Actions
|
||||
{
|
||||
/// <summary>
|
||||
/// Serializes and logs a value to the console.
|
||||
/// </summary>
|
||||
public class Value : ICommandAction
|
||||
{
|
||||
private readonly object _value;
|
||||
private readonly bool _newline;
|
||||
|
||||
public bool IsFinished => true;
|
||||
public bool StartsIdle => false;
|
||||
|
||||
/// <param name="value">The value to log to the console.</param>
|
||||
/// <param name="newline">If the value should be logged on a new line.</param>
|
||||
public Value(object value, bool newline = true)
|
||||
{
|
||||
_value = value;
|
||||
_newline = newline;
|
||||
}
|
||||
|
||||
public void Start(ActionContext context) { }
|
||||
|
||||
public void Finalize(ActionContext context)
|
||||
{
|
||||
QuantumConsole console = context.Console;
|
||||
string serialized = _value as string ?? console.Serialize(_value);
|
||||
console.LogToConsole(serialized, _newline);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: aa35d5d3d1cdc54429fbcd0a8754323f
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,30 @@
|
|||
using UnityEngine;
|
||||
|
||||
namespace QFSW.QC.Actions
|
||||
{
|
||||
/// <summary>
|
||||
/// Waits for the given amount of seconds using scaled time.
|
||||
/// </summary>
|
||||
public class Wait : ICommandAction
|
||||
{
|
||||
private float _startTime;
|
||||
private readonly float _duration;
|
||||
|
||||
public bool IsFinished => Time.time >= _startTime + _duration;
|
||||
public bool StartsIdle => true;
|
||||
|
||||
/// <param name="seconds">The duration to wait in seconds.</param>
|
||||
public Wait(float seconds)
|
||||
{
|
||||
_duration = seconds;
|
||||
}
|
||||
|
||||
public void Start(ActionContext ctx)
|
||||
{
|
||||
_startTime = Time.time;
|
||||
}
|
||||
|
||||
public void Finalize(ActionContext ctx) { }
|
||||
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: da3e71593087b0145b4c7416865c73ff
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,13 @@
|
|||
namespace QFSW.QC.Actions
|
||||
{
|
||||
/// <summary>
|
||||
/// Waits until the next frame.
|
||||
/// </summary>
|
||||
public class WaitFrame : WaitRealtime
|
||||
{
|
||||
public WaitFrame() : base(0)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: ec7bf5a05072b33469812750790bff62
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,16 @@
|
|||
using UnityEngine;
|
||||
|
||||
namespace QFSW.QC.Actions
|
||||
{
|
||||
/// <summary>
|
||||
/// Waits until the given key is pressed.
|
||||
/// </summary>
|
||||
public class WaitKey : WaitUntil
|
||||
{
|
||||
/// <param name="key">The key to wait for.</param>
|
||||
public WaitKey(KeyCode key) : base(() => InputHelper.GetKeyDown(key))
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 67f025b392a312e45bb0ed80959d5cd1
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,30 @@
|
|||
using UnityEngine;
|
||||
|
||||
namespace QFSW.QC.Actions
|
||||
{
|
||||
/// <summary>
|
||||
/// Waits for the given amount of seconds using real time.
|
||||
/// </summary>
|
||||
public class WaitRealtime : ICommandAction
|
||||
{
|
||||
private float _startTime;
|
||||
private readonly float _duration;
|
||||
|
||||
public bool IsFinished => Time.realtimeSinceStartup >= _startTime + _duration;
|
||||
public bool StartsIdle => true;
|
||||
|
||||
/// <param name="seconds">The duration to wait for in seconds.</param>
|
||||
public WaitRealtime(float seconds)
|
||||
{
|
||||
_duration = seconds;
|
||||
}
|
||||
|
||||
public void Start(ActionContext ctx)
|
||||
{
|
||||
_startTime = Time.realtimeSinceStartup;
|
||||
}
|
||||
|
||||
public void Finalize(ActionContext ctx) { }
|
||||
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 32cadea9087bc5d4682ac8455fde1fd4
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,16 @@
|
|||
using System;
|
||||
|
||||
namespace QFSW.QC.Actions
|
||||
{
|
||||
/// <summary>
|
||||
/// Waits until the given condition is met.
|
||||
/// </summary>
|
||||
public class WaitUntil : WaitWhile
|
||||
{
|
||||
/// <param name="condition">The condition to wait on.</param>
|
||||
public WaitUntil(Func<bool> condition) : base(() => !condition())
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 10b1ff66cd0d51d4a9363f7ad3477830
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,25 @@
|
|||
using System;
|
||||
|
||||
namespace QFSW.QC.Actions
|
||||
{
|
||||
/// <summary>
|
||||
/// Waits while the given condition is met.
|
||||
/// </summary>
|
||||
public class WaitWhile : ICommandAction
|
||||
{
|
||||
private readonly Func<bool> _condition;
|
||||
|
||||
public bool IsFinished => _condition();
|
||||
public bool StartsIdle => true;
|
||||
|
||||
/// <param name="condition">The condition to wait on.</param>
|
||||
public WaitWhile(Func<bool> condition)
|
||||
{
|
||||
_condition = condition;
|
||||
}
|
||||
|
||||
|
||||
public void Start(ActionContext context) { }
|
||||
public void Finalize(ActionContext context) { }
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 8050f33217e30684a9a0ea5dfefdfd45
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,8 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 8f98c28cf2a7c934db3f256bd3921741
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,49 @@
|
|||
using System;
|
||||
using System.Linq;
|
||||
using System.Runtime.CompilerServices;
|
||||
using UnityEngine;
|
||||
|
||||
namespace QFSW.QC
|
||||
{
|
||||
/// <summary>
|
||||
/// Marks the associated method as a command, allowing it to be loaded by the QuantumConsoleProcessor. This means it will be usable as a command from a Quantum Console.
|
||||
/// </summary>
|
||||
[AttributeUsage(AttributeTargets.Method | AttributeTargets.Property | AttributeTargets.Field, AllowMultiple = true, Inherited = false)]
|
||||
public sealed class CommandAttribute : Attribute
|
||||
{
|
||||
public readonly string Alias;
|
||||
public readonly string Description;
|
||||
public readonly Platform SupportedPlatforms;
|
||||
public readonly MonoTargetType MonoTarget;
|
||||
public readonly bool Valid = true;
|
||||
|
||||
private static readonly char[] _bannedAliasChars = new char[] { ' ', '(', ')', '{', '}', '[', ']', '<', '>' };
|
||||
|
||||
public CommandAttribute([CallerMemberName] string aliasOverride = "", Platform supportedPlatforms = Platform.AllPlatforms, MonoTargetType targetType = MonoTargetType.Single)
|
||||
{
|
||||
Alias = aliasOverride;
|
||||
MonoTarget = targetType;
|
||||
SupportedPlatforms = supportedPlatforms;
|
||||
|
||||
for (int i = 0; i < _bannedAliasChars.Length; i++)
|
||||
{
|
||||
if (Alias.Contains(_bannedAliasChars[i]))
|
||||
{
|
||||
string errorMessage = $"Development Processor Error: Command with alias '{Alias}' contains the char '{_bannedAliasChars[i]}' which is banned. Unexpected behaviour may occur.";
|
||||
Debug.LogError(errorMessage);
|
||||
Valid = false;
|
||||
throw new ArgumentException(errorMessage, nameof(aliasOverride));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public CommandAttribute(string aliasOverride, MonoTargetType targetType, Platform supportedPlatforms = Platform.AllPlatforms) : this(aliasOverride, supportedPlatforms, targetType) { }
|
||||
|
||||
public CommandAttribute(string aliasOverride, string description, Platform supportedPlatforms = Platform.AllPlatforms, MonoTargetType targetType = MonoTargetType.Single) : this(aliasOverride, supportedPlatforms, targetType)
|
||||
{
|
||||
Description = description;
|
||||
}
|
||||
|
||||
public CommandAttribute(string aliasOverride, string description, MonoTargetType targetType, Platform supportedPlatforms = Platform.AllPlatforms) : this(aliasOverride, description, supportedPlatforms, targetType) { }
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 8115824be443344f29ef0da5a1c05a3b
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,18 @@
|
|||
using System;
|
||||
|
||||
namespace QFSW.QC
|
||||
{
|
||||
/// <summary>Provides a command with a description. If the [Command] attribute already provides a description, that will supersede this one. Useful for when you have several [Command]s on a single method.</summary>
|
||||
[AttributeUsage(AttributeTargets.Method | AttributeTargets.Property | AttributeTargets.Field, AllowMultiple = false, Inherited = false)]
|
||||
public sealed class CommandDescriptionAttribute : Attribute
|
||||
{
|
||||
public readonly string Description;
|
||||
public readonly bool Valid;
|
||||
|
||||
public CommandDescriptionAttribute(string description)
|
||||
{
|
||||
Description = description;
|
||||
Valid = !string.IsNullOrWhiteSpace(description);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: e52ff948b143dc54684640418a70f825
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,18 @@
|
|||
using System;
|
||||
|
||||
namespace QFSW.QC
|
||||
{
|
||||
/// <summary>Provides a command paremeter with a description.</summary>
|
||||
[AttributeUsage(AttributeTargets.Parameter, AllowMultiple = false, Inherited = false)]
|
||||
public sealed class CommandParameterDescriptionAttribute : Attribute
|
||||
{
|
||||
public readonly string Description;
|
||||
public readonly bool Valid;
|
||||
|
||||
public CommandParameterDescriptionAttribute(string description)
|
||||
{
|
||||
Description = description;
|
||||
Valid = !string.IsNullOrWhiteSpace(description);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 6c171fb328ed92146bd061b07d446a1a
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,16 @@
|
|||
using System;
|
||||
|
||||
namespace QFSW.QC
|
||||
{
|
||||
/// <summary>Determines which platforms the command is available on. Supersedes platform availability determined in the [Command].</summary>
|
||||
[AttributeUsage(AttributeTargets.Method | AttributeTargets.Property | AttributeTargets.Field, AllowMultiple = false, Inherited = false)]
|
||||
public sealed class CommandPlatformAttribute : Attribute
|
||||
{
|
||||
public readonly Platform SupportedPlatforms;
|
||||
|
||||
public CommandPlatformAttribute(Platform supportedPlatforms)
|
||||
{
|
||||
SupportedPlatforms = supportedPlatforms;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 6d0cd481e1faecd4a8159c22114d7d9a
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,35 @@
|
|||
using System;
|
||||
using System.Linq;
|
||||
using System.Runtime.CompilerServices;
|
||||
using UnityEngine;
|
||||
|
||||
namespace QFSW.QC
|
||||
{
|
||||
/// <summary>
|
||||
/// Creates a prefix that will be prepended to all commands made within this class. Works recursively with sub-classes.
|
||||
/// </summary>
|
||||
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Assembly, AllowMultiple = true, Inherited = false)]
|
||||
public sealed class CommandPrefixAttribute : Attribute
|
||||
{
|
||||
public readonly string Prefix;
|
||||
public readonly bool Valid = true;
|
||||
|
||||
private static readonly char[] _bannedAliasChars = { ' ', '(', ')', '{', '}', '[', ']', '<', '>' };
|
||||
|
||||
public CommandPrefixAttribute([CallerMemberName] string prefixName = "")
|
||||
{
|
||||
Prefix = prefixName;
|
||||
foreach (var c in _bannedAliasChars)
|
||||
{
|
||||
if (Prefix.Contains(c))
|
||||
{
|
||||
string errorMessage = $"Development Processor Error: Command prefix '{Prefix}' contains the char '{c}' which is banned. Unexpected behaviour may occurr.";
|
||||
Debug.LogError(errorMessage);
|
||||
|
||||
Valid = false;
|
||||
throw new ArgumentException(errorMessage, nameof(prefixName));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: e8b3bb27784b8544785af220e6f8b39a
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,11 @@
|
|||
using System;
|
||||
|
||||
namespace QFSW.QC
|
||||
{
|
||||
/// <summary>
|
||||
/// Instructs QC to ignore this entity when scanning the code base for commands.
|
||||
/// This can be used to optimise QCs loading times in large codebases when there are large entities that do not have any commands present.
|
||||
/// </summary>
|
||||
[AttributeUsage(AttributeTargets.Assembly | AttributeTargets.Class, AllowMultiple = false, Inherited = false)]
|
||||
public sealed class QcIgnoreAttribute : Attribute { }
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: f9509f39d8a98d44784d6efc252ed5d0
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,9 @@
|
|||
namespace QFSW.QC
|
||||
{
|
||||
public enum AutoScrollOptions
|
||||
{
|
||||
Never = 0,
|
||||
OnInvoke = 1,
|
||||
Always = 2
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 1fd10c1eb5013b648963ed0e1cdbd869
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,267 @@
|
|||
using QFSW.QC.Utilities;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
|
||||
namespace QFSW.QC
|
||||
{
|
||||
/// <summary>
|
||||
/// Contains the full data about a command and provides an execution point for invoking the command.
|
||||
/// </summary>
|
||||
public class CommandData
|
||||
{
|
||||
public readonly string CommandName;
|
||||
public readonly string CommandDescription;
|
||||
public readonly string CommandSignature;
|
||||
public readonly string ParameterSignature;
|
||||
public readonly string GenericSignature;
|
||||
|
||||
public readonly ParameterInfo[] MethodParamData;
|
||||
public readonly Type[] ParamTypes;
|
||||
public readonly Type[] GenericParamTypes;
|
||||
public readonly MethodInfo MethodData;
|
||||
public readonly MonoTargetType MonoTarget;
|
||||
|
||||
private readonly object[] _defaultParameters;
|
||||
|
||||
public bool IsGeneric => GenericParamTypes.Length > 0;
|
||||
public bool IsStatic => MethodData.IsStatic;
|
||||
public bool HasDescription => !string.IsNullOrWhiteSpace(CommandDescription);
|
||||
public int ParamCount => ParamTypes.Length - _defaultParameters.Length;
|
||||
|
||||
public Type[] MakeGenericArguments(params Type[] genericTypeArguments)
|
||||
{
|
||||
if (genericTypeArguments.Length != GenericParamTypes.Length)
|
||||
{
|
||||
throw new ArgumentException("Incorrect number of generic substitution types were supplied.");
|
||||
}
|
||||
|
||||
Dictionary<string, Type> substitutionTable = new Dictionary<string, Type>();
|
||||
for (int i = 0; i < genericTypeArguments.Length; i++)
|
||||
{
|
||||
substitutionTable.Add(GenericParamTypes[i].Name, genericTypeArguments[i]);
|
||||
}
|
||||
|
||||
Type[] types = new Type[ParamTypes.Length];
|
||||
for (int i = 0; i < types.Length; i++)
|
||||
{
|
||||
if (ParamTypes[i].ContainsGenericParameters)
|
||||
{
|
||||
Type substitution = ConstructGenericType(ParamTypes[i], substitutionTable);
|
||||
types[i] = substitution;
|
||||
}
|
||||
else
|
||||
{
|
||||
types[i] = ParamTypes[i];
|
||||
}
|
||||
}
|
||||
|
||||
return types;
|
||||
}
|
||||
|
||||
private Type ConstructGenericType(Type genericType, Dictionary<string, Type> substitutionTable)
|
||||
{
|
||||
if (!genericType.ContainsGenericParameters) { return genericType; }
|
||||
if (substitutionTable.ContainsKey(genericType.Name)) { return substitutionTable[genericType.Name]; }
|
||||
if (genericType.IsArray) { return ConstructGenericType(genericType.GetElementType(), substitutionTable).MakeArrayType(); }
|
||||
if (genericType.IsGenericType)
|
||||
{
|
||||
Type baseType = genericType.GetGenericTypeDefinition();
|
||||
Type[] typeArguments = genericType.GetGenericArguments();
|
||||
for (int i = 0; i < typeArguments.Length; i++)
|
||||
{
|
||||
typeArguments[i] = ConstructGenericType(typeArguments[i], substitutionTable);
|
||||
}
|
||||
|
||||
return baseType.MakeGenericType(typeArguments);
|
||||
}
|
||||
|
||||
throw new ArgumentException($"Could not construct the generic type {genericType}");
|
||||
}
|
||||
|
||||
public object Invoke(object[] paramData, Type[] genericTypeArguments)
|
||||
{
|
||||
object[] data = new object[paramData.Length + _defaultParameters.Length];
|
||||
Array.Copy(paramData, 0, data, 0, paramData.Length);
|
||||
Array.Copy(_defaultParameters, 0, data, paramData.Length, _defaultParameters.Length);
|
||||
|
||||
MethodInfo invokingMethod = GetInvokingMethod(genericTypeArguments);
|
||||
|
||||
if (IsStatic)
|
||||
{
|
||||
return invokingMethod.Invoke(null, data);
|
||||
}
|
||||
|
||||
IEnumerable<object> targets = InvocationTargetFactory.FindTargets(invokingMethod.DeclaringType, MonoTarget);
|
||||
return InvocationTargetFactory.InvokeOnTargets(invokingMethod, targets, data);
|
||||
}
|
||||
|
||||
private MethodInfo GetInvokingMethod(Type[] genericTypeArguments)
|
||||
{
|
||||
if (!IsGeneric)
|
||||
{
|
||||
return MethodData;
|
||||
}
|
||||
|
||||
T WrapConstruction<T>(Func<T> f)
|
||||
{
|
||||
try
|
||||
{
|
||||
return f();
|
||||
}
|
||||
catch (ArgumentException)
|
||||
{
|
||||
throw new ArgumentException($"Supplied generic parameters did not satisfy the generic constraints imposed by '{CommandName}'");
|
||||
}
|
||||
}
|
||||
|
||||
Type declaringType = MethodData.DeclaringType;
|
||||
MethodInfo method = MethodData;
|
||||
|
||||
if (declaringType.IsGenericTypeDefinition)
|
||||
{
|
||||
int typeCount = declaringType.GetGenericArguments().Length;
|
||||
|
||||
Type[] genericTypes = genericTypeArguments
|
||||
.Take(typeCount)
|
||||
.ToArray();
|
||||
|
||||
genericTypeArguments = genericTypeArguments
|
||||
.Skip(typeCount)
|
||||
.ToArray();
|
||||
|
||||
declaringType = WrapConstruction(() => declaringType.MakeGenericType(genericTypes));
|
||||
method = method.RebaseMethod(declaringType);
|
||||
}
|
||||
|
||||
return genericTypeArguments.Length == 0
|
||||
? method
|
||||
: WrapConstruction(() => method.MakeGenericMethod(genericTypeArguments));
|
||||
}
|
||||
|
||||
private string BuildPrefix(Type declaringType)
|
||||
{
|
||||
List<string> prefixes = new List<string>();
|
||||
Assembly assembly = declaringType.Assembly;
|
||||
|
||||
void AddPrefixes(IEnumerable<CommandPrefixAttribute> prefixAttributes, string defaultName)
|
||||
{
|
||||
foreach (CommandPrefixAttribute prefixAttribute in prefixAttributes.Reverse())
|
||||
{
|
||||
if (prefixAttribute.Valid)
|
||||
{
|
||||
string prefix = prefixAttribute.Prefix;
|
||||
if (string.IsNullOrWhiteSpace(prefix)) { prefix = defaultName; }
|
||||
|
||||
prefixes.Add(prefix);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
while (declaringType != null)
|
||||
{
|
||||
IEnumerable<CommandPrefixAttribute> typePrefixes = declaringType.GetCustomAttributes<CommandPrefixAttribute>();
|
||||
AddPrefixes(typePrefixes, declaringType.Name);
|
||||
|
||||
declaringType = declaringType.DeclaringType;
|
||||
}
|
||||
|
||||
IEnumerable<CommandPrefixAttribute> assemblyPrefixes = assembly.GetCustomAttributes<CommandPrefixAttribute>();
|
||||
AddPrefixes(assemblyPrefixes, assembly.GetName().Name);
|
||||
|
||||
return string.Join("", prefixes.Reversed());
|
||||
}
|
||||
|
||||
private string BuildGenericSignature(Type[] genericParamTypes)
|
||||
{
|
||||
if (genericParamTypes.Length == 0)
|
||||
{
|
||||
return string.Empty;
|
||||
}
|
||||
|
||||
IEnumerable<string> names = genericParamTypes.Select(x => x.Name);
|
||||
return $"<{string.Join(", ", names)}>";
|
||||
}
|
||||
|
||||
private string BuildParameterSignature(ParameterInfo[] methodParams, int defaultParameterCount)
|
||||
{
|
||||
string signature = string.Empty;
|
||||
for (int i = 0; i < methodParams.Length - defaultParameterCount; i++)
|
||||
{
|
||||
signature += $"{(i == 0 ? string.Empty : " ")}{methodParams[i].Name}";
|
||||
}
|
||||
|
||||
return signature;
|
||||
}
|
||||
|
||||
private Type[] BuildGenericParamTypes(MethodInfo method, Type declaringType)
|
||||
{
|
||||
List<Type> types = new List<Type>();
|
||||
|
||||
if (declaringType.IsGenericTypeDefinition)
|
||||
{
|
||||
types.AddRange(declaringType.GetGenericArguments());
|
||||
}
|
||||
|
||||
if (method.IsGenericMethodDefinition)
|
||||
{
|
||||
types.AddRange(method.GetGenericArguments());
|
||||
}
|
||||
|
||||
return types.ToArray();
|
||||
}
|
||||
|
||||
public CommandData(MethodInfo methodData, int defaultParameterCount = 0) : this(methodData, methodData.Name, defaultParameterCount) { }
|
||||
public CommandData(MethodInfo methodData, string commandName, int defaultParameterCount = 0)
|
||||
{
|
||||
CommandName = commandName;
|
||||
MethodData = methodData;
|
||||
|
||||
if (string.IsNullOrWhiteSpace(commandName))
|
||||
{
|
||||
CommandName = methodData.Name;
|
||||
}
|
||||
|
||||
Type declaringType = methodData.DeclaringType;
|
||||
|
||||
string prefix = BuildPrefix(declaringType);
|
||||
CommandName = $"{prefix}{CommandName}";
|
||||
|
||||
MethodParamData = methodData.GetParameters();
|
||||
ParamTypes = MethodParamData
|
||||
.Select(x => x.ParameterType)
|
||||
.ToArray();
|
||||
|
||||
_defaultParameters = new object[defaultParameterCount];
|
||||
for (int i = 0; i < defaultParameterCount; i++)
|
||||
{
|
||||
int j = MethodParamData.Length - defaultParameterCount + i;
|
||||
_defaultParameters[i] = MethodParamData[j].DefaultValue;
|
||||
}
|
||||
|
||||
GenericParamTypes = BuildGenericParamTypes(methodData, declaringType);
|
||||
|
||||
ParameterSignature = BuildParameterSignature(MethodParamData, defaultParameterCount);
|
||||
GenericSignature = BuildGenericSignature(GenericParamTypes);
|
||||
CommandSignature = ParamCount > 0
|
||||
? $"{CommandName}{GenericSignature} {ParameterSignature}"
|
||||
: $"{CommandName}{GenericSignature}";
|
||||
}
|
||||
|
||||
public CommandData(MethodInfo methodData, CommandAttribute commandAttribute, int defaultParameterCount = 0) : this(methodData, commandAttribute.Alias, defaultParameterCount)
|
||||
{
|
||||
CommandDescription = commandAttribute.Description;
|
||||
MonoTarget = commandAttribute.MonoTarget;
|
||||
}
|
||||
|
||||
public CommandData(MethodInfo methodData, CommandAttribute commandAttribute, CommandDescriptionAttribute descriptionAttribute, int defaultParameterCount = 0)
|
||||
: this(methodData, commandAttribute, defaultParameterCount)
|
||||
{
|
||||
if ((descriptionAttribute?.Valid ?? false) && string.IsNullOrWhiteSpace(commandAttribute.Description))
|
||||
{
|
||||
CommandDescription = descriptionAttribute.Description;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 5e34b97732540ee4d9b37cd16f6b78dc
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,8 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 48497173fbbd4884682d42192fdb2df6
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,149 @@
|
|||
using System.Collections.Generic;
|
||||
|
||||
namespace QFSW.QC.Comparators
|
||||
{
|
||||
public class AlphanumComparator : IComparer<string>
|
||||
{
|
||||
private const int MaxStackSize = 512;
|
||||
|
||||
public unsafe int Compare(string x, string y)
|
||||
{
|
||||
if (x == null) { return 0; }
|
||||
if (y == null) { return 0; }
|
||||
|
||||
int len1 = x.Length;
|
||||
int len2 = y.Length;
|
||||
|
||||
if (len1 + len2 + 2 <= MaxStackSize)
|
||||
{
|
||||
char* buffer1 = stackalloc char[len1 + 1];
|
||||
char* buffer2 = stackalloc char[len2 + 1];
|
||||
|
||||
return Compare(x, buffer1, len1, y, buffer2, len2);
|
||||
}
|
||||
else
|
||||
{
|
||||
char[] buffer1 = new char[len1 + 1];
|
||||
char[] buffer2 = new char[len2 + 1];
|
||||
|
||||
fixed (char* ptr1 = buffer1)
|
||||
fixed (char* ptr2 = buffer2)
|
||||
{
|
||||
return Compare(x, ptr1, len1, y, ptr2, len2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public unsafe int Compare(string x, char* buffer1, int len1, string y, char* buffer2, int len2)
|
||||
{
|
||||
int marker1 = 0;
|
||||
int marker2 = 0;
|
||||
|
||||
while (marker1 < len1 && marker2 < len2)
|
||||
{
|
||||
char ch1 = x[marker1];
|
||||
char ch2 = y[marker2];
|
||||
|
||||
int loc1 = 0;
|
||||
int loc2 = 0;
|
||||
|
||||
do
|
||||
{
|
||||
buffer1[loc1++] = ch1;
|
||||
marker1++;
|
||||
|
||||
if (marker1 < len1)
|
||||
{
|
||||
ch1 = x[marker1];
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
} while (char.IsDigit(ch1) == char.IsDigit(buffer1[0]));
|
||||
|
||||
do
|
||||
{
|
||||
buffer2[loc2++] = ch2;
|
||||
marker2++;
|
||||
|
||||
if (marker2 < len2)
|
||||
{
|
||||
ch2 = y[marker2];
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
} while (char.IsDigit(ch2) == char.IsDigit(buffer2[0]));
|
||||
|
||||
//null terminate buffers
|
||||
buffer1[loc1] = buffer2[loc2] = (char)0;
|
||||
|
||||
int result;
|
||||
if (char.IsDigit(buffer1[0]) && char.IsDigit(buffer2[0]))
|
||||
{
|
||||
int chunk1 = ParseInt(buffer1);
|
||||
int chunk2 = ParseInt(buffer2);
|
||||
result = chunk1 - chunk2;
|
||||
}
|
||||
else
|
||||
{
|
||||
result = CompareStrings(buffer1, buffer2);
|
||||
}
|
||||
|
||||
if (result != 0)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
return len1 - len2;
|
||||
}
|
||||
|
||||
private unsafe int ParseInt(char* buffer)
|
||||
{
|
||||
int acc = 0;
|
||||
|
||||
while (*buffer != 0)
|
||||
{
|
||||
acc *= 10;
|
||||
acc += *buffer++ - '0';
|
||||
}
|
||||
|
||||
return acc;
|
||||
}
|
||||
|
||||
private unsafe int CompareStrings(char* buffer1, char* buffer2)
|
||||
{
|
||||
int index = 0;
|
||||
while (buffer1[index] != 0 && buffer2[index] != 0)
|
||||
{
|
||||
char c1 = buffer1[index];
|
||||
char c2 = buffer2[index++];
|
||||
|
||||
if (c1 > c2)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
else if (c1 < c2)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
if (buffer1[index] != 0)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
else if (buffer2[index] != 0)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 6f5a6b857ac27fa44b0213d2a5f85538
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,40 @@
|
|||
using System.Collections.Concurrent;
|
||||
|
||||
namespace QFSW.QC
|
||||
{
|
||||
public class ConcurrentPool<T> where T : class, new()
|
||||
{
|
||||
private readonly ConcurrentStack<T> _objs;
|
||||
|
||||
public ConcurrentPool()
|
||||
{
|
||||
_objs = new ConcurrentStack<T>();
|
||||
}
|
||||
|
||||
public ConcurrentPool(int objCount)
|
||||
{
|
||||
_objs = new ConcurrentStack<T>();
|
||||
for (int i = 0; i < objCount; i++)
|
||||
{
|
||||
_objs.Push(new T());
|
||||
}
|
||||
}
|
||||
|
||||
public T GetObject()
|
||||
{
|
||||
if (_objs.TryPop(out T obj))
|
||||
{
|
||||
return obj;
|
||||
}
|
||||
else
|
||||
{
|
||||
return new T();
|
||||
}
|
||||
}
|
||||
|
||||
public void Release(T obj)
|
||||
{
|
||||
_objs.Push(obj);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 226777291e3dca846a892782ceadaec0
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,8 @@
|
|||
fileFormatVersion: 2
|
||||
guid: d2efd1c3b1ea14940bbea68283e5ae22
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,37 @@
|
|||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace QFSW.QC.Containers
|
||||
{
|
||||
public struct ArraySingle<T> : IReadOnlyList<T>
|
||||
{
|
||||
private readonly T _data;
|
||||
|
||||
public ArraySingle(T data)
|
||||
{
|
||||
_data = data;
|
||||
}
|
||||
|
||||
public T this[int index] => _data;
|
||||
|
||||
public int Count => 1;
|
||||
|
||||
public IEnumerator<T> GetEnumerator()
|
||||
{
|
||||
yield return _data;
|
||||
}
|
||||
|
||||
IEnumerator IEnumerable.GetEnumerator()
|
||||
{
|
||||
yield return _data;
|
||||
}
|
||||
}
|
||||
|
||||
public static class ArraySingleExtensions
|
||||
{
|
||||
public static ArraySingle<T> AsArraySingle<T>(this T data)
|
||||
{
|
||||
return new ArraySingle<T>(data);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: e0a7bee164207c044847125f649d72e5
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,53 @@
|
|||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace QFSW.QC.Containers
|
||||
{
|
||||
public struct StringContainer : IReadOnlyList<char>
|
||||
{
|
||||
private readonly string _str;
|
||||
|
||||
public StringContainer(string str)
|
||||
{
|
||||
_str = str;
|
||||
}
|
||||
|
||||
public char this[int index] => _str[index];
|
||||
|
||||
public int Count => _str.Length;
|
||||
|
||||
public IEnumerator<char> GetEnumerator()
|
||||
{
|
||||
for (int i = 0; i < _str.Length; i++)
|
||||
{
|
||||
yield return _str[i];
|
||||
}
|
||||
}
|
||||
|
||||
IEnumerator IEnumerable.GetEnumerator()
|
||||
{
|
||||
for (int i = 0; i < _str.Length; i++)
|
||||
{
|
||||
yield return _str[i];
|
||||
}
|
||||
}
|
||||
|
||||
public static implicit operator StringContainer(string str)
|
||||
{
|
||||
return new StringContainer(str);
|
||||
}
|
||||
|
||||
public static implicit operator string(StringContainer str)
|
||||
{
|
||||
return str._str;
|
||||
}
|
||||
}
|
||||
|
||||
public static class StringContainerExtensions
|
||||
{
|
||||
public static StringContainer AsIReadOnlyList(this string str)
|
||||
{
|
||||
return str;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: b6fe5a46a82b32946a28567aefce78c0
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,8 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 6189a8da57915c848abf41c6ae6fc7f4
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,63 @@
|
|||
using System;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
|
||||
namespace QFSW.QC.Editor
|
||||
{
|
||||
public class DataEntryPopup : PopupWindowContent
|
||||
{
|
||||
private readonly string _title;
|
||||
private readonly string _btnName;
|
||||
|
||||
private string _data;
|
||||
private string _errors;
|
||||
private bool _success;
|
||||
|
||||
private GUIStyle _errorStyle;
|
||||
private GUIStyle _successStyle;
|
||||
|
||||
private readonly Action<string> _submitCallback;
|
||||
|
||||
public DataEntryPopup(string title, string btnName, Action<string> SubmitCallback)
|
||||
{
|
||||
CreateStyles();
|
||||
_title = title;
|
||||
_btnName = btnName;
|
||||
_submitCallback = SubmitCallback;
|
||||
}
|
||||
|
||||
public override Vector2 GetWindowSize() { return new Vector2(500, 100); }
|
||||
|
||||
private void CreateStyles()
|
||||
{
|
||||
_errorStyle = new GUIStyle(EditorStyles.wordWrappedLabel);
|
||||
_errorStyle.normal.textColor = new Color(1, 0, 0);
|
||||
|
||||
_successStyle = new GUIStyle(EditorStyles.wordWrappedLabel);
|
||||
_successStyle.normal.textColor = new Color(0, 0.5f, 0);
|
||||
}
|
||||
|
||||
public override void OnGUI(Rect rect)
|
||||
{
|
||||
_data = EditorGUILayout.TextField(_title, _data);
|
||||
GUI.enabled = !string.IsNullOrWhiteSpace(_data);
|
||||
if (GUILayout.Button(_btnName))
|
||||
{
|
||||
try
|
||||
{
|
||||
_submitCallback(_data);
|
||||
_success = true;
|
||||
_errors = "";
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
_errors = e.Message;
|
||||
_success = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(_errors)) { EditorGUILayout.LabelField(_errors, _errorStyle); }
|
||||
else if (_success) { EditorGUILayout.LabelField("Success!", _successStyle); }
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 5eaadd4a6e56548a0bac180051d85654
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,95 @@
|
|||
using QFSW.QC.QGUI;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
|
||||
namespace QFSW.QC.Editor
|
||||
{
|
||||
public static class EditorHelpers
|
||||
{
|
||||
private struct SupportItem
|
||||
{
|
||||
public string Name;
|
||||
public string Tooltip;
|
||||
public string Url;
|
||||
}
|
||||
|
||||
private static readonly SupportItem[] _supportItems =
|
||||
{
|
||||
new SupportItem
|
||||
{
|
||||
Name = "Docs",
|
||||
Tooltip = "Official and up to date documentation for Quantum Console.",
|
||||
Url = "https://qfsw.co.uk/docs/QC/"
|
||||
},
|
||||
new SupportItem
|
||||
{
|
||||
Name = "Email",
|
||||
Tooltip = "Email address for support and other inquiries.",
|
||||
Url = "mailto:support@qfsw.co.uk"
|
||||
},
|
||||
new SupportItem
|
||||
{
|
||||
Name = "Discord",
|
||||
Tooltip = "Discord server for customer support, WIPs and more.",
|
||||
Url = "https://discord.gg/g8SJ7X6"
|
||||
},
|
||||
new SupportItem
|
||||
{
|
||||
Name = "Twitter",
|
||||
Tooltip = "Get in touch or show off what you've made with QC.",
|
||||
Url = "https://twitter.com/QFSW1024"
|
||||
},
|
||||
new SupportItem
|
||||
{
|
||||
Name = "Review",
|
||||
Tooltip = "Leave a review to share your opinion and support Quantum Console!",
|
||||
Url = "https://assetstore.unity.com/packages/tools/utilities/quantum-console-128881#reviews"
|
||||
},
|
||||
new SupportItem
|
||||
{
|
||||
Name = "Survey",
|
||||
Tooltip = "A short survey to help me get feedback on Quantum Console and prioritize what needs the most focus.",
|
||||
Url = "https://forms.gle/TZbpg1t6hc6sypZA9"
|
||||
}
|
||||
};
|
||||
|
||||
private static Rect[] _supportItemRects = new Rect[_supportItems.Length];
|
||||
|
||||
public static void DrawBanner(Texture2D banner, float sizeMultiplier = 1f)
|
||||
{
|
||||
if (banner)
|
||||
{
|
||||
sizeMultiplier = Mathf.Clamp01(sizeMultiplier);
|
||||
Rect bannerRect = GUILayoutUtility.GetRect(0.0f, 0.0f);
|
||||
bannerRect.height = Screen.width / EditorGUIUtility.pixelsPerPoint * banner.height / banner.width;
|
||||
bannerRect.x += bannerRect.width * (1 - sizeMultiplier) / 2;
|
||||
bannerRect.width *= sizeMultiplier;
|
||||
bannerRect.height *= sizeMultiplier;
|
||||
|
||||
GUILayout.Space(bannerRect.height);
|
||||
GUI.Label(bannerRect, banner);
|
||||
}
|
||||
}
|
||||
|
||||
public static void DrawSupportRow()
|
||||
{
|
||||
LayoutController layout = new LayoutController(EditorGUILayout.GetControlRect());
|
||||
layout.SpliceRow(_supportItemRects.Length, ref _supportItemRects);
|
||||
|
||||
for (int i = 0; i < _supportItems.Length; i++)
|
||||
{
|
||||
SupportItem item = _supportItems[i];
|
||||
if (GUI.Button(_supportItemRects[i], new GUIContent(item.Name, item.Tooltip)))
|
||||
{
|
||||
Application.OpenURL(item.Url);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void DrawHeader(Texture2D banner)
|
||||
{
|
||||
DrawBanner(banner);
|
||||
DrawSupportRow();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: b2819424558646f42af68616ef5e127a
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,42 @@
|
|||
using QFSW.QC.QGUI;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
|
||||
namespace QFSW.QC.Editor
|
||||
{
|
||||
[CustomPropertyDrawer(typeof(ModifierKeyCombo), true)]
|
||||
public class ModifierKeyComboEditor : PropertyDrawer
|
||||
{
|
||||
private readonly GUIContent _shiftLabel = new GUIContent("shift");
|
||||
private readonly GUIContent _altLabel = new GUIContent("alt");
|
||||
private readonly GUIContent _ctrlLabel = new GUIContent("ctrl");
|
||||
|
||||
public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
|
||||
{
|
||||
LayoutController layout = new LayoutController(position);
|
||||
EditorGUI.BeginProperty(layout.CurrentRect, label, property);
|
||||
|
||||
const float boolWidth = 10;
|
||||
bool enableState = GUI.enabled;
|
||||
float boolLabelWidth = QGUILayout.GetMaxContentSize(EditorStyles.label, _shiftLabel, _altLabel, _ctrlLabel).x;
|
||||
|
||||
SerializedProperty key = property.FindPropertyRelative("Key");
|
||||
SerializedProperty ctrl = property.FindPropertyRelative("Ctrl");
|
||||
SerializedProperty alt = property.FindPropertyRelative("Alt");
|
||||
SerializedProperty shift = property.FindPropertyRelative("Shift");
|
||||
|
||||
GUI.enabled &= ((KeyCode)key.enumValueIndex) != KeyCode.None;
|
||||
EditorGUI.LabelField(layout.ReserveHorizontalReversed(boolLabelWidth), _shiftLabel);
|
||||
EditorGUI.PropertyField(layout.ReserveHorizontalReversed(boolWidth), shift, GUIContent.none);
|
||||
EditorGUI.LabelField(layout.ReserveHorizontalReversed(boolLabelWidth), _altLabel);
|
||||
EditorGUI.PropertyField(layout.ReserveHorizontalReversed(boolWidth), alt, GUIContent.none);
|
||||
EditorGUI.LabelField(layout.ReserveHorizontalReversed(boolLabelWidth), _ctrlLabel);
|
||||
EditorGUI.PropertyField(layout.ReserveHorizontalReversed(boolWidth), ctrl, GUIContent.none);
|
||||
|
||||
GUI.enabled = enableState;
|
||||
EditorGUI.PropertyField(layout.CurrentRect, key, label);
|
||||
|
||||
EditorGUI.EndProperty();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: a359df86554203048b60947f59468558
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,47 @@
|
|||
using QFSW.QC.Utilities;
|
||||
using System;
|
||||
using System.IO;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
|
||||
namespace QFSW.QC.Editor
|
||||
{
|
||||
public class QCInspectorBase : UnityEditor.Editor
|
||||
{
|
||||
const string ROOT_PATH = "Source";
|
||||
protected string BannerName => "Banner.png";
|
||||
protected Texture2D Banner { get; private set; }
|
||||
|
||||
protected T LoadAssetInSource<T>(string assetName, string root) where T : UnityEngine.Object
|
||||
{
|
||||
MonoScript src = MonoScript.FromScriptableObject(this);
|
||||
string srcPath = AssetDatabase.GetAssetPath(src);
|
||||
string dirPath = Path.GetDirectoryName(srcPath);
|
||||
string[] pathParts = dirPath.Split(new string[] { root }, StringSplitOptions.None);
|
||||
string rootPath = string.Join(root, pathParts.SkipLast()) + root;
|
||||
string[] files = Directory.GetFiles(rootPath, assetName, SearchOption.AllDirectories);
|
||||
|
||||
if (files.Length > 0)
|
||||
{
|
||||
string bannerPath = files[0];
|
||||
return AssetDatabase.LoadAssetAtPath<T>(bannerPath);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
protected virtual void OnEnable()
|
||||
{
|
||||
if (!Banner)
|
||||
{
|
||||
Banner = LoadAssetInSource<Texture2D>(BannerName, ROOT_PATH);
|
||||
}
|
||||
}
|
||||
|
||||
public override void OnInspectorGUI()
|
||||
{
|
||||
EditorHelpers.DrawHeader(Banner);
|
||||
base.OnInspectorGUI();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 117a477a3c59db341907364ce3923b02
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,19 @@
|
|||
{
|
||||
"name": "QFSW.QC.Editor",
|
||||
"references": [
|
||||
"QFSW.QC",
|
||||
"QFSW.QC.Editor.Tools",
|
||||
"QFSW.QC.QGUI",
|
||||
"Unity.TextMeshPro"
|
||||
],
|
||||
"optionalUnityReferences": [],
|
||||
"includePlatforms": [
|
||||
"Editor"
|
||||
],
|
||||
"excludePlatforms": [],
|
||||
"allowUnsafeCode": false,
|
||||
"overrideReferences": false,
|
||||
"precompiledReferences": [],
|
||||
"autoReferenced": true,
|
||||
"defineConstraints": []
|
||||
}
|
|
@ -0,0 +1,7 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 50b2bdd4833ec8043a7227258a04ccb7
|
||||
AssemblyDefinitionImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,8 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 979ba78ee0b3f154ab44f1295d48ce61
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,7 @@
|
|||
namespace QFSW.QC.QGUI
|
||||
{
|
||||
public interface IGUIItem
|
||||
{
|
||||
void DrawGUI(LayoutController layout);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 506cdc118faa64bd7b040644b69c623b
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,140 @@
|
|||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
|
||||
namespace QFSW.QC.QGUI
|
||||
{
|
||||
public class LayoutController
|
||||
{
|
||||
public static float HorizontalPadding => 4;
|
||||
public static float RowPadding => EditorGUIUtility.standardVerticalSpacing;
|
||||
public static float RowHeight => EditorGUIUtility.singleLineHeight;
|
||||
|
||||
public bool IsValid
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_currentRect.width < 0) { return false; }
|
||||
if (_currentRect.height < 0) { return false; }
|
||||
if (_currentRect.x < TotalDrawRect.x) { return false; }
|
||||
if (_currentRect.y < TotalDrawRect.y) { return false; }
|
||||
if (_currentRect.x + _currentRect.width > TotalDrawRect.x + TotalDrawRect.width) { return false; }
|
||||
if (_currentRect.y + _currentRect.height > TotalDrawRect.y + TotalDrawRect.height) { return false; }
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
public Rect TotalDrawRect { get; }
|
||||
public Rect CurrentRect => _currentRect;
|
||||
|
||||
private Rect _currentRect;
|
||||
|
||||
public LayoutController(Rect drawRect)
|
||||
{
|
||||
TotalDrawRect = drawRect;
|
||||
_currentRect = drawRect;
|
||||
_currentRect.height = RowHeight;
|
||||
}
|
||||
|
||||
public Rect BeginNewLine()
|
||||
{
|
||||
_currentRect.y += RowPadding + RowHeight;
|
||||
_currentRect.x = TotalDrawRect.x;
|
||||
_currentRect.width = TotalDrawRect.width;
|
||||
return _currentRect;
|
||||
}
|
||||
|
||||
public Rect ReserveHorizontal(float width)
|
||||
{
|
||||
Rect drawRect = _currentRect;
|
||||
drawRect.width = width;
|
||||
drawRect.width -= HorizontalPadding;
|
||||
|
||||
_currentRect.x += width;
|
||||
_currentRect.width -= width;
|
||||
|
||||
return drawRect;
|
||||
}
|
||||
|
||||
public Rect ReserveHorizontalPercentage(float widthPercentage)
|
||||
{
|
||||
float width = _currentRect.width * widthPercentage;
|
||||
return ReserveHorizontal(width);
|
||||
}
|
||||
|
||||
public Rect ReserveHorizontalReversed(float width)
|
||||
{
|
||||
Rect drawRect = _currentRect;
|
||||
drawRect.x += drawRect.width;
|
||||
drawRect.x -= width;
|
||||
drawRect.width = width;
|
||||
|
||||
_currentRect.width -= HorizontalPadding;
|
||||
_currentRect.width -= width;
|
||||
|
||||
return drawRect;
|
||||
}
|
||||
|
||||
public Rect ReserveHorizontalReversedPercentage(float widthPercentage)
|
||||
{
|
||||
float width = _currentRect.width * widthPercentage;
|
||||
return ReserveHorizontalReversed(width);
|
||||
}
|
||||
|
||||
public Rect ResizeRectHeight(Rect rect, float height)
|
||||
{
|
||||
rect.y += (rect.height - height) / 2;
|
||||
rect.height = height;
|
||||
|
||||
return rect;
|
||||
}
|
||||
|
||||
public Rect ReserveHorizontal(float width, float height)
|
||||
{
|
||||
return ResizeRectHeight(ReserveHorizontal(width), height);
|
||||
}
|
||||
|
||||
public Rect ReserveHorizontalReversed(float width, float height)
|
||||
{
|
||||
return ResizeRectHeight(ReserveHorizontalReversed(width), height);
|
||||
}
|
||||
|
||||
public Rect ReserveSquare()
|
||||
{
|
||||
return ReserveHorizontal(RowHeight);
|
||||
}
|
||||
|
||||
public Rect ReserveSquareReversed()
|
||||
{
|
||||
return ReserveHorizontalReversed(RowHeight);
|
||||
}
|
||||
|
||||
public Rect ReserveAuto(GUIContent content, GUIStyle style)
|
||||
{
|
||||
Vector2 size = style.CalcSize(content);
|
||||
return ReserveHorizontal(size.x, size.y);
|
||||
}
|
||||
|
||||
public Rect ReserveAutoReversed(GUIContent content, GUIStyle style)
|
||||
{
|
||||
Vector2 size = style.CalcSize(content);
|
||||
return ReserveHorizontalReversed(size.x, size.y);
|
||||
}
|
||||
|
||||
public void SpliceRow(int colCount, ref Rect[] rects)
|
||||
{
|
||||
float width = _currentRect.width / colCount;
|
||||
for (int i = 0; i < rects.Length; i++)
|
||||
{
|
||||
rects[i] = ReserveHorizontal(width);
|
||||
}
|
||||
}
|
||||
|
||||
public Rect[] SpliceRow(int colCount)
|
||||
{
|
||||
Rect[] rects = new Rect[colCount];
|
||||
SpliceRow(colCount, ref rects);
|
||||
return rects;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 481da05e0c09175429ec2db6589454a5
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,14 @@
|
|||
{
|
||||
"name": "QFSW.QC.QGUI",
|
||||
"references": [],
|
||||
"optionalUnityReferences": [],
|
||||
"includePlatforms": [
|
||||
"Editor"
|
||||
],
|
||||
"excludePlatforms": [],
|
||||
"allowUnsafeCode": false,
|
||||
"overrideReferences": false,
|
||||
"precompiledReferences": [],
|
||||
"autoReferenced": true,
|
||||
"defineConstraints": []
|
||||
}
|
|
@ -0,0 +1,7 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 2c8115fef53c440a1873e4077e45b326
|
||||
AssemblyDefinitionImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,49 @@
|
|||
using System;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
|
||||
namespace QFSW.QC.QGUI
|
||||
{
|
||||
public static class QGUILayout
|
||||
{
|
||||
public static T EnumPopup<T>(T selected, params GUILayoutOption[] options) where T : Enum
|
||||
{
|
||||
return (T)EditorGUILayout.EnumPopup(selected, options);
|
||||
}
|
||||
|
||||
public static T EnumPopup<T>(GUIContent content, T selected, params GUILayoutOption[] options) where T : Enum
|
||||
{
|
||||
return (T)EditorGUILayout.EnumPopup(content, selected, options);
|
||||
}
|
||||
|
||||
public static T EnumFlagsField<T>(GUIContent content, T enumValue, params GUILayoutOption[] options) where T : Enum
|
||||
{
|
||||
return (T)EditorGUILayout.EnumFlagsField(content, enumValue, options);
|
||||
}
|
||||
|
||||
public static bool ButtonAuto(GUIContent content, GUIStyle style)
|
||||
{
|
||||
Vector2 size = style.CalcSize(content);
|
||||
return GUILayout.Button(content, style, GUILayout.Width(size.x));
|
||||
}
|
||||
|
||||
public static bool ButtonAuto(LayoutController layout, GUIContent content, GUIStyle style)
|
||||
{
|
||||
Rect rect = layout.ReserveAuto(content, style);
|
||||
return GUI.Button(rect, content, style);
|
||||
}
|
||||
|
||||
public static Vector2 GetMaxContentSize(GUIStyle style, params GUIContent[] contents)
|
||||
{
|
||||
Vector2 maxSize = new Vector2();
|
||||
foreach (GUIContent content in contents)
|
||||
{
|
||||
Vector2 size = style.CalcSize(content);
|
||||
maxSize.x = Mathf.Max(maxSize.x, size.x);
|
||||
maxSize.y = Mathf.Max(maxSize.y, size.y);
|
||||
}
|
||||
|
||||
return maxSize;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: df613967b4fdf486d9a4e932822cec60
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,242 @@
|
|||
using QFSW.QC.Editor.Tools;
|
||||
using QFSW.QC.QGUI;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
|
||||
namespace QFSW.QC.Editor
|
||||
{
|
||||
[CustomEditor(typeof(QuantumConsole), true)]
|
||||
public class QuantumConsoleInspector : QCInspectorBase
|
||||
{
|
||||
private QuantumConsole QCInstance;
|
||||
|
||||
private SerializedProperty _themeProperty;
|
||||
private SerializedProperty _keyConfigProperty;
|
||||
|
||||
private SerializedProperty _verboseLoggingProperty;
|
||||
private SerializedProperty _verboseErrorsProperty;
|
||||
private SerializedProperty _loggingLevelProperty;
|
||||
|
||||
private SerializedProperty _openOnLogLevelProperty;
|
||||
private SerializedProperty _supportedStateProperty;
|
||||
private SerializedProperty _autoScrollProperty;
|
||||
private SerializedProperty _interceptDebugProperty;
|
||||
private SerializedProperty _interceptInactiveProperty;
|
||||
private SerializedProperty _prependTimestampsProperty;
|
||||
private SerializedProperty _activateOnStartupProperty;
|
||||
private SerializedProperty _initialiseOnStartupProperty;
|
||||
private SerializedProperty _closeOnSubmitProperty;
|
||||
private SerializedProperty _singletonModeProperty;
|
||||
private SerializedProperty _inputProperty;
|
||||
private SerializedProperty _inputPlaceholderProperty;
|
||||
private SerializedProperty _logProperty;
|
||||
private SerializedProperty _containerProperty;
|
||||
private SerializedProperty _scrollRectProperty;
|
||||
private SerializedProperty _suggestionProperty;
|
||||
private SerializedProperty _popupProperty;
|
||||
private SerializedProperty _popupTextProperty;
|
||||
private SerializedProperty _jobCounterTextProperty;
|
||||
private SerializedProperty _jobCounterRectProperty;
|
||||
private SerializedProperty _panelsProperty;
|
||||
|
||||
private SerializedProperty _commandHistoryProperty;
|
||||
private SerializedProperty _commandHistorySizeProperty;
|
||||
private SerializedProperty _commandHistoryDuplicatesProperty;
|
||||
private SerializedProperty _commandHistoryAdjacentDuplicatesProperty;
|
||||
|
||||
private SerializedProperty _usePopupProperty;
|
||||
private SerializedProperty _maxSuggestionProperty;
|
||||
private SerializedProperty _popupOrderProperty;
|
||||
private SerializedProperty _fuzzyProperty;
|
||||
private SerializedProperty _caseSensitiveProperty;
|
||||
|
||||
private SerializedProperty _showCurrentJobsProperty;
|
||||
private SerializedProperty _blockOnAsyncProperty;
|
||||
private SerializedProperty _maxStoredLogsProperty;
|
||||
private SerializedProperty _maxLogSizeProperty;
|
||||
private SerializedProperty _showInitLogsProperty;
|
||||
|
||||
protected override void OnEnable()
|
||||
{
|
||||
base.OnEnable();
|
||||
|
||||
QCInstance = (QuantumConsole)target;
|
||||
QCInstance.OnStateChange += Repaint;
|
||||
|
||||
FetchSerializedProperties();
|
||||
}
|
||||
|
||||
private void FetchSerializedProperties()
|
||||
{
|
||||
_themeProperty = serializedObject.FindProperty("_theme");
|
||||
_keyConfigProperty = serializedObject.FindProperty("_keyConfig");
|
||||
|
||||
_verboseLoggingProperty = serializedObject.FindProperty("_verboseLogging");
|
||||
_verboseErrorsProperty = serializedObject.FindProperty("_verboseErrors");
|
||||
_loggingLevelProperty = serializedObject.FindProperty("_loggingLevel");
|
||||
_openOnLogLevelProperty = serializedObject.FindProperty("_openOnLogLevel");
|
||||
_supportedStateProperty = serializedObject.FindProperty("_supportedState");
|
||||
_autoScrollProperty = serializedObject.FindProperty("_autoScroll");
|
||||
_interceptDebugProperty = serializedObject.FindProperty("_interceptDebugLogger");
|
||||
_interceptInactiveProperty = serializedObject.FindProperty("_interceptWhilstInactive");
|
||||
_prependTimestampsProperty = serializedObject.FindProperty("_prependTimestamps");
|
||||
_activateOnStartupProperty = serializedObject.FindProperty("_activateOnStartup");
|
||||
_initialiseOnStartupProperty = serializedObject.FindProperty("_initialiseOnStartup");
|
||||
_closeOnSubmitProperty = serializedObject.FindProperty("_closeOnSubmit");
|
||||
_singletonModeProperty = serializedObject.FindProperty("_singletonMode");
|
||||
_containerProperty = serializedObject.FindProperty("_containerRect");
|
||||
_scrollRectProperty = serializedObject.FindProperty("_scrollRect");
|
||||
_popupProperty = serializedObject.FindProperty("_suggestionPopupRect");
|
||||
_jobCounterRectProperty = serializedObject.FindProperty("_jobCounterRect");
|
||||
_panelsProperty = serializedObject.FindProperty("_panels");
|
||||
_commandHistoryProperty = serializedObject.FindProperty("_storeCommandHistory");
|
||||
_commandHistoryDuplicatesProperty = serializedObject.FindProperty("_storeDuplicateCommands");
|
||||
_commandHistoryAdjacentDuplicatesProperty = serializedObject.FindProperty("_storeAdjacentDuplicateCommands");
|
||||
_commandHistorySizeProperty = serializedObject.FindProperty("_commandHistorySize");
|
||||
_showCurrentJobsProperty = serializedObject.FindProperty("_showCurrentJobs");
|
||||
_blockOnAsyncProperty = serializedObject.FindProperty("_blockOnAsync");
|
||||
_usePopupProperty = serializedObject.FindProperty("_showPopupDisplay");
|
||||
_maxSuggestionProperty = serializedObject.FindProperty("_maxSuggestionDisplaySize");
|
||||
_popupOrderProperty = serializedObject.FindProperty("_suggestionDisplayOrder");
|
||||
_fuzzyProperty = serializedObject.FindProperty("_useFuzzySearch");
|
||||
_caseSensitiveProperty = serializedObject.FindProperty("_caseSensitiveSearch");
|
||||
_maxStoredLogsProperty = serializedObject.FindProperty("_maxStoredLogs");
|
||||
_maxLogSizeProperty = serializedObject.FindProperty("_maxLogSize");
|
||||
_showInitLogsProperty = serializedObject.FindProperty("_showInitLogs");
|
||||
|
||||
_inputProperty = serializedObject.FindProperty("_consoleInput");
|
||||
_inputPlaceholderProperty = serializedObject.FindProperty("_inputPlaceholderText");
|
||||
_logProperty = serializedObject.FindProperty("_consoleLogText");
|
||||
_suggestionProperty = serializedObject.FindProperty("_consoleSuggestionText");
|
||||
_popupTextProperty = serializedObject.FindProperty("_suggestionPopupText");
|
||||
_jobCounterTextProperty = serializedObject.FindProperty("_jobCounterText");
|
||||
}
|
||||
|
||||
private void OnDisable()
|
||||
{
|
||||
QCInstance.OnStateChange -= Repaint;
|
||||
}
|
||||
|
||||
public override void OnInspectorGUI()
|
||||
{
|
||||
serializedObject.Update();
|
||||
EditorHelpers.DrawHeader(Banner);
|
||||
|
||||
if (QuantumConsoleProcessor.TableGenerated || QuantumConsoleProcessor.TableIsGenerating)
|
||||
{
|
||||
EditorGUILayout.LabelField("Quantum Console Processor Information", EditorStyles.miniBoldLabel);
|
||||
if (QuantumConsoleProcessor.TableIsGenerating) { EditorGUILayout.LabelField("Command Table Generating...", EditorStyles.miniLabel); }
|
||||
EditorGUILayout.LabelField($"Commands Loaded: {QuantumConsoleProcessor.LoadedCommandCount}", EditorStyles.miniLabel);
|
||||
EditorGUILayout.Space();
|
||||
}
|
||||
|
||||
EditorGUILayout.LabelField(new GUIContent("General Settings", "All general and basic settings for the Quantum Console."), EditorStyles.boldLabel);
|
||||
EditorGUILayout.BeginHorizontal();
|
||||
EditorGUILayout.PropertyField(_themeProperty, new GUIContent("Theme", "QuantumTheme to use for this Quantum Console."));
|
||||
if (_themeProperty.objectReferenceValue)
|
||||
{
|
||||
GUIContent applyBtnContent = new GUIContent("Apply", "Forces an application of the theme now allowing you to see any GUI changes it would make");
|
||||
if (QGUILayout.ButtonAuto(applyBtnContent, EditorStyles.miniButton))
|
||||
{
|
||||
Undo.RecordObject(QCInstance, "Applied a theme to the Quantum Console");
|
||||
QCInstance.ApplyTheme((QuantumTheme)_themeProperty.objectReferenceValue, true);
|
||||
PrefabUtil.RecordPrefabInstancePropertyModificationsFullyRecursive(QCInstance.gameObject);
|
||||
EditorUtility.SetDirty(QCInstance);
|
||||
}
|
||||
}
|
||||
EditorGUILayout.EndHorizontal();
|
||||
EditorGUILayout.PropertyField(_keyConfigProperty, new GUIContent("Key Configuration", "Key configuration for the various keyboard shortcuts used by Quantum Console."));
|
||||
|
||||
EditorGUILayout.BeginHorizontal();
|
||||
EditorGUILayout.PropertyField(_supportedStateProperty, new GUIContent("Enabled", "On which build/editor states should the console be enabled on"));
|
||||
ShowSceneViewToggle();
|
||||
EditorGUILayout.EndHorizontal();
|
||||
EditorGUILayout.PropertyField(_activateOnStartupProperty, new GUIContent("Activate on Startup", "If the Quantum Console should be shown and activated on startup."));
|
||||
if (!_activateOnStartupProperty.boolValue)
|
||||
{
|
||||
EditorGUILayout.PropertyField(_initialiseOnStartupProperty, new GUIContent("Initialise on Startup", "If the Quantum Console should be initialised on startup in the background."));
|
||||
}
|
||||
|
||||
EditorGUILayout.PropertyField(_closeOnSubmitProperty, new GUIContent("Close on Submit", "If the Quantum Console should be hidden and closed when a command is submitted and invoked."));
|
||||
EditorGUILayout.PropertyField(_singletonModeProperty, new GUIContent("Singleton", "Forces the console into singleton mode. " +
|
||||
"This means the console will be made scene persistent and will not be destroyed when new scenes are loaded. " +
|
||||
"Additionally, only one instance of the console will be allowed to exist, and it will be accessible via QuantumConsole.Instance"));
|
||||
EditorGUILayout.PropertyField(_verboseErrorsProperty, new GUIContent("Verbose Errors", "If errors caused by the Quantum Console Processor or commands should be logged in verbose mode."));
|
||||
EditorGUILayout.PropertyField(_autoScrollProperty, new GUIContent("Autoscroll", "Determine if and when the console should autoscroll."));
|
||||
EditorGUILayout.Space();
|
||||
|
||||
EditorGUILayout.LabelField(new GUIContent("Debug Interception", "All settings relating to the interception of Unity's Debug class."), EditorStyles.boldLabel);
|
||||
EditorGUILayout.PropertyField(_interceptDebugProperty, new GUIContent("Intercept Debug Messages", "If the Quantum Console should intercept and display messages from the Unity Debug logging."));
|
||||
if (_interceptDebugProperty.boolValue)
|
||||
{
|
||||
EditorGUILayout.PropertyField(_interceptInactiveProperty, new GUIContent("Intercept Whilst Inactive", "If the Quantum Console should continue to intercept messages whilst inactive."));
|
||||
EditorGUILayout.PropertyField(_prependTimestampsProperty, new GUIContent("Enable Timestamps", "If the timestamp of the log message should be prepended."));
|
||||
EditorGUILayout.PropertyField(_loggingLevelProperty, new GUIContent("Logging Level", "The minimum log severity required to intercept and display the log."));
|
||||
EditorGUILayout.PropertyField(_verboseLoggingProperty, new GUIContent("Verbose Logging", "The minimum log severity required to use verbose logging."));
|
||||
EditorGUILayout.PropertyField(_openOnLogLevelProperty, new GUIContent("Open Console", "The minimum log severity required to open the console."));
|
||||
}
|
||||
EditorGUILayout.Space();
|
||||
|
||||
EditorGUILayout.LabelField(new GUIContent("Async Settings", "All settings related to async commands."), EditorStyles.boldLabel);
|
||||
EditorGUILayout.PropertyField(_showCurrentJobsProperty, new GUIContent("Show Current Jobs", "Shows a popup counter with the currently executing async commands."));
|
||||
EditorGUILayout.PropertyField(_blockOnAsyncProperty, new GUIContent("Block on Execute", "Blocks the Quantum Console from being used until the current async command has finished."));
|
||||
EditorGUILayout.Space();
|
||||
|
||||
EditorGUILayout.LabelField(new GUIContent("Command Search", "Settings relating to searching for commands in the console using tab."), EditorStyles.boldLabel);
|
||||
EditorGUILayout.PropertyField(_fuzzyProperty, new GUIContent("Use Fuzzy Search", "If fuzzy search is disabled, then your current search must match the beginning of the command to be suggested (foo*). If fuzzy search is enabled, it can be anywhere within the command name to be suggested (*foo*)."));
|
||||
EditorGUILayout.PropertyField(_caseSensitiveProperty, new GUIContent("Case Sensitive", "If the search should be case sensitive or not."));
|
||||
EditorGUILayout.PropertyField(_usePopupProperty, new GUIContent("Show Popup Display", "If enabled, a popup display will be shown containing potential command autocompletions as you type."));
|
||||
if (_usePopupProperty.boolValue)
|
||||
{
|
||||
EditorGUILayout.PropertyField(_maxSuggestionProperty, new GUIContent("Max Suggestion Count", "The maximum number of suggestions to display in the popup. Set to -1 for unlimited."));
|
||||
EditorGUILayout.PropertyField(_popupOrderProperty, new GUIContent("Suggestion Popup Order", "The sort direction used when displaying suggestions to the popup display."));
|
||||
}
|
||||
EditorGUILayout.Space();
|
||||
|
||||
EditorGUILayout.LabelField(new GUIContent("Command History", "Settings relating to storing previous commands so that they can be easily accessed with the arrow keys."), EditorStyles.boldLabel);
|
||||
EditorGUILayout.PropertyField(_commandHistoryProperty, new GUIContent("Store Previous Commands", "If previous commands should be stored, allowing them to be accessed with the arrow keys."));
|
||||
if (_commandHistoryProperty.boolValue)
|
||||
{
|
||||
EditorGUILayout.PropertyField(_commandHistoryDuplicatesProperty, new GUIContent("Allow Duplicates", "Store commands into the history even if they have already appeared."));
|
||||
if (_commandHistoryDuplicatesProperty.boolValue) { EditorGUILayout.PropertyField(_commandHistoryAdjacentDuplicatesProperty, new GUIContent("Allow Adjacent Duplicates", "Store commands in the history even if they are adjacent duplicates (i.e same command multiple times in a row).")); }
|
||||
_commandHistorySizeProperty.intValue = Mathf.Max(-1, EditorGUILayout.IntField(new GUIContent("Max Size", "The maximum size of the command history buffer; exceeding this size will cause the oldest commands to be removed to make space. Set to -1 for unlimited."), _commandHistorySizeProperty.intValue));
|
||||
}
|
||||
EditorGUILayout.Space();
|
||||
|
||||
EditorGUILayout.LabelField(new GUIContent("Advanced Settings", "Advanced settings such as buffer sizes."), EditorStyles.boldLabel);
|
||||
EditorGUILayout.PropertyField(_maxStoredLogsProperty, new GUIContent("Maximum Stored Logs", "Maximum number of logtraces to store before discarding old logs. Set to -1 for unlimited."));
|
||||
EditorGUILayout.PropertyField(_maxLogSizeProperty, new GUIContent("Maximum Log Size", "Logs exceeding this size will be discarded and an error will be shown. Set to -1 for no maximum size on a single log."));
|
||||
EditorGUILayout.PropertyField(_showInitLogsProperty, new GUIContent("Show Initialization Logs", "Whether the initialization logs should be shown or not."));
|
||||
EditorGUILayout.Space();
|
||||
|
||||
EditorGUILayout.LabelField(new GUIContent("References", "All the references needed by the Quantum Console"), EditorStyles.boldLabel);
|
||||
EditorGUILayout.PropertyField(_containerProperty, new GUIContent("Container Rect", "The top level container rect-transform containing all of the Quantum Console UI elements."));
|
||||
EditorGUILayout.PropertyField(_scrollRectProperty, new GUIContent("Scroll Rect", "(Optional) The scroll rect of the console text, required for auto scrolling."));
|
||||
EditorGUILayout.PropertyField(_popupProperty, new GUIContent("Suggestion Popup Display", "Top level transform for the suggestion popup display."));
|
||||
EditorGUILayout.PropertyField(_jobCounterRectProperty, new GUIContent("Job Counter Display", "Top level transform for the job counter display."));
|
||||
|
||||
EditorGUILayout.PropertyField(_inputProperty, new GUIContent("Console Input Field", "The input field used for interfacing with the Quantum Console."));
|
||||
EditorGUILayout.PropertyField(_inputPlaceholderProperty, new GUIContent("Console Input Placeholder", "The placeholder text component for when the input field is not in use."));
|
||||
EditorGUILayout.PropertyField(_popupTextProperty, new GUIContent("Suggestion Popup Text", "Text display for the suggestion popup display."));
|
||||
EditorGUILayout.PropertyField(_logProperty, new GUIContent("Console Log Display", "The text display used as the log output by the Quantum Console."));
|
||||
EditorGUILayout.PropertyField(_suggestionProperty, new GUIContent("Command Suggestion Display", "(optional) If assigned, the Quantum Console will show the paramater signature for suggested commands here."));
|
||||
EditorGUILayout.PropertyField(_jobCounterTextProperty, new GUIContent("Job Counter Text", "Text display for the job counter display."));
|
||||
|
||||
EditorGUILayout.PropertyField(_panelsProperty, new GUIContent("UI Panels", "All panels in the UI to control with the Quantum Theme."), true);
|
||||
|
||||
serializedObject.ApplyModifiedProperties();
|
||||
}
|
||||
|
||||
private void ShowSceneViewToggle()
|
||||
{
|
||||
RectTransform consoleContainer = (RectTransform)_containerProperty.objectReferenceValue;
|
||||
bool containerFound = consoleContainer;
|
||||
bool containerHidden = containerFound ? consoleContainer.gameObject.activeSelf : false;
|
||||
|
||||
GUI.enabled = containerFound;
|
||||
GUIContent message = new GUIContent(containerFound ? containerHidden ? "Hide Console" : "Show Console" : "Console Missing");
|
||||
if (QGUILayout.ButtonAuto(message, EditorStyles.miniButton)) { consoleContainer.gameObject.SetActive(!consoleContainer.gameObject.activeSelf); }
|
||||
GUI.enabled = true;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 183567afdaef7164f803d9188375d34b
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences:
|
||||
- banner: {fileID: 2800000, guid: 0a00d33b88ebe3f4eb5dfb0d2a1c0726, type: 3}
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,86 @@
|
|||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
|
||||
namespace QFSW.QC.Editor
|
||||
{
|
||||
[CustomEditor(typeof(QuantumKeyConfig))]
|
||||
public class QuantumKeyConfigInspector : QCInspectorBase
|
||||
{
|
||||
private QuantumKeyConfig _keyConfigInstance;
|
||||
|
||||
private SerializedProperty _submitCommandKeyProperty;
|
||||
private SerializedProperty _hideConsoleKeyProperty;
|
||||
private SerializedProperty _showConsoleKeyProperty;
|
||||
private SerializedProperty _toggleConsoleVisibilityKeyProperty;
|
||||
|
||||
private SerializedProperty _zoomInKeyProperty;
|
||||
private SerializedProperty _zoomOutKeyProperty;
|
||||
private SerializedProperty _dragConsoleKeyProperty;
|
||||
|
||||
private SerializedProperty _suggestNextCommandKeyProperty;
|
||||
private SerializedProperty _suggestPreviousCommandKeyProperty;
|
||||
|
||||
private SerializedProperty _nextCommandKeyProperty;
|
||||
private SerializedProperty _previousCommandKeyProperty;
|
||||
|
||||
private SerializedProperty _cancelActionsKeyProperty;
|
||||
|
||||
protected override void OnEnable()
|
||||
{
|
||||
base.OnEnable();
|
||||
|
||||
_keyConfigInstance = (QuantumKeyConfig)target;
|
||||
|
||||
_submitCommandKeyProperty = serializedObject.FindProperty("SubmitCommandKey");
|
||||
_hideConsoleKeyProperty = serializedObject.FindProperty("HideConsoleKey");
|
||||
_showConsoleKeyProperty = serializedObject.FindProperty("ShowConsoleKey");
|
||||
_toggleConsoleVisibilityKeyProperty = serializedObject.FindProperty("ToggleConsoleVisibilityKey");
|
||||
|
||||
_zoomInKeyProperty = serializedObject.FindProperty("ZoomInKey");
|
||||
_zoomOutKeyProperty = serializedObject.FindProperty("ZoomOutKey");
|
||||
_dragConsoleKeyProperty = serializedObject.FindProperty("DragConsoleKey");
|
||||
|
||||
_suggestNextCommandKeyProperty = serializedObject.FindProperty("SuggestNextCommandKey");
|
||||
_suggestPreviousCommandKeyProperty = serializedObject.FindProperty("SuggestPreviousCommandKey");
|
||||
|
||||
_nextCommandKeyProperty = serializedObject.FindProperty("NextCommandKey");
|
||||
_previousCommandKeyProperty = serializedObject.FindProperty("PreviousCommandKey");
|
||||
|
||||
_cancelActionsKeyProperty = serializedObject.FindProperty("CancelActionsKey");
|
||||
}
|
||||
|
||||
public override void OnInspectorGUI()
|
||||
{
|
||||
serializedObject.Update();
|
||||
EditorHelpers.DrawHeader(Banner);
|
||||
|
||||
EditorGUILayout.LabelField(new GUIContent("General"), EditorStyles.boldLabel);
|
||||
EditorGUILayout.PropertyField(_submitCommandKeyProperty, new GUIContent("Submit Command", "The key to submit and invoke the current console input."));
|
||||
EditorGUILayout.PropertyField(_showConsoleKeyProperty, new GUIContent("Show Console", "The key used to show and activate the console."));
|
||||
EditorGUILayout.PropertyField(_hideConsoleKeyProperty, new GUIContent("Hide Console", "The key used to hide and deactivate the console."));
|
||||
EditorGUILayout.PropertyField(_toggleConsoleVisibilityKeyProperty, new GUIContent("Toggle Console", "The key used to toggle the active and visibility state of the console."));
|
||||
EditorGUILayout.Space();
|
||||
|
||||
EditorGUILayout.LabelField(new GUIContent("UI"), EditorStyles.boldLabel);
|
||||
EditorGUILayout.PropertyField(_zoomInKeyProperty, new GUIContent("Zoom In", "Zooms in the console scaling."));
|
||||
EditorGUILayout.PropertyField(_zoomOutKeyProperty, new GUIContent("Zoom Out", "Zooms out the console scaling."));
|
||||
EditorGUILayout.PropertyField(_dragConsoleKeyProperty, new GUIContent("Drag Console", "Drags the console window with the cursor."));
|
||||
EditorGUILayout.Space();
|
||||
|
||||
EditorGUILayout.LabelField(new GUIContent("Command Suggestions"), EditorStyles.boldLabel);
|
||||
EditorGUILayout.PropertyField(_suggestNextCommandKeyProperty, new GUIContent("Show Suggested Commands", "The key to show and suggest commands based on the current console input."));
|
||||
EditorGUILayout.PropertyField(_suggestPreviousCommandKeyProperty, new GUIContent("Show Previous Suggestion", "The key to show the previous suggestion."));
|
||||
EditorGUILayout.Space();
|
||||
|
||||
EditorGUILayout.LabelField(new GUIContent("Command History"), EditorStyles.boldLabel);
|
||||
EditorGUILayout.PropertyField(_nextCommandKeyProperty, new GUIContent("Select Next Command", "The key to be used to select the next command from the console history."));
|
||||
EditorGUILayout.PropertyField(_previousCommandKeyProperty, new GUIContent("Select Previous Command", "The key to be used to select the previous command from the console history."));
|
||||
EditorGUILayout.Space();
|
||||
|
||||
EditorGUILayout.LabelField(new GUIContent("Actions"), EditorStyles.boldLabel);
|
||||
EditorGUILayout.PropertyField(_cancelActionsKeyProperty, new GUIContent("Cancel Actions", "Cancels any actions currently executing."));
|
||||
|
||||
serializedObject.ApplyModifiedProperties();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 37cda8ee039ccf9499ee9ed64f06664a
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,237 @@
|
|||
using QFSW.QC.Utilities;
|
||||
using System;
|
||||
using System.Collections;
|
||||
using UnityEditor;
|
||||
using UnityEditorInternal;
|
||||
using UnityEngine;
|
||||
|
||||
namespace QFSW.QC.Editor
|
||||
{
|
||||
[CustomEditor(typeof(QuantumTheme), true)]
|
||||
public class QuantumThemeInspector : QCInspectorBase
|
||||
{
|
||||
private QuantumTheme _themeInstance;
|
||||
|
||||
private SerializedProperty _fontProperty;
|
||||
private SerializedProperty _panelMaterialProperty;
|
||||
private SerializedProperty _panelColorProperty;
|
||||
|
||||
private SerializedProperty _errorColorProperty;
|
||||
private SerializedProperty _warningColorProperty;
|
||||
private SerializedProperty _successColorProperty;
|
||||
private SerializedProperty _selectedSuggestionColorProperty;
|
||||
private SerializedProperty _suggestionColorProperty;
|
||||
private SerializedProperty _commandLogColorProperty;
|
||||
private SerializedProperty _defaultValueColorProperty;
|
||||
|
||||
private SerializedProperty _timestampFormatProperty;
|
||||
|
||||
private ReorderableList _typeFormattersListDisplay;
|
||||
private SerializedProperty _typeFormattersProperty;
|
||||
|
||||
private ReorderableList _collectionFormattersListDisplay;
|
||||
private SerializedProperty _collectionFormattersProperty;
|
||||
|
||||
private GUIStyle _centeredMiniLabel;
|
||||
private GUIStyle _centeredLabel;
|
||||
private GUIStyle _centeredTextField;
|
||||
private bool _initialisedStyles;
|
||||
|
||||
protected override void OnEnable()
|
||||
{
|
||||
base.OnEnable();
|
||||
|
||||
_themeInstance = (QuantumTheme)target;
|
||||
|
||||
_fontProperty = serializedObject.FindProperty("Font");
|
||||
_panelMaterialProperty = serializedObject.FindProperty("PanelMaterial");
|
||||
_panelColorProperty = serializedObject.FindProperty("PanelColor");
|
||||
|
||||
_defaultValueColorProperty = serializedObject.FindProperty("DefaultReturnValueColor");
|
||||
_errorColorProperty = serializedObject.FindProperty("ErrorColor");
|
||||
_warningColorProperty = serializedObject.FindProperty("WarningColor");
|
||||
_successColorProperty = serializedObject.FindProperty("SuccessColor");
|
||||
_selectedSuggestionColorProperty = serializedObject.FindProperty("SelectedSuggestionColor");
|
||||
_suggestionColorProperty = serializedObject.FindProperty("SuggestionColor");
|
||||
_commandLogColorProperty = serializedObject.FindProperty("CommandLogColor");
|
||||
|
||||
_timestampFormatProperty = serializedObject.FindProperty("TimestampFormat");
|
||||
|
||||
_typeFormattersProperty = serializedObject.FindProperty("TypeFormatters");
|
||||
_typeFormattersListDisplay = new ReorderableList(serializedObject, _typeFormattersProperty, true, true, true, true);
|
||||
_typeFormattersListDisplay.onAddCallback = AppendNewTypeFormatter;
|
||||
_typeFormattersListDisplay.drawElementCallback = DrawTypeFormatterInspector;
|
||||
_typeFormattersListDisplay.drawHeaderCallback = DrawTypeFormatterListHeader;
|
||||
|
||||
_collectionFormattersProperty = serializedObject.FindProperty("CollectionFormatters");
|
||||
_collectionFormattersListDisplay = new ReorderableList(serializedObject, _collectionFormattersProperty, true, true, true, true);
|
||||
_collectionFormattersListDisplay.onAddCallback = AppendNewCollectionFormatter;
|
||||
_collectionFormattersListDisplay.drawElementCallback = DrawCollectionFormatterInspector;
|
||||
_collectionFormattersListDisplay.drawHeaderCallback = DrawCollectionFormatterListHeader;
|
||||
}
|
||||
|
||||
private void CreateStyles()
|
||||
{
|
||||
if (!_initialisedStyles)
|
||||
{
|
||||
_initialisedStyles = true;
|
||||
|
||||
_centeredMiniLabel = new GUIStyle(EditorStyles.centeredGreyMiniLabel);
|
||||
_centeredMiniLabel.normal.textColor = EditorGUIUtility.isProSkin ? new Color(0.7f, 0.7f, 0.7f, 1) : new Color(0.3f, 0.3f, 0.3f, 1);
|
||||
|
||||
_centeredLabel = new GUIStyle(EditorStyles.label);
|
||||
_centeredLabel.alignment = TextAnchor.MiddleCenter;
|
||||
_centeredLabel.richText = true;
|
||||
|
||||
_centeredTextField = new GUIStyle(EditorStyles.textField);
|
||||
_centeredTextField.alignment = TextAnchor.MiddleCenter;
|
||||
}
|
||||
}
|
||||
|
||||
public override void OnInspectorGUI()
|
||||
{
|
||||
CreateStyles();
|
||||
serializedObject.Update();
|
||||
EditorHelpers.DrawHeader(Banner);
|
||||
|
||||
EditorGUILayout.LabelField(new GUIContent("UI", "Theme customisations for the Quantum Console UI."), EditorStyles.boldLabel);
|
||||
EditorGUILayout.PropertyField(_fontProperty, new GUIContent("Font", "The font to be used throughout the Quantum Console."));
|
||||
|
||||
EditorGUILayout.PropertyField(_panelMaterialProperty, new GUIContent("Panel Material", "The material to use in the UI panels. Leave null for default."));
|
||||
EditorGUILayout.PropertyField(_panelColorProperty, new GUIContent("Panel Color", "The color to use in the UI panels."));
|
||||
EditorGUILayout.Space();
|
||||
|
||||
EditorGUILayout.LabelField(new GUIContent("Colors", "Color customisation for various aspects of the Quantum Console."), EditorStyles.boldLabel);
|
||||
EditorGUILayout.PropertyField(_errorColorProperty, new GUIContent("Error Color", "The color to use when formatting errors in the console log."));
|
||||
EditorGUILayout.PropertyField(_warningColorProperty, new GUIContent("Warning Color", "The color to use when formatting warnings in the console log."));
|
||||
EditorGUILayout.PropertyField(_successColorProperty, new GUIContent("Success Color", "The color to use when formatting successful void commands."));
|
||||
EditorGUILayout.PropertyField(_selectedSuggestionColorProperty, new GUIContent("Selected Suggestion Color", "The color to use for the selected suggestion from the suggestion popup display."));
|
||||
EditorGUILayout.PropertyField(_suggestionColorProperty, new GUIContent("Suggestion Signature Color", "The color to use when displaying the paramater signature for suggested commands."));
|
||||
EditorGUILayout.PropertyField(_commandLogColorProperty, new GUIContent("Command Log Color", "The color to use when displaying logged commands in the console log."));
|
||||
EditorGUILayout.Space();
|
||||
|
||||
EditorGUILayout.LabelField(new GUIContent("Formatting", "Control various formatting within Quantum Console."), EditorStyles.boldLabel);
|
||||
EditorGUILayout.PropertyField(_timestampFormatProperty, new GUIContent("Timestamp Format", "The format to use when generating timestamps." +
|
||||
"\n{0} = Hour" +
|
||||
"\n{1} = Minute" +
|
||||
"\n{2} = Second"));
|
||||
EditorGUILayout.Space();
|
||||
|
||||
EditorGUILayout.LabelField(new GUIContent("Return Value Formatting", "Formatting options for the return serialization"), EditorStyles.boldLabel);
|
||||
EditorGUILayout.PropertyField(_defaultValueColorProperty, new GUIContent("Default Color", "The default color for return values"));
|
||||
_typeFormattersListDisplay.DoLayoutList();
|
||||
_collectionFormattersListDisplay.DoLayoutList();
|
||||
|
||||
serializedObject.ApplyModifiedProperties();
|
||||
}
|
||||
|
||||
private void DrawTypeFormatterInspector(Rect drawRect, int index, bool isActive, bool isFocused)
|
||||
{
|
||||
float nameWidth = 150f;
|
||||
drawRect.y += 2;
|
||||
|
||||
SerializedProperty currentTypeFormatter = _typeFormattersListDisplay.serializedProperty.GetArrayElementAtIndex(index);
|
||||
SerializedProperty colorProperty = currentTypeFormatter.FindPropertyRelative("Color");
|
||||
|
||||
string typeName = _themeInstance.TypeFormatters[index].Type.GetDisplayName();
|
||||
Rect labelRect = new Rect(drawRect.x, drawRect.y, nameWidth, EditorGUIUtility.singleLineHeight);
|
||||
Rect colorRect = new Rect(drawRect.x + nameWidth, drawRect.y, drawRect.width - nameWidth, EditorGUIUtility.singleLineHeight);
|
||||
EditorGUI.LabelField(labelRect, typeName);
|
||||
EditorGUI.PropertyField(colorRect, colorProperty, new GUIContent());
|
||||
}
|
||||
|
||||
private void DrawTypeFormatterListHeader(Rect drawRect)
|
||||
{
|
||||
EditorGUI.LabelField(new Rect(drawRect.x, drawRect.y, 150, drawRect.height), new GUIContent("Type Formatters", "The different colors that should be used for formatting different type returns."));
|
||||
EditorGUI.LabelField(new Rect((drawRect.x + drawRect.width) / 2 - 40, drawRect.y, 80, drawRect.height), _typeFormattersProperty.arraySize.ToString() + (_typeFormattersProperty.arraySize == 1 ? " Formatter" : " Formatters"), _centeredMiniLabel);
|
||||
}
|
||||
|
||||
private void AppendNewTypeFormatter(ReorderableList listTarget)
|
||||
{
|
||||
Action<string> SubmitCallback = (string data) =>
|
||||
{
|
||||
Type type = QuantumParser.ParseType(data);
|
||||
if (type == null) { throw new ArgumentException($"No type of name '{data}' could be found. Are you missing a namespace?"); }
|
||||
|
||||
Undo.RecordObject(_themeInstance, "Added a new Type Formatter");
|
||||
_themeInstance.TypeFormatters.Add(new TypeColorFormatter(type));
|
||||
EditorUtility.SetDirty(_themeInstance);
|
||||
};
|
||||
|
||||
PopupWindow.Show(new Rect(5, 5, 0, 0), new DataEntryPopup("Type Name", "Create Type Formatter", SubmitCallback));
|
||||
}
|
||||
|
||||
private void DrawCollectionFormatterInspector(Rect drawRect, int index, bool isActive, bool isFocused)
|
||||
{
|
||||
float itemWidth = 40f;
|
||||
float dataWidth = 35f;
|
||||
float padding = 5f;
|
||||
float endPadding = 10f;
|
||||
float nameWidth = drawRect.width - (6 * itemWidth + 3 * dataWidth + 5 * padding + endPadding);
|
||||
drawRect.y += 2;
|
||||
|
||||
SerializedProperty currentCollectionFormatter = _collectionFormattersListDisplay.serializedProperty.GetArrayElementAtIndex(index);
|
||||
SerializedProperty seperatorProperty = currentCollectionFormatter.FindPropertyRelative("SeperatorString");
|
||||
SerializedProperty leftScoperProperty = currentCollectionFormatter.FindPropertyRelative("LeftScoper");
|
||||
SerializedProperty rightScoperProperty = currentCollectionFormatter.FindPropertyRelative("RightScoper");
|
||||
|
||||
string typeName = _themeInstance.CollectionFormatters[index].Type.GetDisplayName();
|
||||
Rect rect = new Rect(drawRect.x, drawRect.y, nameWidth, EditorGUIUtility.singleLineHeight);
|
||||
EditorGUI.LabelField(rect, typeName);
|
||||
rect.x += nameWidth + padding;
|
||||
|
||||
Action<SerializedProperty, float> DrawTextField = (SerializedProperty prop, float width) =>
|
||||
{
|
||||
rect.width = width;
|
||||
prop.stringValue = EditorGUI.TextField(rect, new GUIContent(), prop.stringValue, _centeredTextField);
|
||||
rect.x += width + padding;
|
||||
};
|
||||
|
||||
Action<string, float> DrawLabelField = (string text, float width) =>
|
||||
{
|
||||
rect.width = width;
|
||||
EditorGUI.LabelField(rect, text, _centeredLabel);
|
||||
rect.x += width + padding;
|
||||
};
|
||||
|
||||
string highlightCol = EditorGUIUtility.isProSkin ? "#1fe035" : "#005209";
|
||||
string itemCol = EditorGUIUtility.isProSkin ? "#ff8280" : "#6A0301";
|
||||
string example = $"<b><color={highlightCol}>{leftScoperProperty.stringValue}</color></b>" +
|
||||
$"<color={itemCol}>item1</color><b><color={highlightCol}>{seperatorProperty.stringValue}</color></b>" +
|
||||
$"<color={itemCol}>item2</color><b><color={highlightCol}>{rightScoperProperty.stringValue}</color></b>";
|
||||
|
||||
DrawTextField(leftScoperProperty, dataWidth);
|
||||
DrawLabelField("item1", itemWidth);
|
||||
DrawTextField(seperatorProperty, dataWidth);
|
||||
DrawLabelField("item2", itemWidth);
|
||||
DrawTextField(rightScoperProperty, dataWidth);
|
||||
DrawLabelField("<b>=></b>", itemWidth * 1.5f);
|
||||
DrawLabelField(example, itemWidth * 2.5f);
|
||||
}
|
||||
|
||||
private void DrawCollectionFormatterListHeader(Rect drawRect)
|
||||
{
|
||||
EditorGUI.LabelField(new Rect(drawRect.x, drawRect.y, 150, drawRect.height), new GUIContent("Collection Formatters", "The different strings that should be used for seperating and enclosing collections when serialized."));
|
||||
EditorGUI.LabelField(new Rect((drawRect.x + drawRect.width) / 2 - 40, drawRect.y, 80, drawRect.height), _collectionFormattersProperty.arraySize.ToString() + (_collectionFormattersProperty.arraySize == 1 ? " Formatter" : " Formatters"), _centeredMiniLabel);
|
||||
}
|
||||
|
||||
private void AppendNewCollectionFormatter(ReorderableList listTarget)
|
||||
{
|
||||
Action<string> SubmitCallback = (string data) =>
|
||||
{
|
||||
Type type = QuantumParser.ParseType(data);
|
||||
if (type == null) { throw new ArgumentException($"No type of name '{data}' could be found. Are you missing a namespace?"); }
|
||||
if (!typeof(IEnumerable).IsAssignableFrom(type))
|
||||
{
|
||||
throw new ArgumentException("Collection type must implement IEnumerator");
|
||||
}
|
||||
|
||||
Undo.RecordObject(_themeInstance, "Added a new Collection Formatter");
|
||||
_themeInstance.CollectionFormatters.Add(new CollectionFormatter(type));
|
||||
EditorUtility.SetDirty(_themeInstance);
|
||||
};
|
||||
|
||||
PopupWindow.Show(new Rect(5, 5, 0, 0), new DataEntryPopup("Collection Type Name", "Create Collection Formatter", SubmitCallback));
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 3c958f403b85740698edbcc10c951bce
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences:
|
||||
- banner: {fileID: 2800000, guid: 0a00d33b88ebe3f4eb5dfb0d2a1c0726, type: 3}
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,8 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 248ef14759720fa4a800416d09dc3b23
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,23 @@
|
|||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
|
||||
namespace QFSW.QC.Editor.Tools
|
||||
{
|
||||
public static class PrefabUtil
|
||||
{
|
||||
public static void RecordPrefabInstancePropertyModificationsFullyRecursive(GameObject objRoot)
|
||||
{
|
||||
PrefabUtility.RecordPrefabInstancePropertyModifications(objRoot);
|
||||
foreach (Component comp in objRoot.GetComponents<Component>())
|
||||
{
|
||||
PrefabUtility.RecordPrefabInstancePropertyModifications(comp);
|
||||
}
|
||||
|
||||
for (int i = 0; i < objRoot.transform.childCount; i++)
|
||||
{
|
||||
Transform child = objRoot.transform.GetChild(i);
|
||||
RecordPrefabInstancePropertyModificationsFullyRecursive(child.gameObject);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 8efd6ec275d0caa46920e3c03f6e3925
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,14 @@
|
|||
{
|
||||
"name": "QFSW.QC.Editor.Tools",
|
||||
"references": [],
|
||||
"optionalUnityReferences": [],
|
||||
"includePlatforms": [
|
||||
"Editor"
|
||||
],
|
||||
"excludePlatforms": [],
|
||||
"allowUnsafeCode": false,
|
||||
"overrideReferences": false,
|
||||
"precompiledReferences": [],
|
||||
"autoReferenced": true,
|
||||
"defineConstraints": []
|
||||
}
|
|
@ -0,0 +1,7 @@
|
|||
fileFormatVersion: 2
|
||||
guid: a02547252a8685b458cb58325927f320
|
||||
AssemblyDefinitionImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,79 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text.RegularExpressions;
|
||||
using UnityEditor;
|
||||
|
||||
namespace QFSW.QC.Editor.Tools
|
||||
{
|
||||
public static class SymbolEditor
|
||||
{
|
||||
public static IEnumerable<T> AsEnumerable<T>(this T val)
|
||||
{
|
||||
yield return val;
|
||||
}
|
||||
|
||||
private static IEnumerable<BuildTargetGroup> GetPresentBuildTargetGroups()
|
||||
{
|
||||
foreach (BuildTarget target in (BuildTarget[])Enum.GetValues(typeof(BuildTarget)))
|
||||
{
|
||||
BuildTargetGroup group = BuildPipeline.GetBuildTargetGroup(target);
|
||||
if (BuildPipeline.IsBuildTargetSupported(group, target))
|
||||
{
|
||||
yield return group;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void AddSymbol(string symbol)
|
||||
{
|
||||
AddSymbols(symbol.AsEnumerable());
|
||||
}
|
||||
|
||||
public static void AddSymbols(IEnumerable<string> symbols)
|
||||
{
|
||||
AddSymbols(GetPresentBuildTargetGroups(), symbols);
|
||||
}
|
||||
|
||||
public static void AddSymbols(IEnumerable<BuildTargetGroup> groups, IEnumerable<string> symbols)
|
||||
{
|
||||
foreach (BuildTargetGroup group in groups)
|
||||
{
|
||||
string currentSymbols = PlayerSettings.GetScriptingDefineSymbolsForGroup(group);
|
||||
foreach (string symbol in symbols)
|
||||
{
|
||||
if (!currentSymbols.Contains(symbol))
|
||||
{
|
||||
currentSymbols = $"{currentSymbols};{symbol}";
|
||||
}
|
||||
}
|
||||
|
||||
PlayerSettings.SetScriptingDefineSymbolsForGroup(group, currentSymbols);
|
||||
}
|
||||
}
|
||||
|
||||
public static void RemoveSymbol(string symbol)
|
||||
{
|
||||
RemoveSymbols(symbol.AsEnumerable());
|
||||
}
|
||||
|
||||
public static void RemoveSymbols(IEnumerable<string> symbols)
|
||||
{
|
||||
RemoveSymbols(GetPresentBuildTargetGroups(), symbols);
|
||||
}
|
||||
|
||||
public static void RemoveSymbols(IEnumerable<BuildTargetGroup> groups, IEnumerable<string> symbols)
|
||||
{
|
||||
foreach (BuildTargetGroup group in groups)
|
||||
{
|
||||
string currentSymbols = PlayerSettings.GetScriptingDefineSymbolsForGroup(group);
|
||||
foreach (string symbol in symbols)
|
||||
{
|
||||
currentSymbols = Regex.Replace(currentSymbols, symbol, string.Empty);
|
||||
}
|
||||
|
||||
currentSymbols = string.Join(";", currentSymbols.Split(new char[] { ';' }, StringSplitOptions.RemoveEmptyEntries));
|
||||
PlayerSettings.SetScriptingDefineSymbolsForGroup(group, currentSymbols);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 1078e30699e62674ca299f95eb835efc
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,93 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using UnityEngine;
|
||||
|
||||
namespace QFSW.QC
|
||||
{
|
||||
/// <summary>
|
||||
/// Prevents the type from being loaded by an InjectionLoader
|
||||
/// </summary>
|
||||
[AttributeUsage(AttributeTargets.Class, Inherited = false)]
|
||||
public sealed class NoInjectAttribute : Attribute { }
|
||||
|
||||
/// <summary>
|
||||
/// Loads and instantiates instances of the injectable types.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The base type for the instances that will be injected.</typeparam>
|
||||
public class InjectionLoader<T>
|
||||
{
|
||||
private Type[] _injectableTypes;
|
||||
|
||||
/// <summary>
|
||||
/// Retrieves all of the injectable types.
|
||||
/// </summary>
|
||||
/// <param name="forceReload">Forces a reload of the types instead of using the cache.</param>
|
||||
/// <returns>The injectable types.</returns>
|
||||
public Type[] GetInjectableTypes(bool forceReload = false)
|
||||
{
|
||||
if (_injectableTypes == null || forceReload)
|
||||
{
|
||||
#if UNITY_2019_2_OR_NEWER && UNITY_EDITOR
|
||||
_injectableTypes = UnityEditor.TypeCache.GetTypesDerivedFrom<T>()
|
||||
.Where(type => !type.IsAbstract)
|
||||
.Where(type => !type.IsDefined(typeof(NoInjectAttribute), false))
|
||||
.ToArray();
|
||||
#else
|
||||
_injectableTypes = AppDomain.CurrentDomain.GetAssemblies()
|
||||
.SelectMany(assembly => assembly.GetTypes())
|
||||
.Where(type => typeof(T).IsAssignableFrom(type))
|
||||
.Where(type => !type.IsAbstract)
|
||||
.Where(type => !type.IsDefined(typeof(NoInjectAttribute), false))
|
||||
.ToArray();
|
||||
#endif
|
||||
}
|
||||
|
||||
return _injectableTypes;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates instances for all of the injectable types available.
|
||||
/// </summary>
|
||||
/// <param name="forceReload">Forces a reload of the types instead of using the cache.</param>
|
||||
/// <returns>The injectable instances.</returns>
|
||||
public IEnumerable<T> GetInjectedInstances(bool forceReload = false)
|
||||
{
|
||||
IEnumerable<Type> injectableTypes = GetInjectableTypes(forceReload);
|
||||
return GetInjectedInstances(injectableTypes);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates instances from a custom sequence of injectable types.
|
||||
/// </summary>
|
||||
/// <param name="injectableTypes">The types to create instances for.</param>
|
||||
/// <returns>The injectable instances.</returns>
|
||||
public IEnumerable<T> GetInjectedInstances(IEnumerable<Type> injectableTypes)
|
||||
{
|
||||
foreach (Type type in injectableTypes)
|
||||
{
|
||||
T instance = default;
|
||||
bool success = false;
|
||||
|
||||
try
|
||||
{
|
||||
instance = (T)Activator.CreateInstance(type);
|
||||
success = true;
|
||||
}
|
||||
catch (MissingMethodException)
|
||||
{
|
||||
Debug.LogError($"Could not load {typeof(T)} {type} as it is missing a public parameterless constructor.");
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Debug.LogException(e);
|
||||
}
|
||||
|
||||
if (success)
|
||||
{
|
||||
yield return instance;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 30b90f95d53dc6e4289d6ebadaaf342b
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,187 @@
|
|||
#if ENABLE_INPUT_SYSTEM && !ENABLE_LEGACY_INPUT_MANAGER
|
||||
#define NEW_INPUT
|
||||
using UnityEngine.InputSystem;
|
||||
using UnityEngine.InputSystem.Controls;
|
||||
#endif
|
||||
|
||||
using UnityEngine;
|
||||
|
||||
namespace QFSW.QC
|
||||
{
|
||||
public static class InputHelper
|
||||
{
|
||||
private static bool IsKeySupported(KeyCode key)
|
||||
{
|
||||
#if NEW_INPUT
|
||||
bool KeyExists()
|
||||
{
|
||||
Key keyConverted = key.ToKey();
|
||||
foreach (KeyControl k in Keyboard.current.allKeys)
|
||||
{
|
||||
if (k.keyCode == keyConverted)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return key != KeyCode.None
|
||||
&& Keyboard.current != null
|
||||
&& KeyExists();
|
||||
#else
|
||||
return true;
|
||||
#endif
|
||||
}
|
||||
|
||||
public static bool GetKey(KeyCode key)
|
||||
{
|
||||
#if NEW_INPUT
|
||||
return IsKeySupported(key)
|
||||
&& Keyboard.current[key.ToKey()].isPressed;
|
||||
|
||||
#else
|
||||
return Input.GetKey(key);
|
||||
#endif
|
||||
}
|
||||
|
||||
public static bool GetKeyDown(KeyCode key)
|
||||
{
|
||||
#if NEW_INPUT
|
||||
return IsKeySupported(key)
|
||||
&& Keyboard.current[key.ToKey()].wasPressedThisFrame;
|
||||
#else
|
||||
return Input.GetKeyDown(key);
|
||||
#endif
|
||||
}
|
||||
|
||||
public static bool GetKeyUp(KeyCode key)
|
||||
{
|
||||
#if NEW_INPUT
|
||||
return IsKeySupported(key)
|
||||
&& Keyboard.current[key.ToKey()].wasReleasedThisFrame;
|
||||
#else
|
||||
return Input.GetKeyDown(key);
|
||||
#endif
|
||||
}
|
||||
|
||||
#if NEW_INPUT
|
||||
private static Key ToKey(this KeyCode key)
|
||||
{
|
||||
switch (key)
|
||||
{
|
||||
case KeyCode.None: return Key.None;
|
||||
case KeyCode.Space: return Key.Space;
|
||||
case KeyCode.Return: return Key.Enter;
|
||||
case KeyCode.Tab: return Key.Tab;
|
||||
case KeyCode.BackQuote: return Key.Backquote;
|
||||
case KeyCode.Quote: return Key.Quote;
|
||||
case KeyCode.Semicolon: return Key.Semicolon;
|
||||
case KeyCode.Comma: return Key.Comma;
|
||||
case KeyCode.Period: return Key.Period;
|
||||
case KeyCode.Slash: return Key.Slash;
|
||||
case KeyCode.Backslash: return Key.Backslash;
|
||||
case KeyCode.LeftBracket: return Key.LeftBracket;
|
||||
case KeyCode.RightBracket: return Key.RightBracket;
|
||||
case KeyCode.Minus: return Key.Minus;
|
||||
case KeyCode.Equals: return Key.Equals;
|
||||
case KeyCode.A: return Key.A;
|
||||
case KeyCode.B: return Key.B;
|
||||
case KeyCode.C: return Key.C;
|
||||
case KeyCode.D: return Key.D;
|
||||
case KeyCode.E: return Key.E;
|
||||
case KeyCode.F: return Key.F;
|
||||
case KeyCode.G: return Key.G;
|
||||
case KeyCode.H: return Key.H;
|
||||
case KeyCode.I: return Key.I;
|
||||
case KeyCode.J: return Key.J;
|
||||
case KeyCode.K: return Key.K;
|
||||
case KeyCode.L: return Key.L;
|
||||
case KeyCode.M: return Key.M;
|
||||
case KeyCode.N: return Key.N;
|
||||
case KeyCode.O: return Key.O;
|
||||
case KeyCode.P: return Key.P;
|
||||
case KeyCode.Q: return Key.Q;
|
||||
case KeyCode.R: return Key.R;
|
||||
case KeyCode.S: return Key.S;
|
||||
case KeyCode.T: return Key.T;
|
||||
case KeyCode.U: return Key.U;
|
||||
case KeyCode.V: return Key.V;
|
||||
case KeyCode.W: return Key.W;
|
||||
case KeyCode.X: return Key.X;
|
||||
case KeyCode.Y: return Key.Y;
|
||||
case KeyCode.Z: return Key.Z;
|
||||
case KeyCode.Alpha1: return Key.Digit1;
|
||||
case KeyCode.Alpha2: return Key.Digit2;
|
||||
case KeyCode.Alpha3: return Key.Digit3;
|
||||
case KeyCode.Alpha4: return Key.Digit4;
|
||||
case KeyCode.Alpha5: return Key.Digit5;
|
||||
case KeyCode.Alpha6: return Key.Digit6;
|
||||
case KeyCode.Alpha7: return Key.Digit7;
|
||||
case KeyCode.Alpha8: return Key.Digit8;
|
||||
case KeyCode.Alpha9: return Key.Digit9;
|
||||
case KeyCode.Alpha0: return Key.Digit0;
|
||||
case KeyCode.LeftShift: return Key.LeftShift;
|
||||
case KeyCode.RightShift: return Key.RightShift;
|
||||
case KeyCode.LeftAlt: return Key.LeftAlt;
|
||||
case KeyCode.RightAlt: return Key.RightAlt;
|
||||
case KeyCode.AltGr: return Key.AltGr;
|
||||
case KeyCode.LeftControl: return Key.LeftCtrl;
|
||||
case KeyCode.RightControl: return Key.RightCtrl;
|
||||
case KeyCode.LeftWindows: return Key.LeftWindows;
|
||||
case KeyCode.RightWindows: return Key.RightWindows;
|
||||
case KeyCode.LeftCommand: return Key.LeftCommand;
|
||||
case KeyCode.RightCommand: return Key.RightCommand;
|
||||
case KeyCode.Escape: return Key.Escape;
|
||||
case KeyCode.LeftArrow: return Key.LeftArrow;
|
||||
case KeyCode.RightArrow: return Key.RightArrow;
|
||||
case KeyCode.UpArrow: return Key.UpArrow;
|
||||
case KeyCode.DownArrow: return Key.DownArrow;
|
||||
case KeyCode.Backspace: return Key.Backspace;
|
||||
case KeyCode.PageDown: return Key.PageDown;
|
||||
case KeyCode.PageUp: return Key.PageUp;
|
||||
case KeyCode.Home: return Key.Home;
|
||||
case KeyCode.End: return Key.End;
|
||||
case KeyCode.Insert: return Key.Insert;
|
||||
case KeyCode.Delete: return Key.Delete;
|
||||
case KeyCode.CapsLock: return Key.CapsLock;
|
||||
case KeyCode.Numlock: return Key.NumLock;
|
||||
case KeyCode.Print: return Key.PrintScreen;
|
||||
case KeyCode.ScrollLock: return Key.ScrollLock;
|
||||
case KeyCode.Pause: return Key.Pause;
|
||||
case KeyCode.KeypadEnter: return Key.NumpadEnter;
|
||||
case KeyCode.KeypadDivide: return Key.NumpadDivide;
|
||||
case KeyCode.KeypadMultiply: return Key.NumpadMultiply;
|
||||
case KeyCode.KeypadPlus: return Key.NumpadPlus;
|
||||
case KeyCode.KeypadMinus: return Key.NumpadMinus;
|
||||
case KeyCode.KeypadPeriod: return Key.NumpadPeriod;
|
||||
case KeyCode.KeypadEquals: return Key.NumpadEquals;
|
||||
case KeyCode.Keypad0: return Key.Numpad0;
|
||||
case KeyCode.Keypad1: return Key.Numpad1;
|
||||
case KeyCode.Keypad2: return Key.Numpad2;
|
||||
case KeyCode.Keypad3: return Key.Numpad3;
|
||||
case KeyCode.Keypad4: return Key.Numpad4;
|
||||
case KeyCode.Keypad5: return Key.Numpad5;
|
||||
case KeyCode.Keypad6: return Key.Numpad6;
|
||||
case KeyCode.Keypad7: return Key.Numpad7;
|
||||
case KeyCode.Keypad8: return Key.Numpad8;
|
||||
case KeyCode.Keypad9: return Key.Numpad9;
|
||||
case KeyCode.F1: return Key.F1;
|
||||
case KeyCode.F2: return Key.F2;
|
||||
case KeyCode.F3: return Key.F3;
|
||||
case KeyCode.F4: return Key.F4;
|
||||
case KeyCode.F5: return Key.F5;
|
||||
case KeyCode.F6: return Key.F6;
|
||||
case KeyCode.F7: return Key.F7;
|
||||
case KeyCode.F8: return Key.F8;
|
||||
case KeyCode.F9: return Key.F9;
|
||||
case KeyCode.F10: return Key.F10;
|
||||
case KeyCode.F11: return Key.F11;
|
||||
case KeyCode.F12: return Key.F12;
|
||||
default: return Key.None;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 735a8f6b5412bfc40882f5f856dfe9f9
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,8 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 47e7833318a87461886e1eb355a9c7bb
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,43 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Reflection;
|
||||
|
||||
namespace QFSW.QC.Internal
|
||||
{
|
||||
internal class CustomParameter : ParameterInfo
|
||||
{
|
||||
private readonly ParameterInfo _internalParameter;
|
||||
private readonly Type _typeOverride;
|
||||
private readonly string _nameOverride;
|
||||
|
||||
public CustomParameter(ParameterInfo internalParameter, Type typeOverride, string nameOverride)
|
||||
{
|
||||
_typeOverride = typeOverride;
|
||||
_nameOverride = nameOverride;
|
||||
_internalParameter = internalParameter;
|
||||
}
|
||||
|
||||
public CustomParameter(ParameterInfo internalParameter, string nameOverride) : this(internalParameter, internalParameter.ParameterType, nameOverride) { }
|
||||
|
||||
public override Type ParameterType { get { return _typeOverride; } }
|
||||
public override string Name { get { return _nameOverride; } }
|
||||
|
||||
public override ParameterAttributes Attributes { get { return _internalParameter.Attributes; } }
|
||||
public override object DefaultValue { get { return _internalParameter.DefaultValue; } }
|
||||
public override bool Equals(object obj) { return _internalParameter.Equals(obj); }
|
||||
public override IEnumerable<CustomAttributeData> CustomAttributes { get { return _internalParameter.CustomAttributes; } }
|
||||
public override object[] GetCustomAttributes(bool inherit) { return _internalParameter.GetCustomAttributes(inherit); }
|
||||
public override object[] GetCustomAttributes(Type attributeType, bool inherit) { return _internalParameter.GetCustomAttributes(attributeType, inherit); }
|
||||
public override IList<CustomAttributeData> GetCustomAttributesData() { return _internalParameter.GetCustomAttributesData(); }
|
||||
public override int GetHashCode() { return _internalParameter.GetHashCode(); }
|
||||
public override Type[] GetOptionalCustomModifiers() { return _internalParameter.GetOptionalCustomModifiers(); }
|
||||
public override Type[] GetRequiredCustomModifiers() { return _internalParameter.GetRequiredCustomModifiers(); }
|
||||
public override bool HasDefaultValue => _internalParameter.HasDefaultValue;
|
||||
public override bool IsDefined(Type attributeType, bool inherit) { return _internalParameter.IsDefined(attributeType, inherit); }
|
||||
public override MemberInfo Member { get { return _internalParameter.Member; } }
|
||||
public override int MetadataToken { get { return _internalParameter.MetadataToken; } }
|
||||
public override int Position { get { return _internalParameter.Position; } }
|
||||
public override object RawDefaultValue { get { return _internalParameter.RawDefaultValue; } }
|
||||
public override string ToString() { return _internalParameter.ToString(); }
|
||||
}
|
||||
}
|
|
@ -0,0 +1,13 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 9e07451b78498b4408061ec6a2cc95dd
|
||||
timeCreated: 1543091613
|
||||
licenseType: Store
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,36 @@
|
|||
using System;
|
||||
using System.Reflection;
|
||||
|
||||
namespace QFSW.QC.Internal
|
||||
{
|
||||
internal class FieldAutoMethod : FieldMethod
|
||||
{
|
||||
public enum AccessType
|
||||
{
|
||||
Read = 0,
|
||||
Write = 1
|
||||
}
|
||||
|
||||
private readonly AccessType _accessType;
|
||||
|
||||
public FieldAutoMethod(FieldInfo fieldInfo, AccessType accessType) : base(fieldInfo)
|
||||
{
|
||||
_accessType = accessType;
|
||||
if (_accessType == AccessType.Read)
|
||||
{
|
||||
if (_fieldInfo.IsStatic) { _internalDelegate = (Func<FieldInfo, object>)_StaticReader; }
|
||||
else { _internalDelegate = (Func<object, object>)_fieldInfo.GetValue; }
|
||||
_parameters = Array.Empty<ParameterInfo>();
|
||||
}
|
||||
else
|
||||
{
|
||||
if (_fieldInfo.IsStatic) { _internalDelegate = (Action<FieldInfo, object>)_StaticWriter; }
|
||||
else { _internalDelegate = (Action<object, object>)_fieldInfo.SetValue; }
|
||||
_parameters = new ParameterInfo[] { new CustomParameter(_internalDelegate.Method.GetParameters()[1], _fieldInfo.FieldType, "value") };
|
||||
}
|
||||
}
|
||||
|
||||
private static object _StaticReader(FieldInfo field) { return field.GetValue(null); }
|
||||
private static void _StaticWriter(FieldInfo field, object value) { field.SetValue(null, value); }
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 4817e6908a5c544ab88c69cd27c68a41
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,57 @@
|
|||
using QFSW.QC.Utilities;
|
||||
using System;
|
||||
using System.Globalization;
|
||||
using System.Reflection;
|
||||
|
||||
namespace QFSW.QC.Internal
|
||||
{
|
||||
internal class FieldDelegateMethod : FieldMethod
|
||||
{
|
||||
public FieldDelegateMethod(FieldInfo fieldInfo) : base(fieldInfo)
|
||||
{
|
||||
if (!_fieldInfo.IsStrongDelegate())
|
||||
{
|
||||
throw new ArgumentException("Invalid delegate type.", nameof(fieldInfo));
|
||||
}
|
||||
|
||||
if (_fieldInfo.IsStatic)
|
||||
{
|
||||
_internalDelegate = (Func<FieldInfo, object[], object>)StaticInvoker;
|
||||
}
|
||||
else
|
||||
{
|
||||
_internalDelegate = (Func<object, FieldInfo, object[], object>)NonStaticInvoker;
|
||||
}
|
||||
|
||||
_parameters = _fieldInfo.FieldType.GetMethod("Invoke").GetParameters();
|
||||
for (int i = 0; i < _parameters.Length; i++)
|
||||
{
|
||||
_parameters[i] = new CustomParameter(_parameters[i], $"arg{i}");
|
||||
}
|
||||
}
|
||||
|
||||
public override object Invoke(object obj, BindingFlags invokeAttr, Binder binder, object[] parameters, CultureInfo culture)
|
||||
{
|
||||
object[] realParameters = new object[_internalDelegate.Method.GetParameters().Length];
|
||||
if (realParameters.Length < 2) { throw new Exception("FieldDelegateMethod's internal delegate must contain at least two paramaters."); }
|
||||
if (!IsStatic) { realParameters[0] = obj; }
|
||||
realParameters[realParameters.Length - 2] = _fieldInfo;
|
||||
realParameters[realParameters.Length - 1] = parameters;
|
||||
return _internalDelegate.DynamicInvoke(realParameters);
|
||||
}
|
||||
|
||||
private static object StaticInvoker(FieldInfo field, params object[] args)
|
||||
{
|
||||
Delegate del = (Delegate)field.GetValue(null);
|
||||
if (del != null) { return del.DynamicInvoke(args); }
|
||||
else { throw new Exception("Delegate was invalid and could not be invoked."); }
|
||||
}
|
||||
|
||||
private object NonStaticInvoker(object obj, FieldInfo field, params object[] args)
|
||||
{
|
||||
Delegate del = (Delegate)field.GetValue(obj);
|
||||
if (del != null) { return del.DynamicInvoke(args); }
|
||||
else { throw new Exception("Delegate was invalid and could not be invoked."); }
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,13 @@
|
|||
fileFormatVersion: 2
|
||||
guid: b9425c6d4746d884f9a82b6a9ba522f7
|
||||
timeCreated: 1543091933
|
||||
licenseType: Store
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,42 @@
|
|||
using System;
|
||||
using System.Globalization;
|
||||
using System.Reflection;
|
||||
|
||||
namespace QFSW.QC.Internal
|
||||
{
|
||||
internal abstract class FieldMethod : MethodInfo
|
||||
{
|
||||
protected readonly FieldInfo _fieldInfo;
|
||||
protected Delegate _internalDelegate;
|
||||
protected ParameterInfo[] _parameters;
|
||||
|
||||
public FieldMethod(FieldInfo fieldInfo) { _fieldInfo = fieldInfo; }
|
||||
|
||||
public override object Invoke(object obj, BindingFlags invokeAttr, Binder binder, object[] parameters, CultureInfo culture)
|
||||
{
|
||||
object[] realParameters = new object[parameters.Length + 1];
|
||||
if (IsStatic) { realParameters[0] = _fieldInfo; }
|
||||
else { realParameters[0] = obj; }
|
||||
Array.Copy(parameters, 0, realParameters, 1, parameters.Length);
|
||||
return _internalDelegate.DynamicInvoke(realParameters);
|
||||
}
|
||||
|
||||
public override ParameterInfo[] GetParameters()
|
||||
{
|
||||
return _parameters;
|
||||
}
|
||||
|
||||
public override string Name { get { return _fieldInfo.Name; } }
|
||||
public override Type DeclaringType { get { return _fieldInfo.DeclaringType; } }
|
||||
public override Type ReflectedType { get { { return _fieldInfo.ReflectedType; } } }
|
||||
public override object[] GetCustomAttributes(bool inherit) { return _fieldInfo.GetCustomAttributes(inherit); }
|
||||
public override object[] GetCustomAttributes(Type attributeType, bool inherit) { return _fieldInfo.GetCustomAttributes(attributeType, inherit); }
|
||||
|
||||
public override MethodAttributes Attributes { get { return _internalDelegate.Method.Attributes; } }
|
||||
public override RuntimeMethodHandle MethodHandle { get { return _internalDelegate.Method.MethodHandle; } }
|
||||
public override ICustomAttributeProvider ReturnTypeCustomAttributes { get { return _internalDelegate.Method.ReturnTypeCustomAttributes; } }
|
||||
public override MethodInfo GetBaseDefinition() { return _internalDelegate.Method.GetBaseDefinition(); }
|
||||
public override MethodImplAttributes GetMethodImplementationFlags() { return _internalDelegate.Method.GetMethodImplementationFlags(); }
|
||||
public override bool IsDefined(Type attributeType, bool inherit) { return _internalDelegate.Method.IsDefined(attributeType, inherit); }
|
||||
}
|
||||
}
|
|
@ -0,0 +1,13 @@
|
|||
fileFormatVersion: 2
|
||||
guid: bc3a8d5d7bf0b284fb3e38019fb1c469
|
||||
timeCreated: 1543091424
|
||||
licenseType: Store
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,160 @@
|
|||
using QFSW.QC.Comparators;
|
||||
using QFSW.QC.Utilities;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using UnityEngine;
|
||||
using Object = UnityEngine.Object;
|
||||
|
||||
namespace QFSW.QC
|
||||
{
|
||||
public static class InvocationTargetFactory
|
||||
{
|
||||
private static readonly Dictionary<(MonoTargetType, Type), object> TargetCache = new Dictionary<(MonoTargetType, Type), object>();
|
||||
|
||||
public static IEnumerable<T> FindTargets<T>(MonoTargetType method) where T : MonoBehaviour
|
||||
{
|
||||
foreach (object target in FindTargets(typeof(T), method))
|
||||
{
|
||||
yield return target as T;
|
||||
}
|
||||
}
|
||||
|
||||
public static IEnumerable<object> FindTargets(Type classType, MonoTargetType method)
|
||||
{
|
||||
switch (method)
|
||||
{
|
||||
case MonoTargetType.Single:
|
||||
{
|
||||
Object target = Object.FindObjectOfType(classType);
|
||||
return target == null ? Enumerable.Empty<object>() : target.Yield();
|
||||
}
|
||||
case MonoTargetType.SingleInactive:
|
||||
{
|
||||
return WrapSingleCached(classType, method, type =>
|
||||
{
|
||||
return Resources.FindObjectsOfTypeAll(type)
|
||||
.FirstOrDefault(x => !x.hideFlags.HasFlag(HideFlags.HideInHierarchy));
|
||||
});
|
||||
}
|
||||
case MonoTargetType.All:
|
||||
{
|
||||
return Object.FindObjectsOfType(classType)
|
||||
.OrderBy(x => x.name, new AlphanumComparator());
|
||||
}
|
||||
case MonoTargetType.AllInactive:
|
||||
{
|
||||
return Resources.FindObjectsOfTypeAll(classType)
|
||||
.Where(x => !x.hideFlags.HasFlag(HideFlags.HideInHierarchy))
|
||||
.OrderBy(x => x.name, new AlphanumComparator());
|
||||
}
|
||||
case MonoTargetType.Registry:
|
||||
{
|
||||
return QuantumRegistry.GetRegistryContents(classType);
|
||||
}
|
||||
case MonoTargetType.Singleton:
|
||||
{
|
||||
return GetSingletonInstance(classType).Yield();
|
||||
}
|
||||
default:
|
||||
{
|
||||
throw new ArgumentException($"Unsupported MonoTargetType {method}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static IEnumerable<object> WrapSingleCached(Type classType, MonoTargetType method, Func<Type, object> targetFinder)
|
||||
{
|
||||
if (!TargetCache.TryGetValue((method, classType), out object target) || target as Object == null)
|
||||
{
|
||||
target = targetFinder(classType);
|
||||
TargetCache[(method, classType)] = target;
|
||||
}
|
||||
|
||||
return target == null ? Enumerable.Empty<object>() : target.Yield();
|
||||
}
|
||||
|
||||
public static object InvokeOnTargets(MethodInfo invokingMethod, IEnumerable<object> targets, object[] data)
|
||||
{
|
||||
int returnCount = 0;
|
||||
int invokeCount = 0;
|
||||
Dictionary<object, object> resultsParts = new Dictionary<object, object>();
|
||||
|
||||
foreach (object target in targets)
|
||||
{
|
||||
invokeCount++;
|
||||
object result = invokingMethod.Invoke(target, data);
|
||||
|
||||
if (result != null)
|
||||
{
|
||||
resultsParts.Add(target, result);
|
||||
returnCount++;
|
||||
}
|
||||
}
|
||||
|
||||
if (returnCount > 1)
|
||||
{
|
||||
return resultsParts;
|
||||
}
|
||||
|
||||
if (returnCount == 1)
|
||||
{
|
||||
return resultsParts.Values.First();
|
||||
}
|
||||
|
||||
if (invokeCount == 0)
|
||||
{
|
||||
string typeName = invokingMethod.DeclaringType.GetDisplayName();
|
||||
throw new Exception($"Could not invoke the command because no objects of type {typeName} could be found.");
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private static string FormatInvocationMessage(int invocationCount, object lastTarget = null)
|
||||
{
|
||||
switch (invocationCount)
|
||||
{
|
||||
case 0:
|
||||
throw new Exception("No targets could be found");
|
||||
case 1:
|
||||
{
|
||||
string name;
|
||||
if (lastTarget is Object obj)
|
||||
{
|
||||
name = obj.name;
|
||||
}
|
||||
else
|
||||
{
|
||||
name = lastTarget?.ToString();
|
||||
}
|
||||
|
||||
return $"> Invoked on {name}";
|
||||
}
|
||||
default:
|
||||
return $"> Invoked on {invocationCount} targets";
|
||||
}
|
||||
}
|
||||
|
||||
private static object GetSingletonInstance(Type classType)
|
||||
{
|
||||
if (QuantumRegistry.GetRegistrySize(classType) > 0)
|
||||
{
|
||||
return QuantumRegistry.GetRegistryContents(classType).First();
|
||||
}
|
||||
|
||||
object target = CreateCommandSingletonInstance(classType);
|
||||
QuantumRegistry.RegisterObject(classType, target);
|
||||
|
||||
return target;
|
||||
}
|
||||
|
||||
private static Component CreateCommandSingletonInstance(Type classType)
|
||||
{
|
||||
GameObject obj = new GameObject($"{classType}Singleton");
|
||||
Object.DontDestroyOnLoad(obj);
|
||||
return obj.AddComponent(classType);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: bc29296dcdd167042819ecace7ab214a
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,3 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 048bc3796092478d8319d7d1054a547d
|
||||
timeCreated: 1615081377
|
|
@ -0,0 +1,11 @@
|
|||
using UnityEngine;
|
||||
|
||||
namespace QFSW.QC
|
||||
{
|
||||
public interface ILog
|
||||
{
|
||||
string Text { get; }
|
||||
LogType Type { get; }
|
||||
bool NewLine { get; }
|
||||
}
|
||||
}
|
|
@ -0,0 +1,3 @@
|
|||
fileFormatVersion: 2
|
||||
guid: e5def4ecf09b4133b054e98f9afcc5c8
|
||||
timeCreated: 1615116599
|
|
@ -0,0 +1,12 @@
|
|||
namespace QFSW.QC
|
||||
{
|
||||
public interface ILogQueue
|
||||
{
|
||||
int MaxStoredLogs { get; set; }
|
||||
bool IsEmpty { get; }
|
||||
|
||||
void QueueLog(ILog log);
|
||||
bool TryDequeue(out ILog log);
|
||||
void Clear();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,3 @@
|
|||
fileFormatVersion: 2
|
||||
guid: b76bcf3d7eaa412cb2428e464882ed89
|
||||
timeCreated: 1615123713
|
|
@ -0,0 +1,17 @@
|
|||
using System.Collections.Generic;
|
||||
|
||||
namespace QFSW.QC
|
||||
{
|
||||
public interface ILogStorage
|
||||
{
|
||||
int MaxStoredLogs { get; set; }
|
||||
IReadOnlyList<ILog> Logs { get; }
|
||||
|
||||
void AddLog(ILog log);
|
||||
void RemoveLog();
|
||||
void Clear();
|
||||
|
||||
string GetLogString();
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,3 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 859434497f964d328b18530b1230d97f
|
||||
timeCreated: 1615116625
|
|
@ -0,0 +1,18 @@
|
|||
using UnityEngine;
|
||||
|
||||
namespace QFSW.QC
|
||||
{
|
||||
public readonly struct Log : ILog
|
||||
{
|
||||
public string Text { get; }
|
||||
public LogType Type { get; }
|
||||
public bool NewLine { get; }
|
||||
|
||||
public Log(string text, LogType type = LogType.Log, bool newLine = true)
|
||||
{
|
||||
Text = text;
|
||||
Type = type;
|
||||
NewLine = newLine;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
fileFormatVersion: 2
|
||||
guid: f183a6a7c8672b9448d3c1023b68df30
|
||||
timeCreated: 1554340584
|
||||
licenseType: Store
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,36 @@
|
|||
using System.Collections.Concurrent;
|
||||
|
||||
namespace QFSW.QC
|
||||
{
|
||||
public class LogQueue : ILogQueue
|
||||
{
|
||||
private readonly ConcurrentQueue<ILog> _queuedLogs = new ConcurrentQueue<ILog>();
|
||||
|
||||
public int MaxStoredLogs { get; set; }
|
||||
public bool IsEmpty => _queuedLogs.IsEmpty;
|
||||
|
||||
public LogQueue(int maxStoredLogs = -1)
|
||||
{
|
||||
MaxStoredLogs = maxStoredLogs;
|
||||
}
|
||||
|
||||
public void QueueLog(ILog log)
|
||||
{
|
||||
_queuedLogs.Enqueue(log);
|
||||
if (MaxStoredLogs > 0 && _queuedLogs.Count > MaxStoredLogs)
|
||||
{
|
||||
_queuedLogs.TryDequeue(out _);
|
||||
}
|
||||
}
|
||||
|
||||
public bool TryDequeue(out ILog log)
|
||||
{
|
||||
return _queuedLogs.TryDequeue(out log);
|
||||
}
|
||||
|
||||
public void Clear()
|
||||
{
|
||||
while (TryDequeue(out ILog _)) { }
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,3 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 20c64958e7fb4ef6a8089b2cdb9e651a
|
||||
timeCreated: 1615123680
|
|
@ -0,0 +1,91 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using UnityEngine;
|
||||
|
||||
namespace QFSW.QC
|
||||
{
|
||||
public class LogStorage : ILogStorage
|
||||
{
|
||||
private readonly List<ILog> _consoleLogs = new List<ILog>(10);
|
||||
private readonly StringBuilder _logTraceBuilder = new StringBuilder(2048);
|
||||
|
||||
public int MaxStoredLogs { get; set; }
|
||||
public IReadOnlyList<ILog> Logs => _consoleLogs;
|
||||
|
||||
public LogStorage(int maxStoredLogs = -1)
|
||||
{
|
||||
MaxStoredLogs = maxStoredLogs;
|
||||
}
|
||||
|
||||
public void AddLog(ILog log)
|
||||
{
|
||||
_consoleLogs.Add(log);
|
||||
|
||||
int logLength = _logTraceBuilder.Length + log.Text.Length;
|
||||
if (log.NewLine && _logTraceBuilder.Length > 0)
|
||||
{
|
||||
logLength += Environment.NewLine.Length;
|
||||
}
|
||||
|
||||
if (MaxStoredLogs > 0)
|
||||
{
|
||||
while (_consoleLogs.Count > MaxStoredLogs)
|
||||
{
|
||||
int junkLength = _consoleLogs[0].Text.Length;
|
||||
if (_consoleLogs.Count > 1 &&_consoleLogs[1].NewLine)
|
||||
{
|
||||
junkLength += Environment.NewLine.Length;
|
||||
}
|
||||
junkLength = Mathf.Min(junkLength, _logTraceBuilder.Length);
|
||||
logLength -= junkLength;
|
||||
|
||||
_logTraceBuilder.Remove(0, junkLength);
|
||||
_consoleLogs.RemoveAt(0);
|
||||
}
|
||||
}
|
||||
|
||||
int capacity = _logTraceBuilder.Capacity;
|
||||
while (capacity < logLength)
|
||||
{
|
||||
capacity *= 2;
|
||||
}
|
||||
|
||||
_logTraceBuilder.EnsureCapacity(capacity);
|
||||
|
||||
if (log.NewLine && _logTraceBuilder.Length > 0)
|
||||
{
|
||||
_logTraceBuilder.Append(Environment.NewLine);
|
||||
}
|
||||
_logTraceBuilder.Append(log.Text);
|
||||
}
|
||||
|
||||
public void RemoveLog()
|
||||
{
|
||||
if (_consoleLogs.Count > 0)
|
||||
{
|
||||
ILog log = _consoleLogs[_consoleLogs.Count - 1];
|
||||
_consoleLogs.RemoveAt(_consoleLogs.Count - 1);
|
||||
|
||||
int removeLength = log.Text.Length;
|
||||
if (log.NewLine && _consoleLogs.Count > 0)
|
||||
{
|
||||
removeLength += Environment.NewLine.Length;
|
||||
}
|
||||
|
||||
_logTraceBuilder.Remove(_logTraceBuilder.Length - removeLength, removeLength);
|
||||
}
|
||||
}
|
||||
|
||||
public void Clear()
|
||||
{
|
||||
_consoleLogs.Clear();
|
||||
_logTraceBuilder.Length = 0;
|
||||
}
|
||||
|
||||
public string GetLogString()
|
||||
{
|
||||
return _logTraceBuilder.ToString();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,3 @@
|
|||
fileFormatVersion: 2
|
||||
guid: d0b5e8fa829c491eb694d1dfc7a1842a
|
||||
timeCreated: 1615081378
|
|
@ -0,0 +1,14 @@
|
|||
namespace QFSW.QC
|
||||
{
|
||||
/// <summary>
|
||||
/// Thresholds for log severities.
|
||||
/// </summary>
|
||||
public enum LoggingThreshold
|
||||
{
|
||||
Never = 0,
|
||||
Exception = 1,
|
||||
Error = 2,
|
||||
Warning = 3,
|
||||
Always = 4
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: e1deb81bd619957488a2d1d13c0d08d0
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,51 @@
|
|||
using UnityEngine;
|
||||
using UnityEngine.Serialization;
|
||||
|
||||
namespace QFSW.QC
|
||||
{
|
||||
[System.Serializable]
|
||||
public struct ModifierKeyCombo
|
||||
{
|
||||
[FormerlySerializedAs("key")]
|
||||
public KeyCode Key;
|
||||
[FormerlySerializedAs("ctrl")]
|
||||
public bool Ctrl;
|
||||
[FormerlySerializedAs("alt")]
|
||||
public bool Alt;
|
||||
[FormerlySerializedAs("shift")]
|
||||
public bool Shift;
|
||||
|
||||
public bool ModifiersActive
|
||||
{
|
||||
get
|
||||
{
|
||||
bool ctrlDown = !Ctrl ^
|
||||
(InputHelper.GetKey(KeyCode.LeftControl) ||
|
||||
InputHelper.GetKey(KeyCode.RightControl) ||
|
||||
InputHelper.GetKey(KeyCode.LeftCommand) ||
|
||||
InputHelper.GetKey(KeyCode.RightCommand));
|
||||
|
||||
bool altDown = !Alt ^ (InputHelper.GetKey(KeyCode.LeftAlt) || InputHelper.GetKey(KeyCode.RightAlt));
|
||||
bool shiftDown =
|
||||
!Shift ^ (InputHelper.GetKey(KeyCode.LeftShift) || InputHelper.GetKey(KeyCode.RightShift));
|
||||
|
||||
return ctrlDown && altDown && shiftDown;
|
||||
}
|
||||
}
|
||||
|
||||
public bool IsHeld()
|
||||
{
|
||||
return ModifiersActive && InputHelper.GetKey(Key);
|
||||
}
|
||||
|
||||
public bool IsPressed()
|
||||
{
|
||||
return ModifiersActive && InputHelper.GetKeyDown(Key);
|
||||
}
|
||||
|
||||
public static implicit operator ModifierKeyCombo(KeyCode key)
|
||||
{
|
||||
return new ModifierKeyCombo { Key = key };
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 60f8d052d71b77a47b602bb7b96e02d5
|
||||
timeCreated: 1541125662
|
||||
licenseType: Store
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,39 @@
|
|||
namespace QFSW.QC
|
||||
{
|
||||
/// <summary>
|
||||
/// Determines the target type for non static MonoBehaviour commands.
|
||||
/// </summary>
|
||||
public enum MonoTargetType
|
||||
{
|
||||
/// <summary>
|
||||
/// Targets the first instance found of the MonoBehaviour.
|
||||
/// </summary>
|
||||
Single = 0,
|
||||
|
||||
/// <summary>
|
||||
/// Targets all instances found of the MonoBehaviour.
|
||||
/// </summary>
|
||||
All = 1,
|
||||
|
||||
/// <summary>
|
||||
/// Targets all instances registered in the QuantumConsoleProcessor registry. Instances can be added using <c>QFSW.QC.QuantumConsoleProcessor.Register</c>.
|
||||
/// The only supported target type for non MonoBehaviour commands
|
||||
/// </summary>
|
||||
Registry = 2,
|
||||
|
||||
/// <summary>
|
||||
/// Automatically creates an instance if it does not yet exist and adds it to the registry, where it will be used for all future function calls.
|
||||
/// </summary>
|
||||
Singleton = 3,
|
||||
|
||||
/// <summary>
|
||||
/// Targets the first instance found of the MonoBehaviour. Includes inactive objects in its search
|
||||
/// </summary>
|
||||
SingleInactive = 4,
|
||||
|
||||
/// <summary>
|
||||
/// Targets all instances found of the MonoBehaviour. Includes inactive objects in its search
|
||||
/// </summary>
|
||||
AllInactive = 5
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 04b01e54e9d739a43b5df71ab38c6abc
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,8 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 39128e97dd5df334f930d2ffa6544602
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,27 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace QFSW.QC
|
||||
{
|
||||
/// <summary>
|
||||
/// Parser for a single type.
|
||||
/// Caches results and reuses them if the incoming string has already been parsed.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The type to parse.</typeparam>
|
||||
public abstract class BasicCachedQcParser<T> : BasicQcParser<T>
|
||||
{
|
||||
private readonly Dictionary<string, T> _cacheLookup = new Dictionary<string, T>();
|
||||
|
||||
public override object Parse(string value, Type type, Func<string, Type, object> recursiveParser)
|
||||
{
|
||||
if (_cacheLookup.ContainsKey(value))
|
||||
{
|
||||
return _cacheLookup[value];
|
||||
}
|
||||
|
||||
T result = (T)base.Parse(value, type, recursiveParser);
|
||||
_cacheLookup[value] = result;
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: bfc8ab8be8feaaa4292952550e15979d
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,38 @@
|
|||
using System;
|
||||
|
||||
namespace QFSW.QC
|
||||
{
|
||||
/// <summary>
|
||||
/// Parser for a single type.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The type to parse.</typeparam>
|
||||
public abstract class BasicQcParser<T> : IQcParser
|
||||
{
|
||||
private Func<string, Type, object> _recursiveParser;
|
||||
|
||||
public virtual int Priority => 0;
|
||||
|
||||
public bool CanParse(Type type)
|
||||
{
|
||||
return type == typeof(T);
|
||||
}
|
||||
|
||||
public virtual object Parse(string value, Type type, Func<string, Type, object> recursiveParser)
|
||||
{
|
||||
_recursiveParser = recursiveParser;
|
||||
return Parse(value);
|
||||
}
|
||||
|
||||
protected object ParseRecursive(string value, Type type)
|
||||
{
|
||||
return _recursiveParser(value, type);
|
||||
}
|
||||
|
||||
protected TElement ParseRecursive<TElement>(string value)
|
||||
{
|
||||
return (TElement)_recursiveParser(value, typeof(TElement));
|
||||
}
|
||||
|
||||
public abstract T Parse(string value);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: ffe8acdee133098408a3ec9eaacbd78e
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,8 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 223d79a496072b94bb244a4a1f7fc489
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,13 @@
|
|||
using System;
|
||||
|
||||
namespace QFSW.QC
|
||||
{
|
||||
/// <summary>
|
||||
/// Exception to be thrown by an IQcParser.
|
||||
/// </summary>
|
||||
public class ParserException : Exception
|
||||
{
|
||||
public ParserException(string message) : base(message) { }
|
||||
public ParserException(string message, Exception innerException) : base(message, innerException) { }
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 4bac12a9ecc201a4d9988f4f23166952
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,13 @@
|
|||
using System;
|
||||
|
||||
namespace QFSW.QC
|
||||
{
|
||||
/// <summary>
|
||||
/// Exception to be thrown by an IQcParser to indicate the input was invalid.
|
||||
/// </summary>
|
||||
public class ParserInputException : ParserException
|
||||
{
|
||||
public ParserInputException(string message) : base(message) { }
|
||||
public ParserInputException(string message, Exception innerException) : base(message, innerException) { }
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 559f64f0707530544bf37986bfc4f9c1
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,27 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace QFSW.QC
|
||||
{
|
||||
/// <summary>
|
||||
/// Parser for all types that are generic constructions of a single type.
|
||||
/// Caches results and reuses them if the incoming string has already been parsed.
|
||||
/// </summary>
|
||||
public abstract class GenericCachedQcParser : GenericQcParser
|
||||
{
|
||||
private readonly Dictionary<(string, Type), object> _cacheLookup = new Dictionary<(string, Type), object>();
|
||||
|
||||
public override object Parse(string value, Type type, Func<string, Type, object> recursiveParser)
|
||||
{
|
||||
(string value, Type type) key = (value, type);
|
||||
if (_cacheLookup.ContainsKey(key))
|
||||
{
|
||||
return _cacheLookup[key];
|
||||
}
|
||||
|
||||
object result = base.Parse(value, type, recursiveParser);
|
||||
_cacheLookup[key] = result;
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 45c1313ec062d864794a8fb903f0217e
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,56 @@
|
|||
using QFSW.QC.Utilities;
|
||||
using System;
|
||||
|
||||
namespace QFSW.QC
|
||||
{
|
||||
/// <summary>
|
||||
/// Parser for all types that are generic constructions of a single type.
|
||||
/// </summary>
|
||||
public abstract class GenericQcParser : IQcParser
|
||||
{
|
||||
/// <summary>
|
||||
/// The incomplete generic type of this parser.
|
||||
/// </summary>
|
||||
protected abstract Type GenericType { get; }
|
||||
|
||||
private Func<string, Type, object> _recursiveParser;
|
||||
|
||||
protected GenericQcParser()
|
||||
{
|
||||
if (!GenericType.IsGenericType)
|
||||
{
|
||||
throw new ArgumentException($"Generic Parsers must use a generic type as their base");
|
||||
}
|
||||
|
||||
if (GenericType.IsConstructedGenericType)
|
||||
{
|
||||
throw new ArgumentException($"Generic Parsers must use an incomplete generic type as their base");
|
||||
}
|
||||
}
|
||||
|
||||
public virtual int Priority => -500;
|
||||
|
||||
public bool CanParse(Type type)
|
||||
{
|
||||
return type.IsGenericTypeOf(GenericType);
|
||||
}
|
||||
|
||||
public virtual object Parse(string value, Type type, Func<string, Type, object> recursiveParser)
|
||||
{
|
||||
_recursiveParser = recursiveParser;
|
||||
return Parse(value, type);
|
||||
}
|
||||
|
||||
protected object ParseRecursive(string value, Type type)
|
||||
{
|
||||
return _recursiveParser(value, type);
|
||||
}
|
||||
|
||||
protected TElement ParseRecursive<TElement>(string value)
|
||||
{
|
||||
return (TElement)_recursiveParser(value, typeof(TElement));
|
||||
}
|
||||
|
||||
public abstract object Parse(string value, Type type);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: c81ef7ca4a87a7843b5abee5c22e6ace
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,8 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 14f1f27cf493be645ba8db007b704475
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,8 @@
|
|||
fileFormatVersion: 2
|
||||
guid: f7627ba6a0fc6d34182bb1aa178b4be5
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,15 @@
|
|||
using System;
|
||||
using System.Linq.Expressions;
|
||||
|
||||
namespace QFSW.QC.Grammar
|
||||
{
|
||||
public class AdditionOperatorGrammar : BinaryAndUnaryOperatorGrammar
|
||||
{
|
||||
public override int Precedence => 0;
|
||||
|
||||
protected override char OperatorToken => '+';
|
||||
protected override string OperatorMethodName => "op_Addition";
|
||||
|
||||
protected override Func<Expression, Expression, BinaryExpression> PrimitiveExpressionGenerator => Expression.Add;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 0a0906d67478d174c896a36b20dc10c0
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,56 @@
|
|||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace QFSW.QC.Grammar
|
||||
{
|
||||
public abstract class BinaryAndUnaryOperatorGrammar : BinaryOperatorGrammar
|
||||
{
|
||||
private readonly HashSet<char> _operatorChars = new HashSet<char>()
|
||||
{
|
||||
'+',
|
||||
'-',
|
||||
'*',
|
||||
'/',
|
||||
'&',
|
||||
'|',
|
||||
'^',
|
||||
'=',
|
||||
'!',
|
||||
','
|
||||
};
|
||||
|
||||
private readonly HashSet<char> _ignoreChars = new HashSet<char>()
|
||||
{
|
||||
' ',
|
||||
'\0'
|
||||
};
|
||||
|
||||
protected override int GetOperatorPosition(string value)
|
||||
{
|
||||
IEnumerable<int> splitPoints = TextProcessing.GetScopedSplitPoints(value, OperatorToken, TextProcessing.DefaultLeftScopers, TextProcessing.DefaultRightScopers);
|
||||
|
||||
foreach (int index in splitPoints.Reverse())
|
||||
{
|
||||
if (IsValidBinaryOperator(value, index))
|
||||
{
|
||||
return index;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
private bool IsValidBinaryOperator(string value, int position)
|
||||
{
|
||||
while (position > 0)
|
||||
{
|
||||
char ch = value[--position];
|
||||
|
||||
if (_operatorChars.Contains(ch)) { return false; }
|
||||
if (!_ignoreChars.Contains(ch)) { return true; }
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 98ed033aecce1204bbfca244d563194b
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,34 @@
|
|||
using System;
|
||||
using System.Reflection;
|
||||
|
||||
namespace QFSW.QC.Grammar
|
||||
{
|
||||
internal class BinaryOperatorData : IBinaryOperator
|
||||
{
|
||||
public Type LArg { get; }
|
||||
public Type RArg { get; }
|
||||
public Type Ret { get; }
|
||||
|
||||
private readonly MethodInfo _method;
|
||||
|
||||
public BinaryOperatorData(MethodInfo OperatorMethod)
|
||||
{
|
||||
_method = OperatorMethod;
|
||||
Ret = OperatorMethod.ReturnType;
|
||||
|
||||
ParameterInfo[] paramData = _method.GetParameters();
|
||||
if (paramData.Length != 2)
|
||||
{
|
||||
throw new ArgumentException($"Cannot create a binary operator from a method with {paramData.Length} parameters");
|
||||
}
|
||||
|
||||
LArg = paramData[0].ParameterType;
|
||||
RArg = paramData[1].ParameterType;
|
||||
}
|
||||
|
||||
public object Invoke(object left, object right)
|
||||
{
|
||||
return _method.Invoke(null, new[] { left, right });
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: e479a8c10bf9fa043959daa459ce97db
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,146 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Linq.Expressions;
|
||||
using System.Reflection;
|
||||
using System.Text.RegularExpressions;
|
||||
using QFSW.QC.Utilities;
|
||||
|
||||
namespace QFSW.QC.Grammar
|
||||
{
|
||||
public abstract class BinaryOperatorGrammar : IQcGrammarConstruct
|
||||
{
|
||||
public abstract int Precedence { get; }
|
||||
protected abstract char OperatorToken { get; }
|
||||
protected abstract string OperatorMethodName { get; }
|
||||
protected abstract Func<Expression, Expression, BinaryExpression> PrimitiveExpressionGenerator { get; }
|
||||
|
||||
private Regex _operatorRegex;
|
||||
|
||||
private readonly HashSet<Type> _missingOperatorTable = new HashSet<Type>();
|
||||
private readonly Dictionary<Type, IBinaryOperator> _foundOperatorTable = new Dictionary<Type, IBinaryOperator>();
|
||||
|
||||
public bool Match(string value, Type type)
|
||||
{
|
||||
if (_missingOperatorTable.Contains(type))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!IsSyntaxMatch(value))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (_foundOperatorTable.ContainsKey(type))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
IBinaryOperator operatorData = GetOperatorData(type);
|
||||
|
||||
if (operatorData != null)
|
||||
{
|
||||
_foundOperatorTable.Add(type, operatorData);
|
||||
return true;
|
||||
}
|
||||
|
||||
_missingOperatorTable.Add(type);
|
||||
return false;
|
||||
}
|
||||
|
||||
private bool IsSyntaxMatch(string value)
|
||||
{
|
||||
if (_operatorRegex == null)
|
||||
{
|
||||
_operatorRegex = new Regex($@"^.+\{OperatorToken}.+$");
|
||||
}
|
||||
|
||||
if (!_operatorRegex.IsMatch(value))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
int operatorPos = GetOperatorPosition(value);
|
||||
return operatorPos > 0 && operatorPos < value.Length;
|
||||
}
|
||||
|
||||
private IBinaryOperator GetOperatorData(Type type)
|
||||
{
|
||||
if (type.IsPrimitive)
|
||||
{
|
||||
#if !ENABLE_IL2CPP
|
||||
return GeneratePrimitiveOperator(type);
|
||||
#else
|
||||
string typeName = QFSW.QC.Utilities.ReflectionExtensions.GetDisplayName(type);
|
||||
UnityEngine.Debug.LogWarning($"{typeName} {OperatorToken} {typeName} is not supported as IL2CPP does not support dynamic value typed generics.");
|
||||
#endif
|
||||
}
|
||||
|
||||
MethodInfo[] methods = type.GetMethods(BindingFlags.Public | BindingFlags.Static);
|
||||
BinaryOperatorData[] candidates = methods.Where(x => x.Name == OperatorMethodName)
|
||||
.Where(x => x.ReturnType == type)
|
||||
.Where(x => x.GetParameters().Length == 2)
|
||||
.Select(x => new BinaryOperatorData(x))
|
||||
.ToArray();
|
||||
|
||||
BinaryOperatorData idealCandidate = candidates.FirstOrDefault(x => x.LArg == type && x.RArg == type)
|
||||
?? candidates.FirstOrDefault(x => x.LArg == type)
|
||||
?? candidates.FirstOrDefault(x => x.RArg == type)
|
||||
?? candidates.FirstOrDefault();
|
||||
|
||||
return idealCandidate;
|
||||
}
|
||||
|
||||
private IBinaryOperator GeneratePrimitiveOperator(Type type)
|
||||
{
|
||||
ParameterExpression leftParam = Expression.Parameter(type, "left");
|
||||
ParameterExpression rightParam = Expression.Parameter(type, "right");
|
||||
BinaryExpression body;
|
||||
|
||||
try
|
||||
{
|
||||
body = PrimitiveExpressionGenerator(leftParam, rightParam);
|
||||
}
|
||||
catch (InvalidOperationException)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
Delegate expr = Expression.Lambda(body, true, leftParam, rightParam).Compile();
|
||||
|
||||
return new DynamicBinaryOperator(expr, type, type, type);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the position of the right-most valid operator token.
|
||||
/// </summary>
|
||||
/// <param name="value">The string to find the operator in.</param>
|
||||
/// <returns>The position of the operator. -1 if none can be found</returns>
|
||||
protected virtual int GetOperatorPosition(string value)
|
||||
{
|
||||
return TextProcessing.GetScopedSplitPoints(value, OperatorToken, TextProcessing.DefaultLeftScopers, TextProcessing.DefaultRightScopers).LastOr(-1);
|
||||
}
|
||||
|
||||
public object Parse(string value, Type type, Func<string, Type, object> recursiveParser)
|
||||
{
|
||||
IBinaryOperator operatorData = _foundOperatorTable[type];
|
||||
|
||||
int splitIndex = GetOperatorPosition(value);
|
||||
string left = value.Substring(0, splitIndex);
|
||||
string right = value.Substring(splitIndex + 1);
|
||||
|
||||
object leftVal = recursiveParser(left, operatorData.LArg);
|
||||
object rightVal = recursiveParser(right, operatorData.RArg);
|
||||
|
||||
try
|
||||
{
|
||||
return operatorData.Invoke(leftVal, rightVal);
|
||||
}
|
||||
catch (TargetInvocationException e)
|
||||
{
|
||||
throw e.InnerException ?? e;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: f3a6802829bc65049b2c671ce148f547
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,15 @@
|
|||
using System;
|
||||
using System.Linq.Expressions;
|
||||
|
||||
namespace QFSW.QC.Grammar
|
||||
{
|
||||
public class BitwiseAndOperatorGrammar : BinaryOperatorGrammar
|
||||
{
|
||||
public override int Precedence => 6;
|
||||
|
||||
protected override char OperatorToken => '&';
|
||||
protected override string OperatorMethodName => "op_bitwiseAnd";
|
||||
|
||||
protected override Func<Expression, Expression, BinaryExpression> PrimitiveExpressionGenerator => Expression.And;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: d9296938ddd32064d999e8e7000789ba
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,15 @@
|
|||
using System;
|
||||
using System.Linq.Expressions;
|
||||
|
||||
namespace QFSW.QC.Grammar
|
||||
{
|
||||
public class BitwiseOrOperatorGrammar : BinaryOperatorGrammar
|
||||
{
|
||||
public override int Precedence => 5;
|
||||
|
||||
protected override char OperatorToken => '|';
|
||||
protected override string OperatorMethodName => "op_bitwiseOr";
|
||||
|
||||
protected override Func<Expression, Expression, BinaryExpression> PrimitiveExpressionGenerator => Expression.Or;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: a87fe84f3c6c7ba4191321937395bd84
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,15 @@
|
|||
using System;
|
||||
using System.Linq.Expressions;
|
||||
|
||||
namespace QFSW.QC.Grammar
|
||||
{
|
||||
public class DivisionOperatorGrammar : BinaryOperatorGrammar
|
||||
{
|
||||
public override int Precedence => 3;
|
||||
|
||||
protected override char OperatorToken => '/';
|
||||
protected override string OperatorMethodName => "op_Division";
|
||||
|
||||
protected override Func<Expression, Expression, BinaryExpression> PrimitiveExpressionGenerator => Expression.Divide;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 78358bd367d21fb44b571bf2d2dcd03f
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,26 @@
|
|||
using System;
|
||||
|
||||
namespace QFSW.QC.Grammar
|
||||
{
|
||||
internal class DynamicBinaryOperator : IBinaryOperator
|
||||
{
|
||||
public Type LArg { get; }
|
||||
public Type RArg { get; }
|
||||
public Type Ret { get; }
|
||||
|
||||
private readonly Delegate _del;
|
||||
|
||||
public DynamicBinaryOperator(Delegate del, Type lArg, Type rArg, Type ret)
|
||||
{
|
||||
_del = del;
|
||||
LArg = lArg;
|
||||
RArg = rArg;
|
||||
Ret = ret;
|
||||
}
|
||||
|
||||
public object Invoke(object left, object right)
|
||||
{
|
||||
return _del.DynamicInvoke(left, right);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 18c4d964a275c32438dcb4abc6c1fb4d
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,15 @@
|
|||
using System;
|
||||
using System.Linq.Expressions;
|
||||
|
||||
namespace QFSW.QC.Grammar
|
||||
{
|
||||
public class ExclusiveOrOperatorGrammar : BinaryOperatorGrammar
|
||||
{
|
||||
public override int Precedence => 7;
|
||||
|
||||
protected override char OperatorToken => '^';
|
||||
protected override string OperatorMethodName => "op_ExclusiveOr";
|
||||
|
||||
protected override Func<Expression, Expression, BinaryExpression> PrimitiveExpressionGenerator => Expression.ExclusiveOr;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 8528cd4143f809f459ca13f6415e8a03
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,13 @@
|
|||
using System;
|
||||
|
||||
namespace QFSW.QC.Grammar
|
||||
{
|
||||
public interface IBinaryOperator
|
||||
{
|
||||
Type LArg { get; }
|
||||
Type RArg { get; }
|
||||
Type Ret { get; }
|
||||
|
||||
object Invoke(object left, object right);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 8349fa6e81e457847afbe6291aada5fd
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,15 @@
|
|||
using System;
|
||||
using System.Linq.Expressions;
|
||||
|
||||
namespace QFSW.QC.Grammar
|
||||
{
|
||||
public class ModulusOperatorGrammar : BinaryOperatorGrammar
|
||||
{
|
||||
public override int Precedence => 4;
|
||||
|
||||
protected override char OperatorToken => '%';
|
||||
protected override string OperatorMethodName => "op_Modulus";
|
||||
|
||||
protected override Func<Expression, Expression, BinaryExpression> PrimitiveExpressionGenerator => Expression.Modulo;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: fedde2bcbb582294d9c08ba7d622ab14
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,15 @@
|
|||
using System;
|
||||
using System.Linq.Expressions;
|
||||
|
||||
namespace QFSW.QC.Grammar
|
||||
{
|
||||
public class MultiplyOperatorGrammar : BinaryOperatorGrammar
|
||||
{
|
||||
public override int Precedence => 2;
|
||||
|
||||
protected override char OperatorToken => '*';
|
||||
protected override string OperatorMethodName => "op_Multiply";
|
||||
|
||||
protected override Func<Expression, Expression, BinaryExpression> PrimitiveExpressionGenerator => Expression.Multiply;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 00dd2e1128bbc2b4db7fc3c2c1e840e7
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,15 @@
|
|||
using System;
|
||||
using System.Linq.Expressions;
|
||||
|
||||
namespace QFSW.QC.Grammar
|
||||
{
|
||||
public class SubtractionOperatorGrammar : BinaryAndUnaryOperatorGrammar
|
||||
{
|
||||
public override int Precedence => 1;
|
||||
|
||||
protected override char OperatorToken => '-';
|
||||
protected override string OperatorMethodName => "op_Subtraction";
|
||||
|
||||
protected override Func<Expression, Expression, BinaryExpression> PrimitiveExpressionGenerator => Expression.Subtract;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 48f2484f770bd9744bac9ad2f4f92de4
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,23 @@
|
|||
using System;
|
||||
using System.Text.RegularExpressions;
|
||||
|
||||
namespace QFSW.QC.Grammar
|
||||
{
|
||||
public class BooleanNegationGrammar : IQcGrammarConstruct
|
||||
{
|
||||
private readonly Regex _negationRegex = new Regex(@"^!\S+$");
|
||||
|
||||
public int Precedence => 0;
|
||||
|
||||
public bool Match(string value, Type type)
|
||||
{
|
||||
return type == typeof(bool) && _negationRegex.IsMatch(value);
|
||||
}
|
||||
|
||||
public object Parse(string value, Type type, Func<string, Type, object> recursiveParser)
|
||||
{
|
||||
value = value.Substring(1);
|
||||
return !(bool)recursiveParser(value, type);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 0674e06c549290f46914c51adb79b5f7
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,59 @@
|
|||
using QFSW.QC.Utilities;
|
||||
using System;
|
||||
using System.Text.RegularExpressions;
|
||||
|
||||
namespace QFSW.QC.Grammar
|
||||
{
|
||||
public class ExpressionBodyGrammar : IQcGrammarConstruct
|
||||
{
|
||||
private readonly Regex _expressionBodyRegex = new Regex(@"^{.+}\??$");
|
||||
|
||||
public int Precedence => 0;
|
||||
|
||||
public bool Match(string value, Type type)
|
||||
{
|
||||
return _expressionBodyRegex.IsMatch(value);
|
||||
}
|
||||
|
||||
public object Parse(string value, Type type, Func<string, Type, object> recursiveParser)
|
||||
{
|
||||
bool nullable = false;
|
||||
if (value.EndsWith("?"))
|
||||
{
|
||||
nullable = true;
|
||||
value = value.Substring(0, value.Length - 1);
|
||||
}
|
||||
|
||||
value = value.ReduceScope('{', '}');
|
||||
object result = QuantumConsoleProcessor.InvokeCommand(value);
|
||||
|
||||
if (result is null)
|
||||
{
|
||||
if (nullable)
|
||||
{
|
||||
if (type.IsClass)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new ParserInputException($"Expression body {{{value}}} evaluated to null which is incompatible with the expected type '{type.GetDisplayName()}'.");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new ParserInputException($"Expression body {{{value}}} evaluated to null. If this is intended, please use nullable expression bodies, {{expr}}?");
|
||||
}
|
||||
}
|
||||
else if (result.GetType().IsCastableTo(type, true))
|
||||
{
|
||||
return type.Cast(result);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new ParserInputException($"Expression body {{{value}}} evaluated to an object of type '{result.GetType().GetDisplayName()}', " +
|
||||
$"which is incompatible with the expected type '{type.GetDisplayName()}'.");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 4299ec1767412954f9b37800967fd471
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,14 @@
|
|||
{
|
||||
"name": "QFSW.QC.Grammar",
|
||||
"references": [
|
||||
"QFSW.QC"
|
||||
],
|
||||
"optionalUnityReferences": [],
|
||||
"includePlatforms": [],
|
||||
"excludePlatforms": [],
|
||||
"allowUnsafeCode": false,
|
||||
"overrideReferences": false,
|
||||
"precompiledReferences": [],
|
||||
"autoReferenced": true,
|
||||
"defineConstraints": []
|
||||
}
|
|
@ -0,0 +1,7 @@
|
|||
fileFormatVersion: 2
|
||||
guid: ad10a660d2aec9d449de236f5524cb5c
|
||||
AssemblyDefinitionImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,33 @@
|
|||
using System;
|
||||
|
||||
namespace QFSW.QC
|
||||
{
|
||||
/// <summary>
|
||||
/// Creates a Parser for a custom grammar construct that is loaded and used by the QuantumParser.
|
||||
/// Grammar constructs are tested and used before resorting to IQcParsers for object value parsing.
|
||||
/// </summary>
|
||||
public interface IQcGrammarConstruct
|
||||
{
|
||||
/// <summary>
|
||||
/// The precedence of this grammar construct.
|
||||
/// </summary>
|
||||
int Precedence { get; }
|
||||
|
||||
/// <summary>
|
||||
/// If the incoming data matches this grammar construct.
|
||||
/// </summary>
|
||||
/// <param name="value">The incoming string data.</param>
|
||||
/// <param name="type">The type to test.</param>
|
||||
/// <returns>If it matches the grammar defined by this construct.</returns>
|
||||
bool Match(string value, Type type);
|
||||
|
||||
/// <summary>
|
||||
/// Parses the incoming string to the specified type.
|
||||
/// </summary>
|
||||
/// <param name="value">The incoming string data.</param>
|
||||
/// <param name="type">The type to parse the incoming string to.</param>
|
||||
/// <param name="recursiveParser">Delegate back to the main parser to allow for recursive parsing of sub elements.</param>
|
||||
/// <returns>The parsed object.</returns>
|
||||
object Parse(string value, Type type, Func<string, Type, object> recursiveParser);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 9c2c98c09a1ef19408e80fec4b2932d0
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,31 @@
|
|||
using System;
|
||||
|
||||
namespace QFSW.QC
|
||||
{
|
||||
/// <summary>
|
||||
/// Creates a Parser that is loaded and used by the QuantumParser.
|
||||
/// </summary>
|
||||
public interface IQcParser
|
||||
{
|
||||
/// <summary>
|
||||
/// The priority of this parser to resolve multiple parsers covering the same type.
|
||||
/// </summary>
|
||||
int Priority { get; }
|
||||
|
||||
/// <summary>
|
||||
/// If this parser can parse to the incoming type.
|
||||
/// </summary>
|
||||
/// <param name="type">The type to test.</param>
|
||||
/// <returns>If it can be parsed.</returns>
|
||||
bool CanParse(Type type);
|
||||
|
||||
/// <summary>
|
||||
/// Parses the incoming string to the specified type.
|
||||
/// </summary>
|
||||
/// <param name="value">The incoming string data.</param>
|
||||
/// <param name="type">The type to parse the incoming string to.</param>
|
||||
/// <param name="recursiveParser">Delegate back to the main parser to allow for recursive parsing of sub elements.</param>
|
||||
/// <returns>The parsed object.</returns>
|
||||
object Parse(string value, Type type, Func<string, Type, object> recursiveParser);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: d796cb1619e0adb48916716da79c9f9b
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,64 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace QFSW.QC
|
||||
{
|
||||
/// <summary>
|
||||
/// Parser for all types that are generic constructions of a several types.
|
||||
/// </summary>
|
||||
public abstract class MassGenericQcParser : IQcParser
|
||||
{
|
||||
/// <summary>
|
||||
/// The incomplete generic types of this parser.
|
||||
/// </summary>
|
||||
protected abstract HashSet<Type> GenericTypes { get; }
|
||||
|
||||
private Func<string, Type, object> _recursiveParser;
|
||||
|
||||
protected MassGenericQcParser()
|
||||
{
|
||||
foreach (Type type in GenericTypes)
|
||||
{
|
||||
if (!type.IsGenericType)
|
||||
{
|
||||
throw new ArgumentException($"Generic Parsers must use a generic type as their base");
|
||||
}
|
||||
|
||||
if (type.IsConstructedGenericType)
|
||||
{
|
||||
throw new ArgumentException($"Generic Parsers must use an incomplete generic type as their base");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public virtual int Priority => -2000;
|
||||
|
||||
public bool CanParse(Type type)
|
||||
{
|
||||
if (type.IsGenericType)
|
||||
{
|
||||
return GenericTypes.Contains(type.GetGenericTypeDefinition());
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public virtual object Parse(string value, Type type, Func<string, Type, object> recursiveParser)
|
||||
{
|
||||
_recursiveParser = recursiveParser;
|
||||
return Parse(value, type);
|
||||
}
|
||||
|
||||
protected object ParseRecursive(string value, Type type)
|
||||
{
|
||||
return _recursiveParser(value, type);
|
||||
}
|
||||
|
||||
protected TElement ParseRecursive<TElement>(string value)
|
||||
{
|
||||
return (TElement)_recursiveParser(value, typeof(TElement));
|
||||
}
|
||||
|
||||
public abstract object Parse(string value, Type type);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: d08d4cc71bd3f9f47baf04ed33d3a284
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,8 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 819146b9096942b48914d95b8268664a
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,29 @@
|
|||
using System;
|
||||
using System.Collections;
|
||||
|
||||
namespace QFSW.QC.Parsers
|
||||
{
|
||||
public class ArrayParser : IQcParser
|
||||
{
|
||||
public int Priority => -100;
|
||||
|
||||
public bool CanParse(Type type)
|
||||
{
|
||||
return type.IsArray;
|
||||
}
|
||||
|
||||
public object Parse(string value, Type type, Func<string, Type, object> recursiveParser)
|
||||
{
|
||||
Type elementType = type.GetElementType();
|
||||
string[] valueParts = value.ReduceScope('[', ']').SplitScoped(',');
|
||||
|
||||
IList dataArray = Array.CreateInstance(elementType, valueParts.Length);
|
||||
for (int i = 0; i < valueParts.Length; i++)
|
||||
{
|
||||
dataArray[i] = recursiveParser(valueParts[i], elementType);
|
||||
}
|
||||
|
||||
return dataArray;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: debc47c083b042c4c8a295d533a85094
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,22 @@
|
|||
namespace QFSW.QC.Parsers
|
||||
{
|
||||
public class BoolParser : BasicCachedQcParser<bool>
|
||||
{
|
||||
public override bool Parse(string value)
|
||||
{
|
||||
value = value.ToLower().Trim();
|
||||
switch (value)
|
||||
{
|
||||
case "true": return true;
|
||||
case "on": return true;
|
||||
case "1": return true;
|
||||
case "yes": return true;
|
||||
case "false": return false;
|
||||
case "off": return false;
|
||||
case "0": return false;
|
||||
case "no": return false;
|
||||
default: throw new ParserInputException($"Cannot parse '{value}' to a bool.");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: f610c84a8ec2129489d0f4d00a585b18
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,28 @@
|
|||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace QFSW.QC.Parsers
|
||||
{
|
||||
public class CollectionParser : MassGenericQcParser
|
||||
{
|
||||
protected override HashSet<Type> GenericTypes { get; } = new HashSet<Type>
|
||||
{
|
||||
typeof(List<>),
|
||||
typeof(Stack<>),
|
||||
typeof(Queue<>),
|
||||
typeof(HashSet<>),
|
||||
typeof(LinkedList<>),
|
||||
typeof(ConcurrentStack<>),
|
||||
typeof(ConcurrentQueue<>),
|
||||
typeof(ConcurrentBag<>)
|
||||
};
|
||||
|
||||
public override object Parse(string value, Type type)
|
||||
{
|
||||
Type arrayType = type.GetGenericArguments()[0].MakeArrayType();
|
||||
object array = ParseRecursive(value, arrayType);
|
||||
return Activator.CreateInstance(type, array);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 2692eedbcfd50e24a8644b39e70351a7
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,116 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Reflection;
|
||||
using UnityEngine;
|
||||
|
||||
namespace QFSW.QC.Parsers
|
||||
{
|
||||
public class ColorParser : BasicCachedQcParser<Color>
|
||||
{
|
||||
private readonly Dictionary<string, Color> _colorLookup;
|
||||
|
||||
public ColorParser()
|
||||
{
|
||||
_colorLookup = new Dictionary<string, Color>();
|
||||
|
||||
PropertyInfo[] colorProperties = typeof(Color).GetProperties(BindingFlags.Static | BindingFlags.Public);
|
||||
foreach (PropertyInfo prop in colorProperties)
|
||||
{
|
||||
if (prop.CanRead && !prop.CanWrite)
|
||||
{
|
||||
MethodInfo propReader = prop.GetMethod;
|
||||
if (propReader.ReturnType == typeof(Color))
|
||||
{
|
||||
_colorLookup.Add(prop.Name, (Color)propReader.Invoke(null, Array.Empty<object>()));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override Color Parse(string value)
|
||||
{
|
||||
if (_colorLookup.ContainsKey(value.ToLower()))
|
||||
{
|
||||
return _colorLookup[value.ToLower()];
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
if (value.StartsWith("0x"))
|
||||
{
|
||||
return ParseHexColor(value);
|
||||
}
|
||||
else
|
||||
{
|
||||
return ParseRGBAColor(value);
|
||||
}
|
||||
}
|
||||
catch (FormatException e)
|
||||
{
|
||||
throw new ParserInputException($"{e.Message}\nThe format must be either of:" +
|
||||
$"\n - R,G,B" +
|
||||
$"\n - R,G,B,A" +
|
||||
$"\n - 0xRRGGBB" +
|
||||
$"\n - 0xRRGGBBAA" +
|
||||
$"\n - A preset color such as 'red'", e);
|
||||
}
|
||||
}
|
||||
|
||||
private Color ParseRGBAColor(string value)
|
||||
{
|
||||
string[] colorParts = value.Split(',');
|
||||
Color parsedColor = Color.white;
|
||||
int i = 0;
|
||||
|
||||
if (colorParts.Length < 3 || colorParts.Length > 4) { throw new FormatException($"Cannot parse '{value}' as a Color."); }
|
||||
|
||||
float ParsePart(string part)
|
||||
{
|
||||
float val = float.Parse(part);
|
||||
if (val < 0 || val > 1) { throw new FormatException($"{val} falls outside of the valid [0,1] range for a component of a Color."); }
|
||||
return val;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
for (; i < colorParts.Length; i++)
|
||||
{
|
||||
parsedColor[i] = ParsePart(colorParts[i]);
|
||||
}
|
||||
|
||||
return parsedColor;
|
||||
}
|
||||
catch (FormatException)
|
||||
{
|
||||
throw new FormatException($"Cannot parse '{colorParts[i]}' as part of a Color, it must be numerical and in the valid range [0,1].");
|
||||
}
|
||||
}
|
||||
|
||||
private Color ParseHexColor(string value)
|
||||
{
|
||||
int digitCount = value.Length - 2;
|
||||
if (digitCount != 6 && digitCount != 8)
|
||||
{
|
||||
throw new FormatException("Hex colors must contain either 6 or 8 hex digits.");
|
||||
}
|
||||
|
||||
Color parsedColor = Color.white;
|
||||
int byteCount = digitCount / 2;
|
||||
int i = 0;
|
||||
|
||||
try
|
||||
{
|
||||
for (; i < byteCount; i++)
|
||||
{
|
||||
parsedColor[i] = int.Parse(value.Substring(2 * (1 + i), 2), System.Globalization.NumberStyles.HexNumber) / 255f;
|
||||
}
|
||||
|
||||
return parsedColor;
|
||||
}
|
||||
catch (FormatException)
|
||||
{
|
||||
throw new FormatException($"Cannot parse '{value.Substring(2 * (1 + i), 2)}' as part of a Color as it was invalid hex.");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 31739988d804da941aa363d4a58bfae6
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,22 @@
|
|||
using QFSW.QC.Utilities;
|
||||
using System;
|
||||
using UnityEngine;
|
||||
|
||||
namespace QFSW.QC.Parsers
|
||||
{
|
||||
public class ComponentParser : PolymorphicQcParser<Component>
|
||||
{
|
||||
public override Component Parse(string value, Type type)
|
||||
{
|
||||
GameObject obj = ParseRecursive<GameObject>(value);
|
||||
Component objComponent = obj.GetComponent(type);
|
||||
|
||||
if (!objComponent)
|
||||
{
|
||||
throw new ParserInputException($"No component on the object '{value}' of type {type.GetDisplayName()} existed.");
|
||||
}
|
||||
|
||||
return objComponent;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 4fbd8b9265a0c3f4a9a3aa55595b889f
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,20 @@
|
|||
using QFSW.QC.Utilities;
|
||||
using System;
|
||||
|
||||
namespace QFSW.QC.Parsers
|
||||
{
|
||||
public class EnumParser : PolymorphicCachedQcParser<Enum>
|
||||
{
|
||||
public override Enum Parse(string value, Type type)
|
||||
{
|
||||
try
|
||||
{
|
||||
return (Enum)Enum.Parse(type, value);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
throw new ParserInputException($"Cannot parse '{value}' to the type '{type.GetDisplayName()}'. To see the supported values, use the command `enum-info {type}`", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: e211a4d691805e049a06ba8a06ca4f92
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,23 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace QFSW.QC.Parsers
|
||||
{
|
||||
public class EnumerableParser : MassGenericQcParser
|
||||
{
|
||||
protected override HashSet<Type> GenericTypes { get; } = new HashSet<Type>()
|
||||
{
|
||||
typeof(IEnumerable<>),
|
||||
typeof(ICollection<>),
|
||||
typeof(IReadOnlyCollection<>),
|
||||
typeof(IList<>),
|
||||
typeof(IReadOnlyList<>)
|
||||
};
|
||||
|
||||
public override object Parse(string value, Type type)
|
||||
{
|
||||
Type arrayType = type.GetGenericArguments()[0].MakeArrayType();
|
||||
return ParseRecursive(value, arrayType);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: c885a65409b41894ab2688fef15008b0
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,21 @@
|
|||
using QFSW.QC.Utilities;
|
||||
using UnityEngine;
|
||||
|
||||
namespace QFSW.QC.Parsers
|
||||
{
|
||||
public class GameObjectParser : BasicQcParser<GameObject>
|
||||
{
|
||||
public override GameObject Parse(string value)
|
||||
{
|
||||
string name = ParseRecursive<string>(value);
|
||||
GameObject obj = GameObjectExtensions.Find(name, true);
|
||||
|
||||
if (!obj)
|
||||
{
|
||||
throw new ParserInputException($"Could not find GameObject of name {value}.");
|
||||
}
|
||||
|
||||
return obj;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 5c5d24ea53ab5c341b04e2b935368e73
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,46 @@
|
|||
using QFSW.QC.Utilities;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
|
||||
namespace QFSW.QC.Parsers
|
||||
{
|
||||
public class PrimitiveParser : IQcParser
|
||||
{
|
||||
private readonly HashSet<Type> _primitiveTypes = new HashSet<Type>
|
||||
{
|
||||
typeof(int),
|
||||
typeof(float),
|
||||
typeof(decimal),
|
||||
typeof(double),
|
||||
typeof(bool),
|
||||
typeof(byte),
|
||||
typeof(sbyte),
|
||||
typeof(uint),
|
||||
typeof(short),
|
||||
typeof(ushort),
|
||||
typeof(long),
|
||||
typeof(ulong),
|
||||
typeof(char)
|
||||
};
|
||||
|
||||
public int Priority => -1000;
|
||||
|
||||
public bool CanParse(Type type)
|
||||
{
|
||||
return _primitiveTypes.Contains(type);
|
||||
}
|
||||
|
||||
public object Parse(string value, Type type, Func<string, Type, object> recursiveParser)
|
||||
{
|
||||
try
|
||||
{
|
||||
return Convert.ChangeType(value, type, CultureInfo.InvariantCulture);
|
||||
}
|
||||
catch (FormatException e)
|
||||
{
|
||||
throw new ParserInputException($"Cannot parse '{value}' to the type '{type.GetDisplayName()}'.", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 030edeaf5882fc4408d3ebb9368779a9
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,14 @@
|
|||
{
|
||||
"name": "QFSW.QC.Parsers",
|
||||
"references": [
|
||||
"QFSW.QC"
|
||||
],
|
||||
"optionalUnityReferences": [],
|
||||
"includePlatforms": [],
|
||||
"excludePlatforms": [],
|
||||
"allowUnsafeCode": false,
|
||||
"overrideReferences": false,
|
||||
"precompiledReferences": [],
|
||||
"autoReferenced": true,
|
||||
"defineConstraints": []
|
||||
}
|
|
@ -0,0 +1,7 @@
|
|||
fileFormatVersion: 2
|
||||
guid: a5d04fa5e431fa844be99e9199658b16
|
||||
AssemblyDefinitionImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,13 @@
|
|||
using UnityEngine;
|
||||
|
||||
namespace QFSW.QC.Parsers
|
||||
{
|
||||
public class QuaternionParser : BasicCachedQcParser<Quaternion>
|
||||
{
|
||||
public override Quaternion Parse(string value)
|
||||
{
|
||||
Vector4 vector = ParseRecursive<Vector4>(value);
|
||||
return new Quaternion(vector.x, vector.y, vector.z, vector.w);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 99e9d99d8fb57ac42a9821372699449b
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,14 @@
|
|||
namespace QFSW.QC.Parsers
|
||||
{
|
||||
public class StringParser : BasicCachedQcParser<string>
|
||||
{
|
||||
public override int Priority => int.MaxValue;
|
||||
|
||||
public override string Parse(string value)
|
||||
{
|
||||
return value
|
||||
.ReduceScope('"', '"')
|
||||
.UnescapeText('"');
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 028f88c2880e54c4f883885b9a263c8c
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,49 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace QFSW.QC.Parsers
|
||||
{
|
||||
public class TupleParser : MassGenericQcParser
|
||||
{
|
||||
private const int MaxFlatTupleSize = 8;
|
||||
|
||||
protected override HashSet<Type> GenericTypes { get; } = new HashSet<Type>
|
||||
{
|
||||
typeof(ValueTuple<>),
|
||||
typeof(ValueTuple<,>),
|
||||
typeof(ValueTuple<,,>),
|
||||
typeof(ValueTuple<,,,>),
|
||||
typeof(ValueTuple<,,,,>),
|
||||
typeof(ValueTuple<,,,,,>),
|
||||
typeof(ValueTuple<,,,,,,>),
|
||||
typeof(ValueTuple<,,,,,,,>),
|
||||
typeof(Tuple<>),
|
||||
typeof(Tuple<,>),
|
||||
typeof(Tuple<,,>),
|
||||
typeof(Tuple<,,,>),
|
||||
typeof(Tuple<,,,,>),
|
||||
typeof(Tuple<,,,,,>),
|
||||
typeof(Tuple<,,,,,,>),
|
||||
typeof(Tuple<,,,,,,,>)
|
||||
};
|
||||
|
||||
public override object Parse(string value, Type type)
|
||||
{
|
||||
string[] inputParts = value.ReduceScope('(', ')').SplitScoped(',', MaxFlatTupleSize);
|
||||
Type[] elementTypes = type.GetGenericArguments();
|
||||
|
||||
if (elementTypes.Length != inputParts.Length)
|
||||
{
|
||||
throw new ParserInputException($"Desired tuple type {type} has {elementTypes.Length} elements but input contained {inputParts.Length}.");
|
||||
}
|
||||
|
||||
object[] tupleParts = new object[inputParts.Length];
|
||||
for (int i = 0; i < tupleParts.Length; i++)
|
||||
{
|
||||
tupleParts[i] = ParseRecursive(inputParts[i], elementTypes[i]);
|
||||
}
|
||||
|
||||
return Activator.CreateInstance(type, tupleParts);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 6842e4e236f2eaa41bddefbef8aa7276
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,12 @@
|
|||
using System;
|
||||
|
||||
namespace QFSW.QC.Parsers
|
||||
{
|
||||
public class TypeParser : BasicCachedQcParser<Type>
|
||||
{
|
||||
public override Type Parse(string value)
|
||||
{
|
||||
return QuantumParser.ParseType(value);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: f7be70a556f9e094c8fa7f5dd0c7e81b
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,12 @@
|
|||
using UnityEngine;
|
||||
|
||||
namespace QFSW.QC.Parsers
|
||||
{
|
||||
public class Vector2IntParser : BasicCachedQcParser<Vector2Int>
|
||||
{
|
||||
public override Vector2Int Parse(string value)
|
||||
{
|
||||
return (Vector2Int)ParseRecursive<Vector3Int>(value);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 0288f6e4dbdbb964eb1f0f7bafe6ca37
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,12 @@
|
|||
using UnityEngine;
|
||||
|
||||
namespace QFSW.QC.Parsers
|
||||
{
|
||||
public class Vector2Parser : BasicCachedQcParser<Vector2>
|
||||
{
|
||||
public override Vector2 Parse(string value)
|
||||
{
|
||||
return ParseRecursive<Vector4>(value);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: bb12462fc0295f046957d1030894bea6
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,33 @@
|
|||
using UnityEngine;
|
||||
|
||||
namespace QFSW.QC.Parsers
|
||||
{
|
||||
public class Vector3IntParser : BasicCachedQcParser<Vector3Int>
|
||||
{
|
||||
public override Vector3Int Parse(string value)
|
||||
{
|
||||
string[] vectorParts = value.Split(',');
|
||||
Vector3Int parsedVector = new Vector3Int();
|
||||
|
||||
if (vectorParts.Length < 2 || vectorParts.Length > 3)
|
||||
{
|
||||
throw new ParserInputException($"Cannot parse '{value}' as an int vector, the format must be either x,y or x,y,z");
|
||||
}
|
||||
|
||||
int i = 0;
|
||||
try
|
||||
{
|
||||
for (; i < vectorParts.Length; i++)
|
||||
{
|
||||
parsedVector[i] = int.Parse(vectorParts[i]);
|
||||
}
|
||||
|
||||
return parsedVector;
|
||||
}
|
||||
catch
|
||||
{
|
||||
throw new ParserInputException($"Cannot parse '{vectorParts[i]}' as it must be integral.");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 7af974e71f13d6c4f9c3a5291581e815
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,12 @@
|
|||
using UnityEngine;
|
||||
|
||||
namespace QFSW.QC.Parsers
|
||||
{
|
||||
public class Vector3Parser : BasicCachedQcParser<Vector3>
|
||||
{
|
||||
public override Vector3 Parse(string value)
|
||||
{
|
||||
return ParseRecursive<Vector4>(value);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: ca39e94d5f7e12b4cbb7b00f77a8278c
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,25 @@
|
|||
using UnityEngine;
|
||||
|
||||
namespace QFSW.QC.Parsers
|
||||
{
|
||||
public class Vector4Parser : BasicCachedQcParser<Vector4>
|
||||
{
|
||||
public override Vector4 Parse(string value)
|
||||
{
|
||||
string[] vectorParts = value.SplitScoped(',');
|
||||
Vector4 parsedVector = new Vector4();
|
||||
|
||||
if (vectorParts.Length < 2 || vectorParts.Length > 4)
|
||||
{
|
||||
throw new ParserInputException($"Cannot parse '{value}' as a vector, the format must be either x,y x,y,z or x,y,z,w.");
|
||||
}
|
||||
|
||||
for (int i = 0; i < vectorParts.Length; i++)
|
||||
{
|
||||
parsedVector[i] = ParseRecursive<float>(vectorParts[i]);
|
||||
}
|
||||
|
||||
return parsedVector;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: feb6ca1c0ec89bf4e8bb8ae58737a1f3
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,28 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace QFSW.QC
|
||||
{
|
||||
/// <summary>
|
||||
/// Parser for all types inheriting from a single type.
|
||||
/// Caches results and reuses them if the incoming string has already been parsed.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">Base type of the types to parse.</typeparam>
|
||||
public abstract class PolymorphicCachedQcParser<T> : PolymorphicQcParser<T> where T : class
|
||||
{
|
||||
private readonly Dictionary<(string, Type), T> _cacheLookup = new Dictionary<(string, Type), T>();
|
||||
|
||||
public override object Parse(string value, Type type, Func<string, Type, object> recursiveParser)
|
||||
{
|
||||
(string value, Type type) key = (value, type);
|
||||
if (_cacheLookup.ContainsKey(key))
|
||||
{
|
||||
return _cacheLookup[key];
|
||||
}
|
||||
|
||||
T result = (T)base.Parse(value, type, recursiveParser);
|
||||
_cacheLookup[key] = result;
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 512ba3db6b1fb234a878ee64b68bf5c4
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,38 @@
|
|||
using System;
|
||||
|
||||
namespace QFSW.QC
|
||||
{
|
||||
/// <summary>
|
||||
/// Parser for all types inheriting from a single type.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">Base type of the types to parse.</typeparam>
|
||||
public abstract class PolymorphicQcParser<T> : IQcParser where T : class
|
||||
{
|
||||
private Func<string, Type, object> _recursiveParser;
|
||||
|
||||
public virtual int Priority => -1000;
|
||||
|
||||
public bool CanParse(Type type)
|
||||
{
|
||||
return typeof(T).IsAssignableFrom(type);
|
||||
}
|
||||
|
||||
public virtual object Parse(string value, Type type, Func<string, Type, object> recursiveParser)
|
||||
{
|
||||
_recursiveParser = recursiveParser;
|
||||
return Parse(value, type);
|
||||
}
|
||||
|
||||
protected object ParseRecursive(string value, Type type)
|
||||
{
|
||||
return _recursiveParser(value, type);
|
||||
}
|
||||
|
||||
protected TElement ParseRecursive<TElement>(string value)
|
||||
{
|
||||
return (TElement)_recursiveParser(value, typeof(TElement));
|
||||
}
|
||||
|
||||
public abstract T Parse(string value, Type type);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: c042a38294a50b34e8089e7adbaf76e7
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,383 @@
|
|||
using QFSW.QC.Utilities;
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Text.RegularExpressions;
|
||||
using UnityEngine;
|
||||
|
||||
namespace QFSW.QC
|
||||
{
|
||||
/// <summary>
|
||||
/// Handles parsing values to use as console inputs.
|
||||
/// </summary>
|
||||
public class QuantumParser
|
||||
{
|
||||
private readonly IQcParser[] _parsers;
|
||||
private readonly IQcGrammarConstruct[] _grammarConstructs;
|
||||
private readonly ConcurrentDictionary<Type, IQcParser> _parserLookup = new ConcurrentDictionary<Type, IQcParser>();
|
||||
private readonly HashSet<Type> _unparseableLookup = new HashSet<Type>();
|
||||
|
||||
private readonly Func<string, Type, object> _recursiveParser;
|
||||
|
||||
/// <summary>
|
||||
/// Creates a Parser Serializer with a custom set of parsers.
|
||||
/// </summary>
|
||||
/// <param name="parsers">The IQcParsers to use in this Quantum Parser.</param>
|
||||
/// <param name="grammarConstructs">The IQcGrammarConstructs to use in this Quantum Parser</param>
|
||||
public QuantumParser(IEnumerable<IQcParser> parsers, IEnumerable<IQcGrammarConstruct> grammarConstructs)
|
||||
{
|
||||
_recursiveParser = Parse;
|
||||
|
||||
_parsers = parsers.OrderByDescending(x => x.Priority)
|
||||
.ToArray();
|
||||
|
||||
_grammarConstructs = grammarConstructs.OrderBy(x => x.Precedence)
|
||||
.ToArray();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a Quantum Parser with the default injected parsers.
|
||||
/// </summary>
|
||||
public QuantumParser() : this(new InjectionLoader<IQcParser>().GetInjectedInstances(), new InjectionLoader<IQcGrammarConstruct>().GetInjectedInstances())
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public IQcParser GetParser(Type type)
|
||||
{
|
||||
if (_parserLookup.ContainsKey(type))
|
||||
{
|
||||
return _parserLookup[type];
|
||||
}
|
||||
else if (!_unparseableLookup.Contains(type))
|
||||
{
|
||||
foreach (IQcParser parser in _parsers)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (parser.CanParse(type))
|
||||
{
|
||||
return _parserLookup[type] = parser;
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Debug.LogError($"{parser.GetType().GetDisplayName()}.CanParse is malformed and throws");
|
||||
Debug.LogException(e);
|
||||
}
|
||||
}
|
||||
|
||||
_unparseableLookup.Add(type);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public bool CanParse(Type type)
|
||||
{
|
||||
return GetParser(type) != null;
|
||||
}
|
||||
|
||||
private IQcGrammarConstruct GetMatchingGrammar(string value, Type type)
|
||||
{
|
||||
foreach (IQcGrammarConstruct grammar in _grammarConstructs)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (grammar.Match(value, type))
|
||||
{
|
||||
return grammar;
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Debug.LogError($"{grammar.GetType().GetDisplayName()}.Match is malformed and throws");
|
||||
Debug.LogException(e);
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Parses a serialized string of data.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The type of the value to parse.</typeparam>
|
||||
/// <param name="value">The string to parse.</param>
|
||||
/// <returns>The parsed value.</returns>
|
||||
public T Parse<T>(string value)
|
||||
{
|
||||
return (T)Parse(value, typeof(T));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Parses a serialized string of data.
|
||||
/// </summary>
|
||||
/// <param name="value">The string to parse.</param>
|
||||
/// <param name="type">The type of the value to parse.</param>
|
||||
/// <returns>The parsed value.</returns>
|
||||
public object Parse(string value, Type type)
|
||||
{
|
||||
value = value.ReduceScope('(', ')');
|
||||
|
||||
if (type.IsClass && value == "null")
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
IQcGrammarConstruct grammar = GetMatchingGrammar(value, type);
|
||||
if (grammar != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
return grammar.Parse(value, type, _recursiveParser);
|
||||
}
|
||||
catch (ParserException) { throw; }
|
||||
catch (Exception e)
|
||||
{
|
||||
throw new Exception($"Parsing of {type.GetDisplayName()} via {grammar} failed:\n{e.Message}", e);
|
||||
}
|
||||
}
|
||||
|
||||
IQcParser parser = GetParser(type);
|
||||
if (parser == null)
|
||||
{
|
||||
throw new ArgumentException($"Cannot parse object of type '{type.GetDisplayName()}'");
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
return parser.Parse(value, type, _recursiveParser);
|
||||
}
|
||||
catch (ParserException) { throw; }
|
||||
catch (Exception e)
|
||||
{
|
||||
throw new Exception($"Parsing of {type.GetDisplayName()} via {parser} failed:\n{e.Message}", e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#region Type Parser
|
||||
private static readonly Dictionary<Type, string> _typeDisplayNames = new Dictionary<Type, string>
|
||||
{
|
||||
{ typeof(int), "int" }, { typeof(float), "float" }, { typeof(decimal), "decimal" },
|
||||
{ typeof(double), "double" }, { typeof(string), "string" }, { typeof(bool), "bool" },
|
||||
{ typeof(byte), "byte" }, { typeof(sbyte), "sbyte" }, { typeof(uint), "uint" },
|
||||
{ typeof(short), "short" }, { typeof(ushort), "ushort" }, { typeof(long), "long" },
|
||||
{ typeof(ulong), "ulong" }, { typeof(char), "char" }, { typeof(object), "object" }
|
||||
};
|
||||
|
||||
private static readonly Dictionary<string, Type> _reverseTypeDisplayNames = _typeDisplayNames.Invert();
|
||||
private static readonly Assembly[] _loadedAssemblies = AppDomain.CurrentDomain.GetAssemblies();
|
||||
private static readonly string[] _defaultNamespaces = new string[] { "System", "System.Collections", "System.Collections.Generic", "UnityEngine", "UnityEngine.UI", "QFSW.QC" };
|
||||
private static readonly List<string> _namespaceTable = new List<string>(_defaultNamespaces);
|
||||
|
||||
private static readonly Regex _arrayTypeRegex = new Regex(@"^.*\[,*\]$");
|
||||
private static readonly Regex _genericTypeRegex = new Regex(@"^.+<.*>$");
|
||||
private static readonly Regex _tupleTypeRegex = new Regex(@"^\(.*\)$");
|
||||
|
||||
/// <summary>
|
||||
/// Resets the namespace table to its initial state.
|
||||
/// </summary>
|
||||
[Command("reset-namespaces", "Resets the namespace table to its initial state")]
|
||||
public static void ResetNamespaceTable()
|
||||
{
|
||||
_namespaceTable.Clear();
|
||||
_namespaceTable.AddRange(_defaultNamespaces);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds a namespace to the table so that it can be used to type resolution.
|
||||
/// </summary>
|
||||
[Command("use-namespace", "Adds a namespace to the table so that it can be used to type resolution")]
|
||||
public static void AddNamespace(string namespaceName)
|
||||
{
|
||||
if (!_namespaceTable.Contains(namespaceName))
|
||||
{
|
||||
_namespaceTable.Add(namespaceName);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Removes a namespace to the table so that it is no longer used to type resolution.
|
||||
/// </summary>
|
||||
[Command("remove-namespace", "Removes a namespace from the table")]
|
||||
public static void RemoveNamespace(string namespaceName)
|
||||
{
|
||||
if (_namespaceTable.Contains(namespaceName))
|
||||
{
|
||||
_namespaceTable.Remove(namespaceName);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new ArgumentException($"No namespace named {namespaceName} was present in the table");
|
||||
}
|
||||
}
|
||||
|
||||
[Command("all-namespaces", "Displays all of the namespaces currently in use by the namespace table")]
|
||||
private static string ShowNamespaces()
|
||||
{
|
||||
_namespaceTable.Sort();
|
||||
if (_namespaceTable.Count == 0) { return "Namespace table is empty"; }
|
||||
else { return string.Join("\n", _namespaceTable); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a copy of the namespace table.
|
||||
/// </summary>
|
||||
public static IEnumerable<string> GetAllNamespaces() { return _namespaceTable; }
|
||||
|
||||
/// <summary>
|
||||
/// Parses and infers the type specified by the string.
|
||||
/// </summary>
|
||||
/// <returns>The parsed type.</returns>
|
||||
/// <param name="typeName">The type to parse.</param>
|
||||
public static Type ParseType(string typeName)
|
||||
{
|
||||
typeName = typeName.Trim();
|
||||
|
||||
if (_reverseTypeDisplayNames.ContainsKey(typeName))
|
||||
{
|
||||
return _reverseTypeDisplayNames[typeName];
|
||||
}
|
||||
|
||||
if (_tupleTypeRegex.IsMatch(typeName))
|
||||
{
|
||||
return ParseTupleType(typeName);
|
||||
}
|
||||
|
||||
if (_arrayTypeRegex.IsMatch(typeName))
|
||||
{
|
||||
return ParseArrayType(typeName);
|
||||
}
|
||||
|
||||
if (_genericTypeRegex.IsMatch(typeName))
|
||||
{
|
||||
return ParseGenericType(typeName);
|
||||
}
|
||||
|
||||
if (typeName.Contains('`'))
|
||||
{
|
||||
string genericName = typeName.Split('`')[0];
|
||||
if (_reverseTypeDisplayNames.ContainsKey(genericName))
|
||||
{
|
||||
return _reverseTypeDisplayNames[genericName];
|
||||
}
|
||||
}
|
||||
|
||||
return ParseTypeBaseCase(typeName);
|
||||
}
|
||||
|
||||
private static Type ParseArrayType(string typeName)
|
||||
{
|
||||
int arrayPos = typeName.LastIndexOf('[');
|
||||
int arrayRank = typeName.CountFromIndex(',', arrayPos) + 1;
|
||||
Type elementType = ParseType(typeName.Substring(0, arrayPos));
|
||||
|
||||
return arrayRank > 1
|
||||
? elementType.MakeArrayType(arrayRank)
|
||||
: elementType.MakeArrayType();
|
||||
}
|
||||
|
||||
private static Type ParseGenericType(string typeName)
|
||||
{
|
||||
string[] parts = typeName.Split(new[] { '<' }, 2);
|
||||
string[] genericArgNames = $"<{parts[1]}".ReduceScope('<', '>').SplitScoped(',');
|
||||
string incompleteGenericName = $"{parts[0]}`{Math.Max(1, genericArgNames.Length)}";
|
||||
|
||||
Type incompleteGenericType = ParseType(incompleteGenericName);
|
||||
if (genericArgNames.All(string.IsNullOrWhiteSpace))
|
||||
{
|
||||
return incompleteGenericType;
|
||||
}
|
||||
|
||||
Type[] genericArgs = genericArgNames.Select(ParseType).ToArray();
|
||||
|
||||
return incompleteGenericType.MakeGenericType(genericArgs);
|
||||
}
|
||||
|
||||
private static Type ParseTupleType(string typeName)
|
||||
{
|
||||
string inner = typeName.Substring(1, typeName.Length - 2);
|
||||
|
||||
Type[] parts = inner
|
||||
.SplitScoped(',')
|
||||
.Select(ParseType)
|
||||
.ToArray();
|
||||
|
||||
return CreateTupleType(parts);
|
||||
}
|
||||
|
||||
private static readonly Type[] _valueTupleTypes =
|
||||
{
|
||||
typeof(ValueTuple<>),
|
||||
typeof(ValueTuple<,>),
|
||||
typeof(ValueTuple<,,>),
|
||||
typeof(ValueTuple<,,,>),
|
||||
typeof(ValueTuple<,,,,>),
|
||||
typeof(ValueTuple<,,,,,>),
|
||||
typeof(ValueTuple<,,,,,,>),
|
||||
typeof(ValueTuple<,,,,,,,>)
|
||||
};
|
||||
|
||||
private static Type CreateTupleType(Type[] types)
|
||||
{
|
||||
const int maxFlatTupleSize = 8;
|
||||
|
||||
if (types.Length > maxFlatTupleSize - 1)
|
||||
{
|
||||
Type[] innerTypes = types.Skip(maxFlatTupleSize - 1).ToArray();
|
||||
types = types
|
||||
.Take(maxFlatTupleSize - 1)
|
||||
.Concat(CreateTupleType(innerTypes).Yield())
|
||||
.ToArray();
|
||||
}
|
||||
|
||||
return _valueTupleTypes[types.Length - 1].MakeGenericType(types);
|
||||
}
|
||||
|
||||
private static Type ParseTypeBaseCase(string typeName)
|
||||
{
|
||||
return GetTypeFromAssemblies(typeName, _loadedAssemblies, false, false)
|
||||
?? GetTypeFromAssemblies(typeName, _namespaceTable, _loadedAssemblies, false, false)
|
||||
?? GetTypeFromAssemblies(typeName, _loadedAssemblies, false, true)
|
||||
?? GetTypeFromAssemblies(typeName, _namespaceTable, _loadedAssemblies, true, true);
|
||||
}
|
||||
|
||||
private static Type GetTypeFromAssemblies(string typeName, IEnumerable<string> namespaces, IEnumerable<Assembly> assemblies, bool throwOnError, bool ignoreCase)
|
||||
{
|
||||
foreach (string namespaceName in namespaces)
|
||||
{
|
||||
Type type = GetTypeFromAssemblies($"{namespaceName}.{typeName}", assemblies, false, ignoreCase);
|
||||
if (type != null) { return type; }
|
||||
}
|
||||
|
||||
if (throwOnError)
|
||||
{
|
||||
throw new TypeLoadException($"No type of name '{typeName}' could be found in the specified assemblies and namespaces.");
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private static Type GetTypeFromAssemblies(string typeName, IEnumerable<Assembly> assemblies, bool throwOnError, bool ignoreCase)
|
||||
{
|
||||
foreach (Assembly assembly in assemblies)
|
||||
{
|
||||
Type type = Type.GetType($"{typeName}, {assembly.FullName}", false, ignoreCase);
|
||||
if (type != null) { return type; }
|
||||
}
|
||||
|
||||
if (throwOnError)
|
||||
{
|
||||
throw new TypeLoadException($"No type of name '{typeName}' could be found in the specified assemblies.");
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
#endregion
|
||||
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 3f45dc8b7ae674cd99121d0933e891df
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,69 @@
|
|||
using System;
|
||||
using UnityEngine;
|
||||
|
||||
namespace QFSW.QC
|
||||
{
|
||||
/// <summary>
|
||||
/// Bitwise flag enum for the runtime platform. Setting a platform bit to 0 includes it as a supported platform.
|
||||
/// </summary>
|
||||
[Flags]
|
||||
public enum Platform : long
|
||||
{
|
||||
#pragma warning disable 612,618
|
||||
OSXEditor = 1L << RuntimePlatform.OSXEditor,
|
||||
OSXPlayer = 1L << RuntimePlatform.OSXPlayer,
|
||||
WindowsPlayer = 1L << RuntimePlatform.WindowsPlayer,
|
||||
OSXWebPlayer = 1L << 3,
|
||||
OSXDashboardPlayer = 1L << 4,
|
||||
WindowsWebPlayer = 1L << 5,
|
||||
WindowsEditor = 1L << RuntimePlatform.WindowsEditor,
|
||||
IPhonePlayer = 1L << RuntimePlatform.IPhonePlayer,
|
||||
PS3 = 1L << RuntimePlatform.PS3,
|
||||
XBOX360 = 1L << RuntimePlatform.XBOX360,
|
||||
Android = 1L << RuntimePlatform.Android,
|
||||
NaCl = 1L << RuntimePlatform.NaCl,
|
||||
LinuxPlayer = 1L << RuntimePlatform.LinuxPlayer,
|
||||
FlashPlayer = 1L << RuntimePlatform.FlashPlayer,
|
||||
LinuxEditor = 1L << RuntimePlatform.LinuxEditor,
|
||||
WebGLPlayer = 1L << RuntimePlatform.WebGLPlayer,
|
||||
MetroPlayerX86 = 1L << RuntimePlatform.MetroPlayerX86,
|
||||
WSAPlayerX86 = 1L << RuntimePlatform.WSAPlayerX86,
|
||||
MetroPlayerX64 = 1L << RuntimePlatform.MetroPlayerX64,
|
||||
WSAPlayerX64 = 1L << RuntimePlatform.WSAPlayerX64,
|
||||
MetroPlayerARM = 1L << RuntimePlatform.MetroPlayerARM,
|
||||
WSAPlayerARM = 1L << RuntimePlatform.WSAPlayerARM,
|
||||
WP8Player = 1L << RuntimePlatform.WP8Player,
|
||||
BlackBerryPlayer = 1L << RuntimePlatform.BlackBerryPlayer,
|
||||
TizenPlayer = 1L << RuntimePlatform.TizenPlayer,
|
||||
PSP2 = 1L << RuntimePlatform.PSP2,
|
||||
PS4 = 1L << RuntimePlatform.PS4,
|
||||
PSM = 1L << RuntimePlatform.PSM,
|
||||
XboxOne = 1L << RuntimePlatform.XboxOne,
|
||||
SamsungTVPlayer = 1L << RuntimePlatform.SamsungTVPlayer,
|
||||
WiiU = 1L << RuntimePlatform.WiiU,
|
||||
tvOS = 1L << RuntimePlatform.tvOS,
|
||||
Switch = 1L << RuntimePlatform.Switch,
|
||||
Lumin = 1L << RuntimePlatform.Lumin,
|
||||
#if UNITY_2019_3_OR_NEWER
|
||||
Stadia = 1L << RuntimePlatform.Stadia,
|
||||
#endif
|
||||
#pragma warning restore 612, 618
|
||||
|
||||
None = 0,
|
||||
AllPlatforms = ~0,
|
||||
EditorPlatforms = LinuxEditor | OSXEditor | WindowsEditor,
|
||||
BuildPlatforms = AllPlatforms ^ EditorPlatforms,
|
||||
MobilePlatforms = IPhonePlayer | Android | WP8Player
|
||||
}
|
||||
|
||||
public static class PlatformExtensions
|
||||
{
|
||||
/// <summary>Converts Unity's RuntimePlatform to QC's bitwise Platform.</summary>
|
||||
public static Platform ToPlatform(this RuntimePlatform pl)
|
||||
{
|
||||
int val = (int)pl;
|
||||
long bitwise = 1L << val;
|
||||
return (Platform)bitwise;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: fd545ba57b790c84f8bb9e926fedf21f
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,40 @@
|
|||
using System.Collections.Generic;
|
||||
|
||||
namespace QFSW.QC
|
||||
{
|
||||
public class Pool<T> where T : class, new()
|
||||
{
|
||||
private readonly Stack<T> _objs;
|
||||
|
||||
public Pool()
|
||||
{
|
||||
_objs = new Stack<T>();
|
||||
}
|
||||
|
||||
public Pool(int objCount)
|
||||
{
|
||||
_objs = new Stack<T>(objCount);
|
||||
for (int i = 0; i < objCount; i++)
|
||||
{
|
||||
_objs.Push(new T());
|
||||
}
|
||||
}
|
||||
|
||||
public T GetObject()
|
||||
{
|
||||
if (_objs.Count > 0)
|
||||
{
|
||||
return _objs.Pop();
|
||||
}
|
||||
else
|
||||
{
|
||||
return new T();
|
||||
}
|
||||
}
|
||||
|
||||
public void Release(T obj)
|
||||
{
|
||||
_objs.Push(obj);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 92c171e15d3b459478e26e2217e49a05
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,8 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 8f6f8de740c67e8448ac5b693bf65900
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,20 @@
|
|||
namespace QFSW.QC
|
||||
{
|
||||
/// <summary>
|
||||
/// Creates a Preprocessor that is loaded and used by the QuantumConsoleProcessor.
|
||||
/// </summary>
|
||||
public interface IQcPreprocessor
|
||||
{
|
||||
/// <summary>
|
||||
/// The priority of this preprocessor to resolve processing order.
|
||||
/// </summary>
|
||||
int Priority { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Processes the provided text.
|
||||
/// </summary>
|
||||
/// <param name="text">The text to process.</param>
|
||||
/// <returns>The processed text.</returns>
|
||||
string Process(string text);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 982c71777d2ff0148ba45412ef409334
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,54 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace QFSW.QC
|
||||
{
|
||||
/// <summary>
|
||||
/// Handles preprocessing of console input.
|
||||
/// </summary>
|
||||
public class QuantumPreprocessor
|
||||
{
|
||||
private readonly IQcPreprocessor[] _preprocessors;
|
||||
|
||||
/// <summary>
|
||||
/// Creates a Quantum Preprocessor with a custom set of preprocessors.
|
||||
/// </summary>
|
||||
/// <param name="preprocessors">The IQcPreprocessors to use in this Quantum Preprocessor.</param>
|
||||
public QuantumPreprocessor(IEnumerable<IQcPreprocessor> preprocessors)
|
||||
{
|
||||
_preprocessors = preprocessors.OrderByDescending(x => x.Priority)
|
||||
.ToArray();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a Quantum Preprocessor with the default injected preprocessors
|
||||
/// </summary>
|
||||
public QuantumPreprocessor() : this(new InjectionLoader<IQcPreprocessor>().GetInjectedInstances())
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Processes the provided text.
|
||||
/// </summary>
|
||||
/// <param name="text">The text to process.</param>
|
||||
/// <returns>The processed text.</returns>
|
||||
public string Process(string text)
|
||||
{
|
||||
foreach (IQcPreprocessor preprocessor in _preprocessors)
|
||||
{
|
||||
try
|
||||
{
|
||||
text = preprocessor.Process(text);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
throw new Exception($"Preprocessor {preprocessor} failed:\n{e.Message}", e);
|
||||
}
|
||||
}
|
||||
|
||||
return text;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: ca234287b4b55cb45bf0ecea07ef2703
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,15 @@
|
|||
{
|
||||
"name": "QFSW.QC",
|
||||
"references": [
|
||||
"Unity.TextMeshPro",
|
||||
"Unity.InputSystem"
|
||||
],
|
||||
"optionalUnityReferences": [],
|
||||
"includePlatforms": [],
|
||||
"excludePlatforms": [],
|
||||
"allowUnsafeCode": true,
|
||||
"overrideReferences": false,
|
||||
"precompiledReferences": [],
|
||||
"autoReferenced": true,
|
||||
"defineConstraints": []
|
||||
}
|
|
@ -0,0 +1,7 @@
|
|||
fileFormatVersion: 2
|
||||
guid: fb24642277b1db2449da7ac148ce939d
|
||||
AssemblyDefinitionImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 3d0e534416bbcea448f24633d520da24
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,193 @@
|
|||
using QFSW.QC.Utilities;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
|
||||
namespace QFSW.QC
|
||||
{
|
||||
public static partial class QuantumConsoleProcessor
|
||||
{
|
||||
|
||||
private const string helpStr = "Welcome to Quantum Console! In order to see specific help about any specific command, " +
|
||||
"please use the 'man' command. Use 'man man' to see more about the man command. To see a full list of all " +
|
||||
"commands, use 'all-commands'.\n\n" +
|
||||
"mono-targets\nVarious commands may show a mono-target in their command signature.\n" +
|
||||
"This means they are not static commands, and instead requires instance(s) of the class in order to invoke the command." +
|
||||
"\nEach mono-target works differently as follows:" +
|
||||
"\n - single: uses the first instance of the type found in the scene" +
|
||||
"\n - all: uses all instances of the type found in the scene" +
|
||||
"\n - registry: uses all instances of the type found in the registry" +
|
||||
"\n - singleton: creates and manages a single instance automatically" +
|
||||
"\n\nThe registry is a part of the Quantum Registry that allows you to decide which specific instances of the class " +
|
||||
"should be used when invoking the command. In order to add an object to the registry, either use " +
|
||||
"QFSW.QC.QuantumRegistry.RegisterObject<T> or the runtime command 'register-object<T>'.";
|
||||
|
||||
[Command("help", "Shows a basic help guide for Quantum Console")]
|
||||
private static string GetHelp()
|
||||
{
|
||||
return helpStr;
|
||||
}
|
||||
|
||||
[Command("manual")]
|
||||
[Command("man")]
|
||||
private static string ManualHelp()
|
||||
{
|
||||
return "To use the man command, simply put the desired command name in front of it. For example, 'man my-command' will generate the manual for 'my-command'";
|
||||
}
|
||||
|
||||
[CommandDescription("Generates a user manual for any given command, including built in ones. To use the man command, simply put the desired command name infront of it. For example, 'man my-command' will generate the manual for 'my-command'")]
|
||||
[Command("help")]
|
||||
[Command("manual")]
|
||||
[Command("man")]
|
||||
private static string GenerateCommandManual(string commandName)
|
||||
{
|
||||
string[] matchingCommands = _commandTable.Keys.Where((string key) => key.Split('(')[0] == commandName).OrderBy((string key) => key).ToArray();
|
||||
if (matchingCommands.Length == 0) { throw new ArgumentException($"No command with the name {commandName} was found."); }
|
||||
else
|
||||
{
|
||||
Dictionary<string, ParameterInfo> foundParams = new Dictionary<string, ParameterInfo>();
|
||||
Dictionary<string, Type> foundGenericArguments = new Dictionary<string, Type>();
|
||||
Dictionary<string, CommandParameterDescriptionAttribute> foundParamDescriptions = new Dictionary<string, CommandParameterDescriptionAttribute>();
|
||||
List<Type> declaringTypes = new List<Type>(1);
|
||||
|
||||
string manual = $"Generated user manual for {commandName}\nAvailable command signatures:";
|
||||
|
||||
for (int i = 0; i < matchingCommands.Length; i++)
|
||||
{
|
||||
CommandData currentCommand = _commandTable[matchingCommands[i]];
|
||||
declaringTypes.Add(currentCommand.MethodData.DeclaringType);
|
||||
|
||||
manual += $"\n - {currentCommand.CommandSignature}";
|
||||
if (!currentCommand.IsStatic) { manual += $" (mono-target = {currentCommand.MonoTarget.ToString().ToLower()})"; }
|
||||
for (int j = 0; j < currentCommand.ParamCount; j++)
|
||||
{
|
||||
ParameterInfo param = currentCommand.MethodParamData[j];
|
||||
if (!foundParams.ContainsKey(param.Name)) { foundParams.Add(param.Name, param); }
|
||||
if (!foundParamDescriptions.ContainsKey(param.Name))
|
||||
{
|
||||
CommandParameterDescriptionAttribute descriptionAttribute = param.GetCustomAttribute<CommandParameterDescriptionAttribute>();
|
||||
if (descriptionAttribute != null && descriptionAttribute.Valid) { foundParamDescriptions.Add(param.Name, descriptionAttribute); }
|
||||
}
|
||||
}
|
||||
|
||||
if (currentCommand.IsGeneric)
|
||||
{
|
||||
Type[] genericArgs = currentCommand.GenericParamTypes;
|
||||
for (int j = 0; j < genericArgs.Length; j++)
|
||||
{
|
||||
Type arg = genericArgs[j];
|
||||
if (!foundGenericArguments.ContainsKey(arg.Name)) { foundGenericArguments.Add(arg.Name, arg); }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (foundParams.Count > 0)
|
||||
{
|
||||
manual += "\nParameter info:";
|
||||
ParameterInfo[] commandParams = foundParams.Values.ToArray();
|
||||
for (int i = 0; i < commandParams.Length; i++)
|
||||
{
|
||||
ParameterInfo currentParam = commandParams[i];
|
||||
manual += $"\n - {currentParam.Name}: {currentParam.ParameterType.GetDisplayName()}";
|
||||
}
|
||||
}
|
||||
|
||||
string genericConstraintInformation = "";
|
||||
if (foundGenericArguments.Count > 0)
|
||||
{
|
||||
Type[] genericArgs = foundGenericArguments.Values.ToArray();
|
||||
for (int i = 0; i < genericArgs.Length; i++)
|
||||
{
|
||||
Type arg = genericArgs[i];
|
||||
Type[] typeConstraints = arg.GetGenericParameterConstraints();
|
||||
GenericParameterAttributes attributes = arg.GenericParameterAttributes;
|
||||
|
||||
List<string> formattedConstraints = new List<string>();
|
||||
if (attributes.HasFlag(GenericParameterAttributes.NotNullableValueTypeConstraint)) { formattedConstraints.Add("struct"); }
|
||||
if (attributes.HasFlag(GenericParameterAttributes.ReferenceTypeConstraint)) { formattedConstraints.Add("class"); }
|
||||
for (int j = 0; j < typeConstraints.Length; j++) { formattedConstraints.Add(typeConstraints[i].GetDisplayName()); }
|
||||
if (attributes.HasFlag(GenericParameterAttributes.DefaultConstructorConstraint)) { formattedConstraints.Add("new()"); }
|
||||
|
||||
if (formattedConstraints.Count > 0)
|
||||
{
|
||||
genericConstraintInformation += $"\n - {arg.Name}: {string.Join(", ", formattedConstraints)}";
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!string.IsNullOrWhiteSpace(genericConstraintInformation)) { manual += $"\nGeneric constraints:{genericConstraintInformation}"; }
|
||||
|
||||
for (int i = 0; i < matchingCommands.Length; i++)
|
||||
{
|
||||
CommandData currentCommand = _commandTable[matchingCommands[i]];
|
||||
if (currentCommand.HasDescription)
|
||||
{
|
||||
manual += $"\n\nCommand description:\n{currentCommand.CommandDescription}";
|
||||
i = matchingCommands.Length;
|
||||
}
|
||||
}
|
||||
|
||||
if (foundParamDescriptions.Count > 0)
|
||||
{
|
||||
manual += "\n\nParameter descriptions:";
|
||||
ParameterInfo[] commandParams = foundParams.Values.ToArray();
|
||||
for (int i = 0; i < commandParams.Length; i++)
|
||||
{
|
||||
ParameterInfo currentParam = commandParams[i];
|
||||
if (foundParamDescriptions.ContainsKey(currentParam.Name))
|
||||
{
|
||||
manual += $"\n - {currentParam.Name}: {foundParamDescriptions[currentParam.Name].Description}";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
declaringTypes = declaringTypes.Distinct().ToList();
|
||||
manual += "\n\nDeclared in";
|
||||
if (declaringTypes.Count == 1) { manual += $" {declaringTypes[0].GetDisplayName(true)}"; }
|
||||
else
|
||||
{
|
||||
manual += ":";
|
||||
foreach (Type type in declaringTypes)
|
||||
{
|
||||
manual += $"\n - {type.GetDisplayName(true)}";
|
||||
}
|
||||
}
|
||||
|
||||
return manual;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets all loaded unique commands. Unique excludes multiple overloads of the same command from appearing.
|
||||
/// </summary>
|
||||
/// <returns>All loaded unique commands.</returns>
|
||||
public static IEnumerable<CommandData> GetUniqueCommands()
|
||||
{
|
||||
return GetAllCommands()
|
||||
.DistinctBy(x => x.CommandName)
|
||||
.OrderBy(x => x.CommandName);
|
||||
}
|
||||
|
||||
[CommandDescription("Generates a list of all commands currently loaded by the Quantum Console Processor")]
|
||||
[Command("commands")]
|
||||
[Command("all-commands")]
|
||||
private static string GenerateCommandList()
|
||||
{
|
||||
string output = "List of all commands loaded by the Quantum Processor. Use 'man' on any command to see more:";
|
||||
foreach (CommandData command in GetUniqueCommands())
|
||||
{
|
||||
output += $"\n - {command.CommandName}";
|
||||
}
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
[Command("user-commands", "Generates a list of all commands added by the user")]
|
||||
private static IEnumerable<string> GenerateUserCommandList()
|
||||
{
|
||||
return GetUniqueCommands()
|
||||
.Where(x => !x.MethodData.DeclaringType.Assembly.FullName.StartsWith("QFSW.QC"))
|
||||
.Select(x => $" - {x.CommandName}");
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: c72faae396a8a2f40a38eb6d0e1333ac
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,552 @@
|
|||
#if UNITY_EDITOR || !UNITY_WEBGL
|
||||
#define THREADS_SUPPORTED
|
||||
#endif
|
||||
|
||||
using QFSW.QC.Internal;
|
||||
using QFSW.QC.Utilities;
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using UnityEngine;
|
||||
|
||||
namespace QFSW.QC
|
||||
{
|
||||
public enum LoggingLevel
|
||||
{
|
||||
None = 0,
|
||||
Errors = 1,
|
||||
Warnings = 2,
|
||||
Full = 3
|
||||
}
|
||||
|
||||
/// <summary>The core processor of Quantum Console handling command table generation and invocation.</summary>
|
||||
public static partial class QuantumConsoleProcessor
|
||||
{
|
||||
/// <summary>The logging level to use during operation of the Quantum Console Processor.</summary>
|
||||
public static LoggingLevel loggingLevel = LoggingLevel.Full;
|
||||
|
||||
private static readonly QuantumParser _parser = new QuantumParser();
|
||||
private static readonly QuantumPreprocessor _preprocessor = new QuantumPreprocessor();
|
||||
private static readonly ConcurrentDictionary<string, CommandData> _commandTable = new ConcurrentDictionary<string, CommandData>();
|
||||
|
||||
public static bool TableGenerated { get; private set; }
|
||||
public static bool TableIsGenerating { get; private set; }
|
||||
|
||||
[Command("command-count", "Gets the number of loaded commands")]
|
||||
public static int LoadedCommandCount => _loadedCommandCount;
|
||||
private static int _loadedCommandCount = 0;
|
||||
|
||||
private static readonly Assembly[] _loadedAssemblies = AppDomain.CurrentDomain.GetAssemblies();
|
||||
|
||||
/// <summary>
|
||||
/// Gets all loaded commands.
|
||||
/// </summary>
|
||||
/// <returns>All loaded commands.</returns>
|
||||
public static IEnumerable<CommandData> GetAllCommands()
|
||||
{
|
||||
return _commandTable.Values;
|
||||
}
|
||||
|
||||
#region Table Generation
|
||||
/// <summary>
|
||||
/// Generates the command table so that commands can be invoked.
|
||||
/// </summary>
|
||||
/// <param name="deployThread">If set to <c>true</c> a second thread will be deployed for the table generation.</param>
|
||||
/// <param name="forceReload">If set to <c>true</c> then the table will be cleared and generated again.</param>
|
||||
public static void GenerateCommandTable(bool deployThread = false, bool forceReload = false)
|
||||
{
|
||||
#if THREADS_SUPPORTED
|
||||
if (deployThread)
|
||||
{
|
||||
ThreadPool.QueueUserWorkItem(state =>
|
||||
{
|
||||
try
|
||||
{
|
||||
GenerateCommandTable(false, forceReload);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Debug.LogException(e);
|
||||
}
|
||||
});
|
||||
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
lock (_commandTable)
|
||||
{
|
||||
if (!TableGenerated || forceReload)
|
||||
{
|
||||
TableIsGenerating = true;
|
||||
{
|
||||
if (forceReload && TableGenerated)
|
||||
{
|
||||
_commandTable.Clear();
|
||||
_loadedCommandCount = 0;
|
||||
}
|
||||
|
||||
#if THREADS_SUPPORTED
|
||||
Parallel.ForEach(_loadedAssemblies, assembly =>
|
||||
{
|
||||
if (AssemblyRequiresScan(assembly))
|
||||
{
|
||||
LoadCommandsFromAssembly(assembly);
|
||||
}
|
||||
});
|
||||
#else
|
||||
foreach (Assembly assembly in _loadedAssemblies)
|
||||
{
|
||||
if (AssemblyRequiresScan(assembly))
|
||||
{
|
||||
LoadCommandsFromAssembly(assembly);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
TableIsGenerating = false;
|
||||
TableGenerated = true;
|
||||
GC.Collect(3, GCCollectionMode.Forced, false, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static IEnumerable<(MethodInfo method, MemberInfo member)> ExtractCommandMethods(Type type)
|
||||
{
|
||||
const BindingFlags flags =
|
||||
BindingFlags.Static
|
||||
| BindingFlags.Instance
|
||||
| BindingFlags.Public
|
||||
| BindingFlags.NonPublic
|
||||
| BindingFlags.DeclaredOnly;
|
||||
|
||||
MethodInfo[] methods = type.GetMethods(flags);
|
||||
PropertyInfo[] properties = type.GetProperties(flags);
|
||||
FieldInfo[] fields = type.GetFields(flags);
|
||||
|
||||
foreach (MethodInfo method in methods)
|
||||
{
|
||||
yield return (method, method);
|
||||
}
|
||||
|
||||
foreach (PropertyInfo property in properties)
|
||||
{
|
||||
if (property.CanWrite)
|
||||
{
|
||||
yield return (property.SetMethod, property);
|
||||
}
|
||||
if (property.CanRead)
|
||||
{
|
||||
yield return (property.GetMethod, property);
|
||||
}
|
||||
}
|
||||
|
||||
foreach (FieldInfo field in fields)
|
||||
{
|
||||
if (field.HasAttribute<CommandAttribute>())
|
||||
{
|
||||
if (field.IsDelegate())
|
||||
{
|
||||
if (field.IsStrongDelegate())
|
||||
{
|
||||
FieldDelegateMethod executer = new FieldDelegateMethod(field);
|
||||
yield return (executer, field);
|
||||
}
|
||||
else if (loggingLevel >= LoggingLevel.Warnings)
|
||||
{
|
||||
Debug.LogWarning($"Quantum Processor Warning: Could not add '{field.Name}' from {field.DeclaringType} to the table as it is an invalid delegate type.");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
FieldAutoMethod reader = new FieldAutoMethod(field, FieldAutoMethod.AccessType.Read);
|
||||
yield return (reader, field);
|
||||
|
||||
if (!(field.IsLiteral || field.IsInitOnly))
|
||||
{
|
||||
FieldAutoMethod writer = new FieldAutoMethod(field, FieldAutoMethod.AccessType.Write);
|
||||
yield return (writer, field);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static bool GetCommandSupported(CommandData command, out string unsupportedReason)
|
||||
{
|
||||
for (int i = 0; i < command.ParamCount; i++)
|
||||
{
|
||||
ParameterInfo param = command.MethodParamData[i];
|
||||
Type paramType = param.ParameterType;
|
||||
|
||||
if (!_parser.CanParse(paramType) && !paramType.IsGenericParameter)
|
||||
{
|
||||
unsupportedReason = $"Parameter type {paramType} is not supported by the Quantum Parser.";
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (command.MonoTarget != MonoTargetType.Registry
|
||||
&& !command.MethodData.IsStatic
|
||||
&& !command.MethodData.DeclaringType.IsDerivedTypeOf(typeof(MonoBehaviour)))
|
||||
{
|
||||
unsupportedReason = $"Non static non MonoBehaviour commands are incompatible with MonoTargetType.{command.MonoTarget}.";
|
||||
return false;
|
||||
}
|
||||
|
||||
unsupportedReason = string.Empty;
|
||||
return true;
|
||||
}
|
||||
|
||||
private static bool AssemblyRequiresScan(Assembly assembly)
|
||||
{
|
||||
if (assembly.HasAttribute<QcIgnoreAttribute>(false))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
string[] bannedPrefixes = new string[]
|
||||
{
|
||||
"System", "Unity", "Microsoft", "Mono.", "mscorlib", "NSubstitute", "JetBrains", "nunit.",
|
||||
"GeNa."
|
||||
#if QC_DISABLE_BUILTIN_ALL
|
||||
, "QFSW.QC"
|
||||
#elif QC_DISABLE_BUILTIN_EXTRA
|
||||
, "QFSW.QC.Extra"
|
||||
#endif
|
||||
};
|
||||
|
||||
string[] bannedAssemblies = new string[]
|
||||
{
|
||||
"mcs", "AssetStoreTools"
|
||||
};
|
||||
|
||||
string assemblyFullName = assembly.FullName;
|
||||
foreach (string prefix in bannedPrefixes)
|
||||
{
|
||||
if (assemblyFullName.StartsWith(prefix))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
string assemblyShortName = assembly.GetName().Name;
|
||||
foreach (string name in bannedAssemblies)
|
||||
{
|
||||
if (assemblyShortName == name)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private static void LoadCommandsFromAssembly(Assembly assembly)
|
||||
{
|
||||
Type[] loadedTypes = assembly.GetTypes();
|
||||
foreach (Type type in loadedTypes)
|
||||
{
|
||||
try
|
||||
{
|
||||
LoadCommandsFromType(type);
|
||||
}
|
||||
catch (TypeLoadException)
|
||||
{
|
||||
// Issue under investigation
|
||||
|
||||
/*
|
||||
if (loggingLevel >= LoggingLevel.Warnings)
|
||||
{
|
||||
Debug.LogWarning($"Unable to extract command data from type {type} in assembly {assembly.GetName().Name} as it may be corrupted. The following exception was thrown: {e.Message}");
|
||||
}
|
||||
*/
|
||||
}
|
||||
catch (BadImageFormatException)
|
||||
{
|
||||
// Confirmed to be an issue on Unity/Mono's side
|
||||
// Extremely unlikely that it will ever occur in user code, so for this reason it is ignored silently
|
||||
// QC Issue: https://bitbucket.org/QFSW/quantum-console/issues/67/add-protection-against-corrupt-dlls
|
||||
// Unity Issue: https://issuetracker.unity3d.com/issues/badimageformatexception-is-thrown-when-calling-getcustomattributes-on-certain-memberinfo-instances
|
||||
// Mono Issue: https://github.com/mono/mono/issues/17278
|
||||
|
||||
/*
|
||||
if (loggingLevel >= LoggingLevel.Warnings)
|
||||
{
|
||||
Debug.LogWarning($"Unable to extract command data from type {type} in assembly {assembly.GetName().Name} as it may be corrupted. The following exception was thrown: {e.Message}");
|
||||
}
|
||||
*/
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void LoadCommandsFromType(Type type)
|
||||
{
|
||||
if (type.HasAttribute<QcIgnoreAttribute>(false)) return;
|
||||
if (type.HasAttribute<CompilerGeneratedAttribute>(true)) { return; }
|
||||
|
||||
foreach ((MethodInfo method, MemberInfo member) in ExtractCommandMethods(type))
|
||||
{
|
||||
if (member.DeclaringType == type)
|
||||
{
|
||||
LoadCommandsFromMember(member, method);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void LoadCommandsFromMember(MemberInfo member, MethodInfo method)
|
||||
{
|
||||
IEnumerable<CommandAttribute> commandAttributes = member.GetCustomAttributes<CommandAttribute>();
|
||||
CommandDescriptionAttribute descriptionAttribute = member.GetCustomAttribute<CommandDescriptionAttribute>();
|
||||
|
||||
foreach (CommandAttribute commandAttribute in commandAttributes)
|
||||
{
|
||||
if (!commandAttribute.Valid)
|
||||
{
|
||||
if (loggingLevel >= LoggingLevel.Warnings)
|
||||
{
|
||||
Debug.LogWarning($"Quantum Processor Warning: Could not add '{commandAttribute.Alias}' to the table as it is invalid.");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
CommandPlatformAttribute platformAttribute = member.GetCustomAttribute<CommandPlatformAttribute>();
|
||||
Platform commandPlatforms = platformAttribute?.SupportedPlatforms ?? commandAttribute.SupportedPlatforms;
|
||||
if (commandPlatforms.HasFlag(Application.platform.ToPlatform()))
|
||||
{
|
||||
IEnumerable<CommandData> newCommands = CreateCommandOverloads(method, commandAttribute, descriptionAttribute);
|
||||
foreach (CommandData command in newCommands)
|
||||
{
|
||||
TryAddCommand(command);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static IEnumerable<CommandData> CreateCommandOverloads(MethodInfo method, CommandAttribute commandAttribute, CommandDescriptionAttribute descriptionAttribute)
|
||||
{
|
||||
int defaultParameters = method.GetParameters().Count(x => x.HasDefaultValue);
|
||||
for (int i = 0; i < defaultParameters + 1; i++)
|
||||
{
|
||||
CommandData command = new CommandData(method, commandAttribute, descriptionAttribute, i);
|
||||
yield return command;
|
||||
}
|
||||
}
|
||||
|
||||
private static string GenerateCommandKey(CommandData command)
|
||||
{
|
||||
return $"{command.CommandName}({command.ParamCount})";
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Registers a new command.
|
||||
/// </summary>
|
||||
/// <param name="command">The command to register.</param>
|
||||
/// <returns>If the addition was successful.</returns>
|
||||
public static bool TryAddCommand(CommandData command)
|
||||
{
|
||||
if (!GetCommandSupported(command, out string reason))
|
||||
{
|
||||
if (loggingLevel >= LoggingLevel.Warnings)
|
||||
{
|
||||
Debug.LogWarning($"Quantum Processor Warning: Could not add '{command.CommandSignature}' from {command.MethodData.DeclaringType.GetDisplayName()} " +
|
||||
$"to the table as it is not supported. {reason}");
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
string key = GenerateCommandKey(command);
|
||||
bool alreadyExists = !_commandTable.TryAdd(key, command);
|
||||
|
||||
if (alreadyExists)
|
||||
{
|
||||
if (loggingLevel >= LoggingLevel.Warnings)
|
||||
{
|
||||
string fullMethodName = $"{command.MethodData.DeclaringType.FullName}.{command.MethodData.Name}";
|
||||
Debug.LogWarning($"Quantum Processor Warning: Could not add {fullMethodName} to the table as another method with the same alias and parameter count, {key}, already exists.");
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
Interlocked.Increment(ref _loadedCommandCount);
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Removes an existing command.
|
||||
/// </summary>
|
||||
/// <param name="command">The command to remove.</param>
|
||||
/// <returns>If the removal was successful.</returns>
|
||||
public static bool TryRemoveCommand(CommandData command)
|
||||
{
|
||||
string key = GenerateCommandKey(command);
|
||||
if (_commandTable.TryRemove(key, out _))
|
||||
{
|
||||
Interlocked.Decrement(ref _loadedCommandCount);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Command Invocation
|
||||
/// <summary>Invokes a command on the QuantumConsoleProcessor.</summary>
|
||||
/// <returns>Return value of the invocation.</returns>
|
||||
/// <param name="commandString">The command to invoke.</param>
|
||||
public static object InvokeCommand(string commandString)
|
||||
{
|
||||
GenerateCommandTable();
|
||||
|
||||
commandString = commandString.Trim();
|
||||
commandString = _preprocessor.Process(commandString);
|
||||
|
||||
if (string.IsNullOrWhiteSpace(commandString)) { throw new ArgumentException("Cannot parse an empty string."); }
|
||||
string[] commandParts = commandString.SplitScoped(' ');
|
||||
commandParts = commandParts.Where(x => !string.IsNullOrWhiteSpace(x)).ToArray();
|
||||
|
||||
string commandName = commandParts[0];
|
||||
string[] commandParams = commandParts.SubArray(1, commandParts.Length - 1);
|
||||
int paramCount = commandParams.Length;
|
||||
|
||||
string[] commandNameParts = commandName.Split(new[] { '<' }, 2);
|
||||
string genericSignature = commandNameParts.Length > 1 ? $"<{commandNameParts[1]}" : "";
|
||||
commandName = commandNameParts[0];
|
||||
|
||||
string keyName = $"{commandName}({paramCount})";
|
||||
if (!_commandTable.ContainsKey(keyName))
|
||||
{
|
||||
bool overloadExists = _commandTable.Keys.Any(key => key.Contains($"{commandName}(") && _commandTable[key].CommandName == commandName);
|
||||
if (overloadExists) { throw new ArgumentException($"No overload of '{commandName}' with {paramCount} parameters could be found."); }
|
||||
else { throw new ArgumentException($"Command '{commandName}' could not be found."); }
|
||||
}
|
||||
CommandData command = _commandTable[keyName];
|
||||
|
||||
Type[] genericTypes = Array.Empty<Type>();
|
||||
if (command.IsGeneric)
|
||||
{
|
||||
int expectedArgCount = command.GenericParamTypes.Length;
|
||||
string[] genericArgNames = genericSignature.ReduceScope('<', '>').SplitScoped(',');
|
||||
if (genericArgNames.Length == expectedArgCount)
|
||||
{
|
||||
genericTypes = new Type[genericArgNames.Length];
|
||||
for (int i = 0; i < genericTypes.Length; i++)
|
||||
{
|
||||
genericTypes[i] = QuantumParser.ParseType(genericArgNames[i]);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new ArgumentException($"Generic command '{commandName}' requires {expectedArgCount} generic parameter{(expectedArgCount == 1 ? "" : "s")} but was supplied with {genericArgNames.Length}.");
|
||||
}
|
||||
}
|
||||
else if (genericSignature != string.Empty)
|
||||
{
|
||||
throw new ArgumentException($"Command '{commandName}' is not a generic command and cannot be invoked as such.");
|
||||
}
|
||||
|
||||
#if !UNITY_EDITOR && ENABLE_IL2CPP
|
||||
if (genericTypes.Any((Type x) => x.IsValueType))
|
||||
{
|
||||
throw new NotSupportedException("Value types in generic commands are not currently supported by Unity in IL2CPP");
|
||||
}
|
||||
#endif
|
||||
|
||||
object[] parsedCommandParams = ParseParamData(command.MakeGenericArguments(genericTypes), commandParams);
|
||||
return command.Invoke(parsedCommandParams, genericTypes);
|
||||
}
|
||||
|
||||
private static object[] ParseParamData(Type[] paramTypes, string[] paramData)
|
||||
{
|
||||
object[] parsedData = new object[paramData.Length];
|
||||
for (int i = 0; i < parsedData.Length; i++)
|
||||
{
|
||||
parsedData[i] = _parser.Parse(paramData[i], paramTypes[i]);
|
||||
}
|
||||
|
||||
return parsedData;
|
||||
}
|
||||
#endregion
|
||||
|
||||
/// <summary>Gets suggestions for possible commands given the currently entered command fragment.</summary>
|
||||
/// <returns>All commands suggested for the provided fragment.</returns>
|
||||
/// <param name="incompleteCommandName">Incomplete command name to base the search off of.</param>
|
||||
/// <param name="fuzzy">If fuzzy search is disabled, then your current search must match the beginning of the command to be suggested (foo*). If fuzzy search is enabled, it can be anywhere within the command name to be suggested (*foo*).</param>
|
||||
/// <param name="caseSensitive">If the search should be case sensitive or not.</param>
|
||||
/// <param name="includeOverloads">If multiple overloads of the same command should be included.</param>
|
||||
public static IEnumerable<CommandData> GetCommandSuggestions(string incompleteCommandName, bool fuzzy = false, bool caseSensitive = true, bool includeOverloads = true)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(incompleteCommandName))
|
||||
{
|
||||
return Enumerable.Empty<CommandData>();
|
||||
}
|
||||
|
||||
HashSet<string> foundNames = includeOverloads ? null : new HashSet<string>();
|
||||
List<CommandData> foundCommands = new List<CommandData>();
|
||||
|
||||
bool MatchFound(string incompleteCommand, string commandSuggestion)
|
||||
{
|
||||
if (commandSuggestion.Length < incompleteCommand.Length) { return false; }
|
||||
|
||||
if (fuzzy)
|
||||
{
|
||||
if (caseSensitive) { return commandSuggestion.Contains(incompleteCommand); }
|
||||
else { return commandSuggestion.ContainsCaseInsensitive(incompleteCommand); }
|
||||
}
|
||||
else
|
||||
{
|
||||
return commandSuggestion.StartsWith(incompleteCommand, !caseSensitive, null);
|
||||
}
|
||||
}
|
||||
|
||||
foreach (CommandData command in _commandTable.Values)
|
||||
{
|
||||
if (includeOverloads || !foundNames.Contains(command.CommandName))
|
||||
{
|
||||
if (MatchFound(incompleteCommandName, command.CommandName))
|
||||
{
|
||||
if (!includeOverloads) { foundNames.Add(command.CommandName); }
|
||||
foundCommands.Add(command);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
IOrderedEnumerable<CommandData> sortedSuggestions;
|
||||
|
||||
if (includeOverloads)
|
||||
{
|
||||
sortedSuggestions = foundCommands.OrderBy(x => x.ParamCount)
|
||||
.OrderBy(x => x.CommandName)
|
||||
.OrderBy(x => x.CommandName.Length);
|
||||
}
|
||||
else
|
||||
{
|
||||
sortedSuggestions = foundCommands.OrderBy(x => x.CommandName)
|
||||
.OrderBy(x => x.CommandName.Length);
|
||||
}
|
||||
|
||||
if (fuzzy)
|
||||
{
|
||||
if (caseSensitive)
|
||||
{
|
||||
sortedSuggestions = sortedSuggestions.OrderBy(x => x.CommandName.IndexOf(incompleteCommandName, StringComparison.CurrentCulture));
|
||||
}
|
||||
else
|
||||
{
|
||||
sortedSuggestions = sortedSuggestions.OrderBy(x => x.CommandName.IndexOf(incompleteCommandName, StringComparison.CurrentCultureIgnoreCase));
|
||||
}
|
||||
}
|
||||
|
||||
return sortedSuggestions;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 6fb22d374d9f13f4599f9b4bd7351078
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,25 @@
|
|||
using UnityEngine;
|
||||
|
||||
namespace QFSW.QC
|
||||
{
|
||||
[CreateAssetMenu(fileName = "Untitled Key Config", menuName = "Quantum Console/Key Config")]
|
||||
public class QuantumKeyConfig : ScriptableObject
|
||||
{
|
||||
public KeyCode SubmitCommandKey = KeyCode.Return;
|
||||
public ModifierKeyCombo ShowConsoleKey = KeyCode.None;
|
||||
public ModifierKeyCombo HideConsoleKey = KeyCode.None;
|
||||
public ModifierKeyCombo ToggleConsoleVisibilityKey = KeyCode.Escape;
|
||||
|
||||
public ModifierKeyCombo ZoomInKey = new ModifierKeyCombo { Key = KeyCode.Equals, Ctrl = true };
|
||||
public ModifierKeyCombo ZoomOutKey = new ModifierKeyCombo { Key = KeyCode.Minus, Ctrl = true };
|
||||
public ModifierKeyCombo DragConsoleKey = new ModifierKeyCombo { Key = KeyCode.Mouse0, Shift = true };
|
||||
|
||||
public ModifierKeyCombo SuggestNextCommandKey = KeyCode.Tab;
|
||||
public ModifierKeyCombo SuggestPreviousCommandKey = new ModifierKeyCombo { Key = KeyCode.Tab, Shift = true };
|
||||
|
||||
public KeyCode NextCommandKey = KeyCode.UpArrow;
|
||||
public KeyCode PreviousCommandKey = KeyCode.DownArrow;
|
||||
|
||||
public ModifierKeyCombo CancelActionsKey = new ModifierKeyCombo { Key = KeyCode.C, Ctrl = true };
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: a59acf1affd56c94fa937563dd75c947
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,163 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
|
||||
namespace QFSW.QC
|
||||
{
|
||||
public static class QuantumMacros
|
||||
{
|
||||
private class MacroPreprocessor : IQcPreprocessor
|
||||
{
|
||||
public int Priority => 1000;
|
||||
|
||||
public string Process(string text)
|
||||
{
|
||||
if (!text.StartsWith("#define", StringComparison.CurrentCulture))
|
||||
{
|
||||
text = ExpandMacros(text);
|
||||
}
|
||||
|
||||
return text;
|
||||
}
|
||||
}
|
||||
|
||||
private static readonly Dictionary<string, string> _macroTable = new Dictionary<string, string>();
|
||||
|
||||
/// <summary>
|
||||
/// Expands all the macros in the given text.
|
||||
/// </summary>
|
||||
/// <returns>The macro expanded text.</returns>
|
||||
/// <param name="text">The text to expand the macros in.</param>
|
||||
/// <param name="maximumExpansions">The maximum number of macro expansions that can be performed before an exception is thrown.</param>
|
||||
public static string ExpandMacros(string text, int maximumExpansions = 1000)
|
||||
{
|
||||
if (_macroTable.Count == 0) { return text; }
|
||||
|
||||
int expansionCount = 0;
|
||||
for (int i = 0; i < text.Length; i++)
|
||||
{
|
||||
if (text[i] == '#')
|
||||
{
|
||||
foreach (KeyValuePair<string, string> macro in _macroTable)
|
||||
{
|
||||
int keyLength = macro.Key.Length;
|
||||
if (i + keyLength < text.Length)
|
||||
{
|
||||
if (text.Substring(i + 1, keyLength) == macro.Key)
|
||||
{
|
||||
if (expansionCount >= maximumExpansions)
|
||||
{
|
||||
throw new ArgumentException($"Maximum macro expansions of {maximumExpansions} was exhausted: infinitely recursive macro is likely.");
|
||||
}
|
||||
else
|
||||
{
|
||||
string start = text.Substring(0, i);
|
||||
string end = text.Substring(i + 1 + keyLength);
|
||||
text = $"{start}{macro.Value}{end}";
|
||||
|
||||
expansionCount++;
|
||||
i--;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return text;
|
||||
}
|
||||
|
||||
[Command("#define")]
|
||||
[CommandDescription("Adds a macro to the macro table which can then be used in the Quantum Console. If the macro 'name' is added, " +
|
||||
"then all instances of '#name' will be expanded into the full macro expansion. This allows you to define " +
|
||||
"shortcuts for various things such as long type names or commonly used command strings.\n\n" +
|
||||
"Macros may not contain hashtags or whitespace in their name.\n\n" +
|
||||
"Note: macros will not be expanded when using #define, this is so that defining nested macros is possible.")]
|
||||
public static void DefineMacro(string macroName, string macroExpansion)
|
||||
{
|
||||
macroName = macroName.Trim();
|
||||
if (macroName.Contains(' ')) { throw new ArgumentException("Macro names cannot contain whitespace."); }
|
||||
if (macroName.Contains('\n')) { throw new ArgumentException("Macro names cannot contain newlines."); }
|
||||
if (macroName.Contains('#')) { throw new ArgumentException("Macro names cannot contain hashtags."); }
|
||||
if (macroName == "define") { throw new ArgumentException("Macros cannot be named define."); }
|
||||
if (macroExpansion.Contains('\n')) { throw new ArgumentException("Macro names cannot contain newlines."); }
|
||||
if (macroExpansion.Contains($"#{macroName}")) { throw new ArgumentException("Macros cannot contain themselves within the expansion."); }
|
||||
|
||||
if (_macroTable.ContainsKey(macroName)) { _macroTable[macroName] = macroExpansion; }
|
||||
else { _macroTable.Add(macroName, macroExpansion); }
|
||||
}
|
||||
|
||||
[Command("remove-macro")]
|
||||
[CommandDescription("Removes the specified macro from the macro table")]
|
||||
public static void RemoveMacro(string macroName)
|
||||
{
|
||||
if (_macroTable.ContainsKey(macroName)) { _macroTable.Remove(macroName); }
|
||||
else { throw new Exception($"Specified macro #{macroName} as it was not defined."); }
|
||||
}
|
||||
|
||||
[Command("clear-macros")]
|
||||
[CommandDescription("Clears the macro table")]
|
||||
public static void ClearMacros() { _macroTable.Clear(); }
|
||||
|
||||
[Command("all-macros", "Displays all of the macros currently stored in the macro table")]
|
||||
private static string GetAllMacros()
|
||||
{
|
||||
if (_macroTable.Count == 0) { return "Macro table is empty"; }
|
||||
else { return $"Macro table:\n{string.Join("\n", _macroTable.Select((x) => $"#{x.Key} = {x.Value}"))}"; }
|
||||
}
|
||||
|
||||
[Command("dump-macros", "Creates a file dump of macro table which can the be loaded to repopulate the table using load-macros")]
|
||||
[CommandPlatform(Platform.AllPlatforms ^ (Platform.WebGLPlayer))]
|
||||
public static void DumpMacrosToFile(string filePath)
|
||||
{
|
||||
using (StreamWriter dumpFile = new StreamWriter(filePath))
|
||||
{
|
||||
foreach (KeyValuePair<string, string> macro in _macroTable)
|
||||
{
|
||||
dumpFile.WriteLine($"{macro.Key} {macro.Value}");
|
||||
}
|
||||
|
||||
dumpFile.Flush();
|
||||
dumpFile.Close();
|
||||
}
|
||||
}
|
||||
|
||||
[Command("load-macros", "Loads macros from an external file into the macro table")]
|
||||
[CommandPlatform(Platform.AllPlatforms ^ (Platform.WebGLPlayer))]
|
||||
public static string LoadMacrosFromFile(string filePath)
|
||||
{
|
||||
if (!File.Exists(filePath))
|
||||
{
|
||||
throw new ArgumentException($"file at the specified path '{filePath}' did not exist.");
|
||||
}
|
||||
|
||||
using (StreamReader macroFile = new StreamReader(filePath))
|
||||
{
|
||||
List<string> messages = new List<string>();
|
||||
while (!macroFile.EndOfStream)
|
||||
{
|
||||
string line = macroFile.ReadLine();
|
||||
string[] parts = line.Split(" ".ToCharArray(), 2);
|
||||
if (parts.Length != 2)
|
||||
{
|
||||
messages.Add($"'{line}' is not a valid macro definition");
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
DefineMacro(parts[0], parts[1]);
|
||||
messages.Add($"#{parts[0]} was successfully defined");
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
messages.Add($"#{parts[0]} could not be defined: {e.Message}");
|
||||
}
|
||||
}
|
||||
|
||||
macroFile.Close();
|
||||
return string.Join("\n", messages);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 05bc585af49664b3c8b92ae33adf1965
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,149 @@
|
|||
using QFSW.QC.Utilities;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace QFSW.QC
|
||||
{
|
||||
public static class QuantumRegistry
|
||||
{
|
||||
private static readonly Dictionary<Type, List<object>> _objectRegistry = new Dictionary<Type, List<object>>();
|
||||
|
||||
private static bool IsNull(object x)
|
||||
{
|
||||
if (x is UnityEngine.Object u)
|
||||
{
|
||||
return !u;
|
||||
}
|
||||
|
||||
return x is null;
|
||||
}
|
||||
|
||||
/// <summary>Adds the object to the registry.</summary>
|
||||
/// <param name="obj">The object to add to the registry.</param>
|
||||
/// <typeparam name="T">The type of the object to add to the registry.</typeparam>
|
||||
[Command("register-object", "Adds the object to the registry to be used by commands with MonoTargetType = Registry")]
|
||||
public static void RegisterObject<T>(T obj) where T : class { RegisterObject(typeof(T), obj); }
|
||||
|
||||
/// <summary>Adds the object to the registry.</summary>
|
||||
/// <param name="type">The type of the object to add to the registry.</param>
|
||||
/// <param name="obj">The object to add to the registry.</param>
|
||||
public static void RegisterObject(Type type, object obj)
|
||||
{
|
||||
if (!type.IsClass) { throw new Exception("Registry may only contain class types"); }
|
||||
lock (_objectRegistry)
|
||||
{
|
||||
if (_objectRegistry.ContainsKey(type))
|
||||
{
|
||||
if (_objectRegistry[type].Contains(obj))
|
||||
{
|
||||
throw new ArgumentException($"Could not register object '{obj}' of type {type.GetDisplayName()} as it was already registered.");
|
||||
}
|
||||
|
||||
_objectRegistry[type].Add(obj);
|
||||
}
|
||||
else
|
||||
{
|
||||
_objectRegistry.Add(type, new List<object>() { obj });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Removes the object from the registry.</summary>
|
||||
/// <param name="obj">The object to remove from the registry.</param>
|
||||
/// <typeparam name="T">The type of the object to remove from the registry.</typeparam>
|
||||
[Command("deregister-object", "Removes the object to the registry to be used by commands with MonoTargetType = Registry")]
|
||||
public static void DeregisterObject<T>(T obj) where T : class { DeregisterObject(typeof(T), obj); }
|
||||
|
||||
/// <summary>Removes the object to the registry.</summary>
|
||||
/// <param name="type">The type of the object to remove from the registry.</param>
|
||||
/// <param name="obj">The object to remove from the registry.</param>
|
||||
public static void DeregisterObject(Type type, object obj)
|
||||
{
|
||||
if (!type.IsClass) { throw new Exception("Registry may only contain class types"); }
|
||||
lock (_objectRegistry)
|
||||
{
|
||||
if (_objectRegistry.ContainsKey(type) && _objectRegistry[type].Contains(obj))
|
||||
{
|
||||
_objectRegistry[type].Remove(obj);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new ArgumentException($"Could not deregister object '{obj}' of type {type.GetDisplayName()} as it was not found in the registry.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Gets the size of the specified registry.</summary>
|
||||
/// <returns>The registry size.</returns>
|
||||
/// <typeparam name="T">The registry to query.</typeparam>
|
||||
public static int GetRegistrySize<T>() where T : class { return GetRegistrySize(typeof(T)); }
|
||||
|
||||
/// <summary>Gets the size of the specified registry.</summary>
|
||||
/// <returns>The registry size.</returns>
|
||||
/// <param name="type">The registry to query.</param>
|
||||
public static int GetRegistrySize(Type type)
|
||||
{
|
||||
return GetRegistryContents(type).Count();
|
||||
}
|
||||
|
||||
/// <summary>Gets the contents of the specified registry.</summary>
|
||||
/// <returns>The registry contents.</returns>
|
||||
/// <typeparam name="T">The registry to query.</typeparam>
|
||||
public static IEnumerable<T> GetRegistryContents<T>() where T : class
|
||||
{
|
||||
foreach (object obj in GetRegistryContents(typeof(T)))
|
||||
{
|
||||
yield return (T)obj;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Gets the contents of the specified registry.</summary>
|
||||
/// <returns>The registry contents.</returns>
|
||||
/// <param name="type">The registry to query.</param>
|
||||
public static IEnumerable<object> GetRegistryContents(Type type)
|
||||
{
|
||||
if (!type.IsClass) { throw new Exception("Registry may only contain class types"); }
|
||||
lock (_objectRegistry)
|
||||
{
|
||||
if (_objectRegistry.ContainsKey(type))
|
||||
{
|
||||
List<object> registry = _objectRegistry[type];
|
||||
registry.RemoveAll(IsNull);
|
||||
return registry;
|
||||
}
|
||||
|
||||
return Enumerable.Empty<object>();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>clears the contents of the specified registry.</summary>
|
||||
/// <typeparam name="T">The registry to clear.</typeparam>
|
||||
public static void ClearRegistryContents<T>() where T : class
|
||||
{
|
||||
ClearRegistryContents(typeof(T));
|
||||
}
|
||||
|
||||
/// <summary>clears the contents of the specified registry.</summary>
|
||||
/// <param name="type">The registry to clear.</param>
|
||||
public static void ClearRegistryContents(Type type)
|
||||
{
|
||||
if (!type.IsClass) { throw new Exception("Registry may only contain class types"); }
|
||||
lock (_objectRegistry)
|
||||
{
|
||||
if (_objectRegistry.ContainsKey(type))
|
||||
{
|
||||
_objectRegistry.Clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[Command("display-registry", "Displays the contents of the specified registry")]
|
||||
private static string DisplayRegistry([CommandParameterDescription("Full namespace qualified name of the type of the registry.")]Type type)
|
||||
{
|
||||
int registrySize = GetRegistrySize(type);
|
||||
if (registrySize < 1) { return $"registry '{type.GetDisplayName()}' was empty"; }
|
||||
else { return string.Join("\n", GetRegistryContents(type).Select(x => x.ToString())); }
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 1f66fabefb8ae475e982456889549b97
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,74 @@
|
|||
using QFSW.QC.Utilities;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using TMPro;
|
||||
using UnityEngine;
|
||||
|
||||
namespace QFSW.QC
|
||||
{
|
||||
[CreateAssetMenu(fileName = "Untitled Theme", menuName = "Quantum Console/Theme")]
|
||||
public class QuantumTheme : ScriptableObject
|
||||
{
|
||||
[SerializeField] public TMP_FontAsset Font = null;
|
||||
[SerializeField] public Material PanelMaterial = null;
|
||||
[SerializeField] public Color PanelColor = Color.white;
|
||||
|
||||
[SerializeField] public Color CommandLogColor = new Color(0, 1, 1);
|
||||
[SerializeField] public Color SelectedSuggestionColor = new Color(1, 1, 0.55f);
|
||||
[SerializeField] public Color SuggestionColor = Color.gray;
|
||||
[SerializeField] public Color ErrorColor = Color.red;
|
||||
[SerializeField] public Color WarningColor = new Color(1, 0.5f, 0);
|
||||
[SerializeField] public Color SuccessColor = Color.green;
|
||||
|
||||
[SerializeField] public string TimestampFormat = "[{0}:{1}:{2}]";
|
||||
|
||||
[SerializeField] public Color DefaultReturnValueColor = Color.white;
|
||||
[SerializeField] public List<TypeColorFormatter> TypeFormatters = new List<TypeColorFormatter>(0);
|
||||
[SerializeField] public List<CollectionFormatter> CollectionFormatters = new List<CollectionFormatter>(0);
|
||||
|
||||
private T FindTypeFormatter<T>(List<T> formatters, Type type) where T : TypeFormatter
|
||||
{
|
||||
foreach (T formatter in formatters)
|
||||
{
|
||||
if (type == formatter.Type || type.IsGenericTypeOf(formatter.Type))
|
||||
{
|
||||
return formatter;
|
||||
}
|
||||
}
|
||||
|
||||
foreach (T formatter in formatters)
|
||||
{
|
||||
if (formatter.Type.IsAssignableFrom(type))
|
||||
{
|
||||
return formatter;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public string ColorizeReturn(string data, Type type)
|
||||
{
|
||||
TypeColorFormatter formatter = FindTypeFormatter(TypeFormatters, type);
|
||||
if (formatter == null) { return data.ColorText(DefaultReturnValueColor); }
|
||||
else { return data.ColorText(formatter.Color); }
|
||||
}
|
||||
|
||||
public void GetCollectionFormatting(Type type, out string leftScoper, out string seperator, out string rightScoper)
|
||||
{
|
||||
CollectionFormatter formatter = FindTypeFormatter(CollectionFormatters, type);
|
||||
if (formatter == null)
|
||||
{
|
||||
leftScoper = "[";
|
||||
seperator = ",";
|
||||
rightScoper = "]";
|
||||
}
|
||||
else
|
||||
{
|
||||
leftScoper = formatter.LeftScoper.Replace("\\n", "\n");
|
||||
seperator = formatter.SeperatorString.Replace("\\n", "\n");
|
||||
rightScoper = formatter.RightScoper.Replace("\\n", "\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 49e15215dd5c7444aa955d9a8a83fea0
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,8 @@
|
|||
fileFormatVersion: 2
|
||||
guid: cab58cf9e8aea91499df0cc05f876361
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,33 @@
|
|||
using System;
|
||||
|
||||
namespace QFSW.QC
|
||||
{
|
||||
/// <summary>
|
||||
/// Serializer for a single type.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The type to serialize.</typeparam>
|
||||
public abstract class BasicQcSerializer<T> : IQcSerializer
|
||||
{
|
||||
private Func<object, QuantumTheme, string> _recursiveSerializer;
|
||||
|
||||
public virtual int Priority => 0;
|
||||
|
||||
public bool CanSerialize(Type type)
|
||||
{
|
||||
return type == typeof(T);
|
||||
}
|
||||
|
||||
string IQcSerializer.SerializeFormatted(object value, QuantumTheme theme, Func<object, QuantumTheme, string> recursiveSerializer)
|
||||
{
|
||||
_recursiveSerializer = recursiveSerializer;
|
||||
return SerializeFormatted((T)value, theme);
|
||||
}
|
||||
|
||||
protected string SerializeRecursive(object value, QuantumTheme theme)
|
||||
{
|
||||
return _recursiveSerializer(value, theme);
|
||||
}
|
||||
|
||||
public abstract string SerializeFormatted(T value, QuantumTheme theme);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 8ca902898efebc44eb68a9de6f50a37b
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,51 @@
|
|||
using QFSW.QC.Utilities;
|
||||
using System;
|
||||
|
||||
namespace QFSW.QC
|
||||
{
|
||||
/// <summary>
|
||||
/// Serializer for all types that are generic constructions of a single type.
|
||||
/// </summary>
|
||||
public abstract class GenericQcSerializer : IQcSerializer
|
||||
{
|
||||
/// <summary>
|
||||
/// The incomplete generic type of this serializer.
|
||||
/// </summary>
|
||||
protected abstract Type GenericType { get; }
|
||||
|
||||
private Func<object, QuantumTheme, string> _recursiveSerializer;
|
||||
|
||||
protected GenericQcSerializer()
|
||||
{
|
||||
if (!GenericType.IsGenericType)
|
||||
{
|
||||
throw new ArgumentException($"Generic Serializers must use a generic type as their base");
|
||||
}
|
||||
|
||||
if (GenericType.IsConstructedGenericType)
|
||||
{
|
||||
throw new ArgumentException($"Generic Serializers must use an incomplete generic type as their base");
|
||||
}
|
||||
}
|
||||
|
||||
public virtual int Priority => -500;
|
||||
|
||||
public bool CanSerialize(Type type)
|
||||
{
|
||||
return type.IsGenericTypeOf(GenericType);
|
||||
}
|
||||
|
||||
string IQcSerializer.SerializeFormatted(object value, QuantumTheme theme, Func<object, QuantumTheme, string> recursiveSerializer)
|
||||
{
|
||||
_recursiveSerializer = recursiveSerializer;
|
||||
return SerializeFormatted(value, theme);
|
||||
}
|
||||
|
||||
protected string SerializeRecursive(object value, QuantumTheme theme)
|
||||
{
|
||||
return _recursiveSerializer(value, theme);
|
||||
}
|
||||
|
||||
public abstract string SerializeFormatted(object value, QuantumTheme theme);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: a7640a2497d7d04489df10e2a4d1c7ad
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,31 @@
|
|||
using System;
|
||||
|
||||
namespace QFSW.QC
|
||||
{
|
||||
/// <summary>
|
||||
/// Creates a Serializer that is loaded and used by the QuantumSerializer.
|
||||
/// </summary>
|
||||
public interface IQcSerializer
|
||||
{
|
||||
/// <summary>
|
||||
/// The priority of this serializer to resolve multiple serializers covering the same type.
|
||||
/// </summary>
|
||||
int Priority { get; }
|
||||
|
||||
/// <summary>
|
||||
/// If this serializer can serialize the incoming type.
|
||||
/// </summary>
|
||||
/// <param name="type">The type to test.</param>
|
||||
/// <returns>If it can serialize.</returns>
|
||||
bool CanSerialize(Type type);
|
||||
|
||||
/// <summary>
|
||||
/// Serializes the incoming data.
|
||||
/// </summary>
|
||||
/// <param name="value">The value to serialize.</param>
|
||||
/// <param name="theme">The (optional) theme to use for formatted serialization.</param>
|
||||
/// <param name="recursiveSerializer">Delegate back to the main serializer to allow for recursive serialization of sub elements.</param>
|
||||
/// <returns>The serialized result.</returns>
|
||||
string SerializeFormatted(object value, QuantumTheme theme, Func<object, QuantumTheme, string> recursiveSerializer);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 34cdc555ca8a54e44863b4552852df71
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,33 @@
|
|||
using System;
|
||||
|
||||
namespace QFSW.QC
|
||||
{
|
||||
/// <summary>
|
||||
/// Serializer for all types inheriting from a single type.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">Base type of the types to serialize.</typeparam>
|
||||
public abstract class PolymorphicQcSerializer<T> : IQcSerializer where T : class
|
||||
{
|
||||
private Func<object, QuantumTheme, string> _recursiveSerializer;
|
||||
|
||||
public virtual int Priority => -1000;
|
||||
|
||||
public bool CanSerialize(Type type)
|
||||
{
|
||||
return typeof(T).IsAssignableFrom(type);
|
||||
}
|
||||
|
||||
string IQcSerializer.SerializeFormatted(object value, QuantumTheme theme, Func<object, QuantumTheme, string> recursiveSerializer)
|
||||
{
|
||||
_recursiveSerializer = recursiveSerializer;
|
||||
return SerializeFormatted((T)value, theme);
|
||||
}
|
||||
|
||||
protected string SerializeRecursive(object value, QuantumTheme theme)
|
||||
{
|
||||
return _recursiveSerializer(value, theme);
|
||||
}
|
||||
|
||||
public abstract string SerializeFormatted(T value, QuantumTheme theme);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: fca63e83ffbf0884fb2f5910dc3ecec4
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,105 @@
|
|||
using QFSW.QC.Utilities;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace QFSW.QC
|
||||
{
|
||||
/// <summary>
|
||||
/// Handles formatted serialization for console returns.
|
||||
/// </summary>
|
||||
public class QuantumSerializer
|
||||
{
|
||||
private readonly IQcSerializer[] _serializers;
|
||||
private readonly Dictionary<Type, IQcSerializer> _serializerLookup = new Dictionary<Type, IQcSerializer>();
|
||||
private readonly HashSet<Type> _unserializableLookup = new HashSet<Type>();
|
||||
|
||||
private readonly Func<object, QuantumTheme, string> _recursiveSerializer;
|
||||
|
||||
/// <summary>
|
||||
/// Creates a Quantum Serializer with a custom set of serializers.
|
||||
/// </summary>
|
||||
/// <param name="serializers">The IQcSerializers to use in this Quantum Serializer.</param>
|
||||
public QuantumSerializer(IEnumerable<IQcSerializer> serializers)
|
||||
{
|
||||
_recursiveSerializer = SerializeFormatted;
|
||||
_serializers = serializers.OrderByDescending(x => x.Priority)
|
||||
.ToArray();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a Quantum Serializer with the default injected serializers
|
||||
/// </summary>
|
||||
public QuantumSerializer() : this(new InjectionLoader<IQcSerializer>().GetInjectedInstances())
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Serializes the object with formatting for displaying in the console.
|
||||
/// </summary>
|
||||
/// <param name="value">The value to format and serialize.</param>
|
||||
/// <param name="theme">(Optional) QuantumTheme to use for formatting the results.</param>
|
||||
/// <returns>The formatted serialization.</returns>
|
||||
public string SerializeFormatted(object value, QuantumTheme theme = null)
|
||||
{
|
||||
if (value is null)
|
||||
{
|
||||
return string.Empty;
|
||||
}
|
||||
|
||||
Type type = value.GetType();
|
||||
string result = string.Empty;
|
||||
|
||||
string SerializeInternal(IQcSerializer serializer)
|
||||
{
|
||||
try
|
||||
{
|
||||
return serializer.SerializeFormatted(value, theme, _recursiveSerializer);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
throw new Exception($"Serialization of {type.GetDisplayName()} via {serializer} failed:\n{e.Message}", e);
|
||||
}
|
||||
}
|
||||
|
||||
if (_serializerLookup.ContainsKey(type))
|
||||
{
|
||||
result = SerializeInternal(_serializerLookup[type]);
|
||||
}
|
||||
else if (_unserializableLookup.Contains(type))
|
||||
{
|
||||
result = value.ToString();
|
||||
}
|
||||
else
|
||||
{
|
||||
bool converted = false;
|
||||
|
||||
foreach (IQcSerializer serializer in _serializers)
|
||||
{
|
||||
if (serializer.CanSerialize(type))
|
||||
{
|
||||
result = SerializeInternal(serializer);
|
||||
|
||||
_serializerLookup[type] = serializer;
|
||||
converted = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!converted)
|
||||
{
|
||||
result = value.ToString();
|
||||
_unserializableLookup.Add(type);
|
||||
}
|
||||
}
|
||||
|
||||
if (theme && !string.IsNullOrWhiteSpace(result))
|
||||
{
|
||||
result = theme.ColorizeReturn(result, type);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: ee15beb7bc84a94449abebd99629b1bb
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,8 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 3ea795e317dd5b64f8b699ef7a640f92
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,15 @@
|
|||
using System.Collections;
|
||||
|
||||
namespace QFSW.QC.Serializers
|
||||
{
|
||||
public class DictionaryEntrySerializer : BasicQcSerializer<DictionaryEntry>
|
||||
{
|
||||
public override string SerializeFormatted(DictionaryEntry value, QuantumTheme theme)
|
||||
{
|
||||
string innerKey = SerializeRecursive(value.Key, theme);
|
||||
string innerValue = SerializeRecursive(value.Value, theme);
|
||||
|
||||
return $"{innerKey}: {innerValue}";
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 8f5ea7a0667903a4a81ff2b0253cf886
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,15 @@
|
|||
using System.Collections;
|
||||
|
||||
namespace QFSW.QC.Serializers
|
||||
{
|
||||
public class IDictionarySerializer : IEnumerableSerializer<IDictionary>
|
||||
{
|
||||
protected override IEnumerable GetObjectStream(IDictionary value)
|
||||
{
|
||||
foreach (DictionaryEntry item in value)
|
||||
{
|
||||
yield return item;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: ecd3d9e7bdfeaa1478f9a208e8251397
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,61 @@
|
|||
using System;
|
||||
using System.Collections;
|
||||
using System.Text;
|
||||
|
||||
namespace QFSW.QC.Serializers
|
||||
{
|
||||
public class IEnumerableSerializer : IEnumerableSerializer<IEnumerable>
|
||||
{
|
||||
public override int Priority => base.Priority - 1000;
|
||||
|
||||
protected override IEnumerable GetObjectStream(IEnumerable value)
|
||||
{
|
||||
return value;
|
||||
}
|
||||
}
|
||||
|
||||
public abstract class IEnumerableSerializer<T> : PolymorphicQcSerializer<T> where T : class, IEnumerable
|
||||
{
|
||||
private readonly Pool<StringBuilder> _builderPool = new Pool<StringBuilder>();
|
||||
|
||||
public override string SerializeFormatted(T value, QuantumTheme theme)
|
||||
{
|
||||
Type type = value.GetType();
|
||||
StringBuilder builder = _builderPool.GetObject();
|
||||
|
||||
string left = "[";
|
||||
string seperator = ",";
|
||||
string right = "]";
|
||||
if (theme)
|
||||
{
|
||||
theme.GetCollectionFormatting(type, out left, out seperator, out right);
|
||||
}
|
||||
|
||||
builder.Clear();
|
||||
builder.Append(left);
|
||||
|
||||
bool firstIteration = true;
|
||||
foreach (object item in GetObjectStream(value))
|
||||
{
|
||||
if (firstIteration)
|
||||
{
|
||||
firstIteration = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
builder.Append(seperator);
|
||||
}
|
||||
|
||||
builder.Append(SerializeRecursive(item, theme));
|
||||
}
|
||||
|
||||
builder.Append(right);
|
||||
|
||||
string result = builder.ToString();
|
||||
_builderPool.Release(builder);
|
||||
return result;
|
||||
}
|
||||
|
||||
protected abstract IEnumerable GetObjectStream(T value);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 85d1c77e99db74c4786c67db88eed3ce
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,21 @@
|
|||
#if !NET_STANDARD_2_0
|
||||
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
namespace QFSW.QC.Serializers
|
||||
{
|
||||
public class ITupleSerializer : PolymorphicQcSerializer<ITuple>
|
||||
{
|
||||
public override string SerializeFormatted(ITuple value, QuantumTheme theme)
|
||||
{
|
||||
string[] serializedItems = new string[value.Length];
|
||||
for (int i = 0; i < value.Length; i++)
|
||||
{
|
||||
serializedItems[i] = SerializeRecursive(value[i], theme);
|
||||
}
|
||||
|
||||
return $"({string.Join(", ", serializedItems)})";
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: a98f9dc2d30e50a4ea3e6b10d5af4d1a
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,46 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Reflection;
|
||||
|
||||
namespace QFSW.QC.Serializers
|
||||
{
|
||||
public class KeyValuePairSerializer : GenericQcSerializer
|
||||
{
|
||||
protected override Type GenericType { get; } = typeof(KeyValuePair<,>);
|
||||
|
||||
private readonly Dictionary<Type, PropertyInfo> _keyPropertyLookup = new Dictionary<Type, PropertyInfo>();
|
||||
private readonly Dictionary<Type, PropertyInfo> _valuePropertyLookup = new Dictionary<Type, PropertyInfo>();
|
||||
|
||||
public override string SerializeFormatted(object value, QuantumTheme theme)
|
||||
{
|
||||
Type type = value.GetType();
|
||||
PropertyInfo keyProperty;
|
||||
PropertyInfo valueProperty;
|
||||
|
||||
if (_keyPropertyLookup.ContainsKey(type))
|
||||
{
|
||||
keyProperty = _keyPropertyLookup[type];
|
||||
}
|
||||
else
|
||||
{
|
||||
keyProperty = type.GetProperty("Key");
|
||||
_keyPropertyLookup[type] = keyProperty;
|
||||
}
|
||||
|
||||
if (_valuePropertyLookup.ContainsKey(type))
|
||||
{
|
||||
valueProperty = _valuePropertyLookup[type];
|
||||
}
|
||||
else
|
||||
{
|
||||
valueProperty = type.GetProperty("Value");
|
||||
_valuePropertyLookup[type] = valueProperty;
|
||||
}
|
||||
|
||||
string innerKey = SerializeRecursive(keyProperty.GetValue(value, null), theme);
|
||||
string innerValue = SerializeRecursive(valueProperty.GetValue(value, null), theme);
|
||||
|
||||
return $"{innerKey}: {innerValue}";
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 90dd2bea123ca7a43b2aee4e0985bd0f
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,14 @@
|
|||
{
|
||||
"name": "QFSW.QC.Serializers",
|
||||
"references": [
|
||||
"QFSW.QC"
|
||||
],
|
||||
"optionalUnityReferences": [],
|
||||
"includePlatforms": [],
|
||||
"excludePlatforms": [],
|
||||
"allowUnsafeCode": false,
|
||||
"overrideReferences": false,
|
||||
"precompiledReferences": [],
|
||||
"autoReferenced": true,
|
||||
"defineConstraints": []
|
||||
}
|
|
@ -0,0 +1,7 @@
|
|||
fileFormatVersion: 2
|
||||
guid: b2b4ba6eb36b7bb49beadaf8e4db329a
|
||||
AssemblyDefinitionImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,12 @@
|
|||
namespace QFSW.QC.Serializers
|
||||
{
|
||||
public class StringSerializer : BasicQcSerializer<string>
|
||||
{
|
||||
public override int Priority => int.MaxValue;
|
||||
|
||||
public override string SerializeFormatted(string value, QuantumTheme theme)
|
||||
{
|
||||
return value;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: a7a677dc32186804cb64e985537c4e21
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,13 @@
|
|||
using QFSW.QC.Utilities;
|
||||
using System;
|
||||
|
||||
namespace QFSW.QC.Serializers
|
||||
{
|
||||
public class TypeSerialiazer : PolymorphicQcSerializer<Type>
|
||||
{
|
||||
public override string SerializeFormatted(Type value, QuantumTheme theme)
|
||||
{
|
||||
return value.GetDisplayName();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: a0081da50a0ad3743b7adaa7f49a327d
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,12 @@
|
|||
using UnityEngine;
|
||||
|
||||
namespace QFSW.QC.Serializers
|
||||
{
|
||||
public class UnityObjectSerializer : PolymorphicQcSerializer<Object>
|
||||
{
|
||||
public override string SerializeFormatted(Object value, QuantumTheme theme)
|
||||
{
|
||||
return value.name;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 85179674c3db5514082e498f38a169d6
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,12 @@
|
|||
using UnityEngine;
|
||||
|
||||
namespace QFSW.QC.Serializers
|
||||
{
|
||||
public class Vector2IntSerializer : BasicQcSerializer<Vector2Int>
|
||||
{
|
||||
public override string SerializeFormatted(Vector2Int value, QuantumTheme theme)
|
||||
{
|
||||
return $"({value.x}, {value.y})";
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: c966e27c828cfa84b80e8bf5c057176b
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,12 @@
|
|||
using UnityEngine;
|
||||
|
||||
namespace QFSW.QC.Serializers
|
||||
{
|
||||
public class Vector2Serializer : BasicQcSerializer<Vector2>
|
||||
{
|
||||
public override string SerializeFormatted(Vector2 value, QuantumTheme theme)
|
||||
{
|
||||
return $"({value.x}, {value.y})";
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 84fbe7c52769e5049af7ac1c1ccf0c1a
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,12 @@
|
|||
using UnityEngine;
|
||||
|
||||
namespace QFSW.QC.Serializers
|
||||
{
|
||||
public class Vector3IntSerializer : BasicQcSerializer<Vector3Int>
|
||||
{
|
||||
public override string SerializeFormatted(Vector3Int value, QuantumTheme theme)
|
||||
{
|
||||
return $"({value.x}, {value.y}, {value.z})";
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: e04a3eb24be1a7f4f80c1c53290fed34
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,12 @@
|
|||
using UnityEngine;
|
||||
|
||||
namespace QFSW.QC.Serializers
|
||||
{
|
||||
public class Vector3Serializer : BasicQcSerializer<Vector3>
|
||||
{
|
||||
public override string SerializeFormatted(Vector3 value, QuantumTheme theme)
|
||||
{
|
||||
return $"({value.x}, {value.y}, {value.z})";
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: d55001e28a383304ab174d2aed504aa6
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,12 @@
|
|||
using UnityEngine;
|
||||
|
||||
namespace QFSW.QC.Serializers
|
||||
{
|
||||
public class Vector4Serializer : BasicQcSerializer<Vector4>
|
||||
{
|
||||
public override string SerializeFormatted(Vector4 value, QuantumTheme theme)
|
||||
{
|
||||
return $"({value.x}, {value.y}, {value.z}, {value.w})";
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: af0a28dfe0d28b844b9ca788f93145c2
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,11 @@
|
|||
namespace QFSW.QC
|
||||
{
|
||||
/// <summary>
|
||||
/// Sort order options.
|
||||
/// </summary>
|
||||
public enum SortOrder
|
||||
{
|
||||
Ascending = 0,
|
||||
Descending = 1
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 0970a46bb4e45ab43a2bc7bc8b776e9a
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,25 @@
|
|||
using TMPro;
|
||||
using UnityEngine;
|
||||
using UnityEngine.EventSystems;
|
||||
|
||||
namespace QFSW.QC
|
||||
{
|
||||
public class SuggestionDisplay : MonoBehaviour, IPointerClickHandler
|
||||
{
|
||||
[SerializeField] private QuantumConsole _quantumConsole = null;
|
||||
[SerializeField] private TextMeshProUGUI _textArea = null;
|
||||
|
||||
public void OnPointerClick(PointerEventData eventData)
|
||||
{
|
||||
int linkIndex = TMP_TextUtilities.FindIntersectingLink(_textArea, eventData.position, null);
|
||||
if (linkIndex >= 0)
|
||||
{
|
||||
TMP_LinkInfo link = _textArea.textInfo.linkInfo[linkIndex];
|
||||
if (int.TryParse(link.GetLinkID(), out int suggestionIndex))
|
||||
{
|
||||
_quantumConsole.SetCommandSuggestion(suggestionIndex);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: c57eacd1ea0009e4bb19fc30e8a32f07
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,13 @@
|
|||
namespace QFSW.QC
|
||||
{
|
||||
/// <summary>
|
||||
/// Which states of the build will be supported.
|
||||
/// </summary>
|
||||
public enum SupportedState
|
||||
{
|
||||
Always = 0,
|
||||
Development = 1,
|
||||
Editor = 2,
|
||||
Never = 3
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: c7235c8804e73e04ea64942b9b104dfa
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,65 @@
|
|||
using System;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Serialization;
|
||||
|
||||
#region Preserve Fix
|
||||
#if UNITY_2018_4_OR_NEWER
|
||||
using UnityEngine.Scripting;
|
||||
#else
|
||||
/// <summary>
|
||||
/// <para>PreserveAttribute prevents byte code stripping from removing a class, method, field, or property.</para>
|
||||
/// </summary>
|
||||
[AttributeUsage(AttributeTargets.Assembly | AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Enum | AttributeTargets.Constructor | AttributeTargets.Method | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Interface | AttributeTargets.Delegate, Inherited = false)]
|
||||
public sealed class PreserveAttribute : Attribute
|
||||
{
|
||||
}
|
||||
#endif
|
||||
#endregion
|
||||
|
||||
namespace QFSW.QC
|
||||
{
|
||||
[Serializable]
|
||||
public abstract class TypeFormatter : ISerializationCallbackReceiver
|
||||
{
|
||||
public Type Type { get; private set; }
|
||||
[SerializeField, HideInInspector] private string _type;
|
||||
|
||||
[Preserve]
|
||||
protected TypeFormatter(Type type) { Type = type; }
|
||||
|
||||
public void OnAfterDeserialize()
|
||||
{
|
||||
Type = Type.GetType(_type, false);
|
||||
if (Type == null) { Type = QuantumParser.ParseType(_type.Split(',')[0]); }
|
||||
}
|
||||
|
||||
public void OnBeforeSerialize()
|
||||
{
|
||||
if (Type != null) { _type = Type.AssemblyQualifiedName; }
|
||||
}
|
||||
}
|
||||
|
||||
[Serializable]
|
||||
public class TypeColorFormatter : TypeFormatter
|
||||
{
|
||||
[FormerlySerializedAs("color")]
|
||||
public Color Color = Color.white;
|
||||
|
||||
[Preserve]
|
||||
public TypeColorFormatter(Type type) : base(type) { }
|
||||
}
|
||||
|
||||
[Serializable]
|
||||
public class CollectionFormatter : TypeFormatter
|
||||
{
|
||||
[FormerlySerializedAs("seperatorString")]
|
||||
public string SeperatorString = ",";
|
||||
[FormerlySerializedAs("leftScoper")]
|
||||
public string LeftScoper = "[";
|
||||
[FormerlySerializedAs("rightScoper")]
|
||||
public string RightScoper = "]";
|
||||
|
||||
[Preserve]
|
||||
public CollectionFormatter(Type type) : base(type) { }
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: d74bd8bf31ee943da8e69911a852e4b5
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,8 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 4463cd27ce1497447be2ab49507ed2d3
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,23 @@
|
|||
using UnityEngine;
|
||||
|
||||
namespace QFSW.QC.UI
|
||||
{
|
||||
[ExecuteInEditMode]
|
||||
public class BlurShaderController : MonoBehaviour
|
||||
{
|
||||
[SerializeField] private Material _blurMaterial = null;
|
||||
[SerializeField] private float _blurRadius = 1f;
|
||||
[SerializeField] private Vector2 _referenceResolution = new Vector2(1920, 1080);
|
||||
|
||||
private void LateUpdate()
|
||||
{
|
||||
if (_blurMaterial)
|
||||
{
|
||||
Vector2 resolution = new Vector2(Screen.width, Screen.height);
|
||||
float correction = resolution.y / _referenceResolution.y;
|
||||
_blurMaterial.SetFloat("_Radius", _blurRadius);
|
||||
_blurMaterial.SetFloat("_BlurMultiplier", correction);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 71717f6dc91a9d44f954817d678345d2
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,68 @@
|
|||
using UnityEngine;
|
||||
using UnityEngine.Events;
|
||||
using UnityEngine.EventSystems;
|
||||
|
||||
namespace QFSW.QC.UI
|
||||
{
|
||||
[DisallowMultipleComponent]
|
||||
[RequireComponent(typeof(RectTransform))]
|
||||
public class DraggableUI : MonoBehaviour, IPointerDownHandler, IPointerUpHandler
|
||||
{
|
||||
[SerializeField] private RectTransform _dragRoot = null;
|
||||
[SerializeField] private QuantumConsole _quantumConsole = null;
|
||||
[SerializeField] private bool _lockInScreen = true;
|
||||
|
||||
[SerializeField] private UnityEvent _onBeginDrag = null;
|
||||
[SerializeField] private UnityEvent _onDrag = null;
|
||||
[SerializeField] private UnityEvent _onEndDrag = null;
|
||||
|
||||
private Vector2 _lastPos;
|
||||
private bool _isDragging = false;
|
||||
|
||||
public void OnPointerDown(PointerEventData eventData)
|
||||
{
|
||||
_isDragging =
|
||||
_quantumConsole &&
|
||||
_quantumConsole.KeyConfig &&
|
||||
_quantumConsole.KeyConfig.DragConsoleKey.IsHeld();
|
||||
|
||||
if (_isDragging)
|
||||
{
|
||||
_onBeginDrag.Invoke();
|
||||
_lastPos = eventData.position;
|
||||
}
|
||||
}
|
||||
|
||||
public void LateUpdate()
|
||||
{
|
||||
if (_isDragging)
|
||||
{
|
||||
Transform root = _dragRoot;
|
||||
if (!root) { root = transform as RectTransform; }
|
||||
|
||||
Vector2 pos = Input.mousePosition;
|
||||
Vector2 delta = pos - _lastPos;
|
||||
_lastPos = pos;
|
||||
|
||||
if (_lockInScreen)
|
||||
{
|
||||
Vector2 resolution = new Vector2(Screen.width, Screen.height);
|
||||
if (pos.x <= 0 || pos.x >= resolution.x) { delta.x = 0; }
|
||||
if (pos.y <= 0 || pos.y >= resolution.y) { delta.y = 0; }
|
||||
}
|
||||
|
||||
root.Translate(delta);
|
||||
_onDrag.Invoke();
|
||||
}
|
||||
}
|
||||
|
||||
public void OnPointerUp(PointerEventData eventData)
|
||||
{
|
||||
if (_isDragging)
|
||||
{
|
||||
_isDragging = false;
|
||||
_onEndDrag.Invoke();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: dddf2c665e079af45893ab7b0269d255
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,71 @@
|
|||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
|
||||
namespace QFSW.QC.UI
|
||||
{
|
||||
[ExecuteInEditMode]
|
||||
public class DynamicCanvasScaler : MonoBehaviour
|
||||
{
|
||||
public float RectMagnification
|
||||
{
|
||||
get => _rectMagnification;
|
||||
set
|
||||
{
|
||||
if (value > 0)
|
||||
{
|
||||
_rectMagnification = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
[Range(0.5f, 2f)]
|
||||
[SerializeField] private float _rectMagnification = 1f;
|
||||
|
||||
public float ZoomMagnification
|
||||
{
|
||||
get => _zoomMagnification;
|
||||
set
|
||||
{
|
||||
if (value > 0)
|
||||
{
|
||||
_zoomMagnification = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
[Range(0.5f, 2f)]
|
||||
[SerializeField] private float _zoomMagnification = 1f;
|
||||
|
||||
[SerializeField] private CanvasScaler _scaler = null;
|
||||
[SerializeField] private RectTransform _uiRoot = null;
|
||||
[SerializeField] private Vector2 _referenceResolution = new Vector2(1920, 1080);
|
||||
|
||||
private float RootScaler => _rectMagnification / _zoomMagnification;
|
||||
|
||||
private float _lastScaler;
|
||||
|
||||
private void OnEnable()
|
||||
{
|
||||
_lastScaler = RootScaler;
|
||||
}
|
||||
|
||||
private void Update()
|
||||
{
|
||||
if (_scaler && _uiRoot)
|
||||
{
|
||||
if (RootScaler != _lastScaler)
|
||||
{
|
||||
Rect rootRect = new Rect(_uiRoot.offsetMin.x / _lastScaler, _uiRoot.offsetMin.y / _lastScaler, _uiRoot.offsetMax.x / _lastScaler, _uiRoot.offsetMax.y / _lastScaler);
|
||||
_lastScaler = RootScaler;
|
||||
|
||||
_scaler.referenceResolution = _referenceResolution / _zoomMagnification;
|
||||
_uiRoot.offsetMin = new Vector2(rootRect.x, rootRect.y) * RootScaler;
|
||||
_uiRoot.offsetMax = new Vector2(rootRect.width, rootRect.height) * RootScaler;
|
||||
|
||||
#if UNITY_EDITOR
|
||||
UnityEditor.EditorUtility.SetDirty(_uiRoot);
|
||||
UnityEditor.EditorUtility.SetDirty(_scaler);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 937bd4b48d20c51489879aabbe372231
|
||||
timeCreated: 1568116289
|
||||
licenseType: Store
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,15 @@
|
|||
{
|
||||
"name": "QFSW.QC.UI",
|
||||
"references": [
|
||||
"QFSW.QC",
|
||||
"Unity.TextMeshPro"
|
||||
],
|
||||
"optionalUnityReferences": [],
|
||||
"includePlatforms": [],
|
||||
"excludePlatforms": [],
|
||||
"allowUnsafeCode": false,
|
||||
"overrideReferences": false,
|
||||
"precompiledReferences": [],
|
||||
"autoReferenced": true,
|
||||
"defineConstraints": []
|
||||
}
|
|
@ -0,0 +1,7 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 0ea4188915c00fb4688accb5ae29f133
|
||||
AssemblyDefinitionImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,41 @@
|
|||
using UnityEngine;
|
||||
using UnityEngine.EventSystems;
|
||||
|
||||
namespace QFSW.QC.UI
|
||||
{
|
||||
[DisallowMultipleComponent]
|
||||
public class ResizableUI : MonoBehaviour, IDragHandler
|
||||
{
|
||||
[SerializeField] private RectTransform _resizeRoot = null;
|
||||
[SerializeField] private Canvas _resizeCanvas = null;
|
||||
|
||||
[SerializeField] private bool _lockInScreen = true;
|
||||
[SerializeField] private Vector2 _minSize = new Vector2();
|
||||
|
||||
public void OnDrag(PointerEventData eventData)
|
||||
{
|
||||
Vector2 minBounds = (_resizeRoot.offsetMin + _minSize) * _resizeCanvas.scaleFactor;
|
||||
Vector2 maxBounds = _lockInScreen
|
||||
? new Vector2(Screen.width, Screen.height)
|
||||
: new Vector2(Mathf.Infinity, Mathf.Infinity);
|
||||
|
||||
Vector2 delta = eventData.delta;
|
||||
Vector2 posCurrent = eventData.position;
|
||||
Vector2 posLast = posCurrent - delta;
|
||||
|
||||
Vector2 posCurrentBounded = new Vector2(
|
||||
Mathf.Clamp(posCurrent.x, minBounds.x, maxBounds.x),
|
||||
Mathf.Clamp(posCurrent.y, minBounds.y, maxBounds.y)
|
||||
);
|
||||
|
||||
Vector2 posLastBounded = new Vector2(
|
||||
Mathf.Clamp(posLast.x, minBounds.x, maxBounds.x),
|
||||
Mathf.Clamp(posLast.y, minBounds.y, maxBounds.y)
|
||||
);
|
||||
|
||||
Vector2 deltaBounded = posCurrentBounded - posLastBounded;
|
||||
|
||||
_resizeRoot.offsetMax += deltaBounded / _resizeCanvas.scaleFactor;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: f34c043809e27534ebfd9bfa1410ac0a
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,74 @@
|
|||
using TMPro;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
|
||||
namespace QFSW.QC.UI
|
||||
{
|
||||
[ExecuteInEditMode]
|
||||
public class ZoomUIController : MonoBehaviour
|
||||
{
|
||||
[SerializeField] private float _zoomIncrement = 0.1f;
|
||||
[SerializeField] private float _minZoom = 0.1f;
|
||||
[SerializeField] private float _maxZoom = 2f;
|
||||
|
||||
[SerializeField] private Button _zoomDownBtn = null;
|
||||
[SerializeField] private Button _zoomUpBtn = null;
|
||||
|
||||
[SerializeField] private DynamicCanvasScaler _scaler = null;
|
||||
[SerializeField] private QuantumConsole _quantumConsole = null;
|
||||
[SerializeField] private TextMeshProUGUI _text = null;
|
||||
|
||||
private float _lastZoom = -1;
|
||||
|
||||
private float ClampAndSnapZoom(float zoom)
|
||||
{
|
||||
float clampedZoom = Mathf.Min(_maxZoom, Mathf.Max(_minZoom, zoom));
|
||||
float snappedZoom = Mathf.Round(clampedZoom / _zoomIncrement) * _zoomIncrement;
|
||||
return snappedZoom;
|
||||
}
|
||||
|
||||
public void ZoomUp()
|
||||
{
|
||||
_scaler.ZoomMagnification = ClampAndSnapZoom(_scaler.ZoomMagnification + _zoomIncrement);
|
||||
}
|
||||
|
||||
public void ZoomDown()
|
||||
{
|
||||
_scaler.ZoomMagnification = ClampAndSnapZoom(_scaler.ZoomMagnification - _zoomIncrement);
|
||||
}
|
||||
|
||||
private void Update()
|
||||
{
|
||||
if (_quantumConsole && _quantumConsole.KeyConfig)
|
||||
{
|
||||
if (_quantumConsole.KeyConfig.ZoomInKey.IsPressed()) { ZoomUp(); }
|
||||
if (_quantumConsole.KeyConfig.ZoomOutKey.IsPressed()) { ZoomDown(); }
|
||||
}
|
||||
}
|
||||
|
||||
private void LateUpdate()
|
||||
{
|
||||
if (_scaler && _text)
|
||||
{
|
||||
float zoom = _scaler.ZoomMagnification;
|
||||
if (zoom != _lastZoom)
|
||||
{
|
||||
_lastZoom = zoom;
|
||||
|
||||
int percentage = Mathf.RoundToInt(100 * zoom);
|
||||
_text.text = $"{percentage}%";
|
||||
}
|
||||
}
|
||||
|
||||
if (_zoomDownBtn)
|
||||
{
|
||||
_zoomDownBtn.interactable = _lastZoom > _minZoom;
|
||||
}
|
||||
|
||||
if (_zoomUpBtn)
|
||||
{
|
||||
_zoomUpBtn.interactable = _lastZoom < _maxZoom;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 302ba813ec8ed7b4da5659d8529ab761
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,8 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 0a3ab78ceb448994ba285874cb280c7b
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,96 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace QFSW.QC.Utilities
|
||||
{
|
||||
public static class CollectionExtensions
|
||||
{
|
||||
/// <summary>Inverts the key/value relationship between the items in the dictionary.</summary>
|
||||
/// <returns>Dictionary with the inverted relationship.</returns>
|
||||
public static Dictionary<TValue, TKey> Invert<TKey, TValue>(this IDictionary<TKey, TValue> source)
|
||||
{
|
||||
Dictionary<TValue, TKey> dictionary = new Dictionary<TValue, TKey>();
|
||||
foreach (KeyValuePair<TKey, TValue> item in source)
|
||||
{
|
||||
if (!dictionary.ContainsKey(item.Value))
|
||||
{
|
||||
dictionary.Add(item.Value, item.Key);
|
||||
}
|
||||
}
|
||||
|
||||
return dictionary;
|
||||
}
|
||||
|
||||
/// <summary>Gets a sub array of an existing array.</summary>
|
||||
/// <param name="index">Index to take the sub array from.</param>
|
||||
/// <param name="length">The length of the sub array.</param>
|
||||
public static T[] SubArray<T>(this T[] data, int index, int length)
|
||||
{
|
||||
T[] result = new T[length];
|
||||
Array.Copy(data, index, result, 0, length);
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>Skips the last element in the sequence.</summary>
|
||||
public static IEnumerable<T> SkipLast<T>(this IEnumerable<T> source)
|
||||
{
|
||||
using (IEnumerator<T> enumurator = source.GetEnumerator())
|
||||
{
|
||||
if (enumurator.MoveNext())
|
||||
{
|
||||
for (T value = enumurator.Current; enumurator.MoveNext(); value = enumurator.Current)
|
||||
{
|
||||
yield return value;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Reverses the order of the sequence.</summary>
|
||||
public static IEnumerable<T> Reversed<T>(this IReadOnlyList<T> source)
|
||||
{
|
||||
for (int i = source.Count - 1; i >= 0; i--)
|
||||
{
|
||||
yield return source[i];
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a distinct stream based on a custom predicate.
|
||||
/// </summary>
|
||||
/// <typeparam name="TValue">The type of the IEnumerable.</typeparam>
|
||||
/// <typeparam name="TDistinct">The type of the value to test for distinctness.</typeparam>
|
||||
/// <param name="source">The source IEnumerable.</param>
|
||||
/// <param name="predicate">The custom distinct item producer.</param>
|
||||
/// <returns>The distinct stream.</returns>
|
||||
public static IEnumerable<TValue> DistinctBy<TValue, TDistinct>(this IEnumerable<TValue> source, Func<TValue, TDistinct> predicate)
|
||||
{
|
||||
HashSet<TDistinct> set = new HashSet<TDistinct>();
|
||||
foreach (TValue value in source)
|
||||
{
|
||||
if (set.Add(predicate(value)))
|
||||
{
|
||||
yield return value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static IEnumerable<T> Yield<T>(this T item)
|
||||
{
|
||||
yield return item;
|
||||
}
|
||||
|
||||
public static T LastOr<T>(this IEnumerable<T> source, T value)
|
||||
{
|
||||
try
|
||||
{
|
||||
return source.Last();
|
||||
}
|
||||
catch (InvalidOperationException)
|
||||
{
|
||||
return value;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 99be75fe8deafca40aeb940896f68a4f
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,58 @@
|
|||
using System.Collections.Concurrent;
|
||||
using UnityEngine;
|
||||
|
||||
namespace QFSW.QC.Utilities
|
||||
{
|
||||
public static class ColorExtensions
|
||||
{
|
||||
/// <summary>Colors a string using rich formatting.</summary>
|
||||
/// <returns>The formatted text.</returns>
|
||||
/// <param name="text">The text to color.</param>
|
||||
/// <param name="color">The color to add to the text.</param>
|
||||
public static string ColorText(this string text, Color color)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(text)) { return text; }
|
||||
string hexColor = Color32ToStringNonAlloc(color);
|
||||
return $"<color=#{hexColor}>{text}</color>";
|
||||
}
|
||||
|
||||
private static readonly ConcurrentDictionary<int, string> _colorLookupTable = new ConcurrentDictionary<int, string>();
|
||||
public static unsafe string Color32ToStringNonAlloc(Color32 color)
|
||||
{
|
||||
int colorKey = color.r << 24 | color.g << 16 | color.b << 8 | color.a;
|
||||
if (_colorLookupTable.ContainsKey(colorKey))
|
||||
{
|
||||
return _colorLookupTable[colorKey];
|
||||
}
|
||||
|
||||
char* buffer = stackalloc char[8];
|
||||
Color32ToHexNonAlloc(color, buffer);
|
||||
|
||||
int bufferLength = color.a < 0xFF ? 8 : 6;
|
||||
string colorText = new string(buffer, 0, bufferLength);
|
||||
|
||||
_colorLookupTable[colorKey] = colorText;
|
||||
return colorText;
|
||||
}
|
||||
|
||||
private static unsafe void Color32ToHexNonAlloc(Color32 color, char* buffer)
|
||||
{
|
||||
ByteToHex(color.r, out buffer[0], out buffer[1]);
|
||||
ByteToHex(color.g, out buffer[2], out buffer[3]);
|
||||
ByteToHex(color.b, out buffer[4], out buffer[5]);
|
||||
ByteToHex(color.a, out buffer[6], out buffer[7]);
|
||||
}
|
||||
|
||||
private static void ByteToHex(byte value, out char dig1, out char dig2)
|
||||
{
|
||||
dig1 = NibbleToHex((byte)(value >> 4));
|
||||
dig2 = NibbleToHex((byte)(value & 0xF));
|
||||
}
|
||||
|
||||
private static char NibbleToHex(byte nibble)
|
||||
{
|
||||
if (nibble < 10) { return (char)('0' + nibble); }
|
||||
else { return (char)('A' + nibble - 10); }
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 5551e6df9beb04cd08039b2d8912821a
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,84 @@
|
|||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using UnityEngine;
|
||||
using UnityEngine.SceneManagement;
|
||||
|
||||
namespace QFSW.QC.Utilities
|
||||
{
|
||||
public static class GameObjectExtensions
|
||||
{
|
||||
private static readonly Dictionary<string, GameObject> GameObjectCache = new Dictionary<string, GameObject>();
|
||||
private static readonly List<GameObject> RootGameObjectBuffer = new List<GameObject>();
|
||||
|
||||
public static GameObject Find(string name, bool includeInactive = false)
|
||||
{
|
||||
if (GameObjectCache.TryGetValue(name, out GameObject obj)
|
||||
&& obj
|
||||
&& obj.activeInHierarchy | includeInactive
|
||||
&& obj.name == name)
|
||||
{
|
||||
return obj;
|
||||
}
|
||||
|
||||
obj = GameObject.Find(name);
|
||||
if (obj)
|
||||
{
|
||||
return GameObjectCache[name] = obj;
|
||||
}
|
||||
|
||||
if (includeInactive)
|
||||
{
|
||||
int sceneCount = SceneManager.sceneCountInBuildSettings;
|
||||
for (int i = 0; i < sceneCount; i++)
|
||||
{
|
||||
Scene scene = SceneManager.GetSceneByBuildIndex(i);
|
||||
if (scene.isLoaded)
|
||||
{
|
||||
RootGameObjectBuffer.Clear();
|
||||
scene.GetRootGameObjects(RootGameObjectBuffer);
|
||||
|
||||
foreach (GameObject root in RootGameObjectBuffer)
|
||||
{
|
||||
obj = Find(name, root);
|
||||
if (obj)
|
||||
{
|
||||
return GameObjectCache[name] = obj;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
obj = Resources
|
||||
.FindObjectsOfTypeAll<GameObject>()
|
||||
.Where(x => !x.hideFlags.HasFlag(HideFlags.HideInHierarchy))
|
||||
.FirstOrDefault(x => x.name == name);
|
||||
|
||||
if (obj)
|
||||
{
|
||||
return GameObjectCache[name] = obj;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public static GameObject Find(string name, GameObject root)
|
||||
{
|
||||
if (root.name == name)
|
||||
{
|
||||
return root;
|
||||
}
|
||||
|
||||
for (int i = 0; i < root.transform.childCount; i++)
|
||||
{
|
||||
GameObject obj = Find(name, root.transform.GetChild(i).gameObject);
|
||||
if (obj)
|
||||
{
|
||||
return obj;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 9afd52ab3444b8f4bb5518c7a215c953
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,22 @@
|
|||
using UnityEngine;
|
||||
|
||||
namespace QFSW.QC
|
||||
{
|
||||
public static class LogTypeExtensions
|
||||
{
|
||||
public static LoggingThreshold ToLoggingThreshold(this LogType logType)
|
||||
{
|
||||
LoggingThreshold severity = LoggingThreshold.Always;
|
||||
switch (logType)
|
||||
{
|
||||
case LogType.Exception: severity = LoggingThreshold.Exception; break;
|
||||
case LogType.Error: severity = LoggingThreshold.Error; break;
|
||||
case LogType.Assert: severity = LoggingThreshold.Error; break;
|
||||
case LogType.Warning: severity = LoggingThreshold.Warning; break;
|
||||
case LogType.Log: severity = LoggingThreshold.Always; break;
|
||||
}
|
||||
|
||||
return severity;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 6173ce0a9ecacf0408e91b424d44ab09
|
||||
timeCreated: 1554342642
|
||||
licenseType: Store
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,370 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Linq.Expressions;
|
||||
using System.Reflection;
|
||||
|
||||
namespace QFSW.QC.Utilities
|
||||
{
|
||||
public static class ReflectionExtensions
|
||||
{
|
||||
#region Lookup Tables
|
||||
private static readonly Dictionary<Type, string> _typeDisplayNames = new Dictionary<Type, string>
|
||||
{
|
||||
{ typeof(int), "int" },
|
||||
{ typeof(float), "float" },
|
||||
{ typeof(decimal), "decimal" },
|
||||
{ typeof(double), "double" },
|
||||
{ typeof(string), "string" },
|
||||
{ typeof(bool), "bool" },
|
||||
{ typeof(byte), "byte" },
|
||||
{ typeof(sbyte), "sbyte" },
|
||||
{ typeof(uint), "uint" },
|
||||
{ typeof(short), "short" },
|
||||
{ typeof(ushort), "ushort" },
|
||||
{ typeof(long), "decimal" },
|
||||
{ typeof(ulong), "ulong" },
|
||||
{ typeof(char), "char" },
|
||||
{ typeof(object), "object" }
|
||||
};
|
||||
|
||||
private static readonly Type[] _valueTupleTypes =
|
||||
{
|
||||
typeof(ValueTuple<>),
|
||||
typeof(ValueTuple<,>),
|
||||
typeof(ValueTuple<,,>),
|
||||
typeof(ValueTuple<,,,>),
|
||||
typeof(ValueTuple<,,,,>),
|
||||
typeof(ValueTuple<,,,,,>),
|
||||
typeof(ValueTuple<,,,,,,>),
|
||||
typeof(ValueTuple<,,,,,,,>)
|
||||
};
|
||||
|
||||
private static readonly Type[][] _primitiveTypeCastHierarchy =
|
||||
{
|
||||
new[] { typeof(byte), typeof(sbyte), typeof(char) },
|
||||
new[] { typeof(short), typeof(ushort) },
|
||||
new[] { typeof(int), typeof(uint) },
|
||||
new[] { typeof(long), typeof(ulong) },
|
||||
new[] { typeof(float) },
|
||||
new[] { typeof(double) }
|
||||
};
|
||||
#endregion
|
||||
|
||||
/// <summary>Determines if a type is a delegate.</summary>
|
||||
/// <returns>If the type is a delegate.</returns>
|
||||
public static bool IsDelegate(this Type type)
|
||||
{
|
||||
if (!typeof(Delegate).IsAssignableFrom(type)) { return false; }
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>Determines if a type is a strongly typed delegate.</summary>
|
||||
/// <returns>If the type is a strongly typed delegate.</returns>
|
||||
public static bool IsStrongDelegate(this Type type)
|
||||
{
|
||||
if (!type.IsDelegate()) { return false; }
|
||||
if (type.IsAbstract) { return false; }
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>Determines if a field is a delegate.</summary>
|
||||
/// <returns>If the field is a delegate.</returns>
|
||||
public static bool IsDelegate(this FieldInfo fieldInfo)
|
||||
{
|
||||
return fieldInfo.FieldType.IsDelegate();
|
||||
}
|
||||
|
||||
/// <summary>Determines if a field is a strongly typed delegate.</summary>
|
||||
/// <param name="fieldInfo">The field to query.</param>
|
||||
/// <returns>If the field is a strongly typed delegate.</returns>
|
||||
public static bool IsStrongDelegate(this FieldInfo fieldInfo)
|
||||
{
|
||||
return fieldInfo.FieldType.IsStrongDelegate();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Determines if the type is a generic type of the given non-generic type.
|
||||
/// </summary>
|
||||
/// <param name="nonGenericType">The non-generic type to test against.</param>
|
||||
/// <returns>If the type is a generic type of the non-generic type.</returns>
|
||||
public static bool IsGenericTypeOf(this Type genericType, Type nonGenericType)
|
||||
{
|
||||
if (!genericType.IsGenericType) { return false; }
|
||||
return genericType.GetGenericTypeDefinition() == nonGenericType;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Determines if the type is a derived type of the given base type.
|
||||
/// </summary>
|
||||
/// <param name="baseType">The base type to test against.</param>
|
||||
/// <returns>If the type is a derived type of the base type.</returns>
|
||||
public static bool IsDerivedTypeOf(this Type type, Type baseType)
|
||||
{
|
||||
return baseType.IsAssignableFrom(type);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Determines if an object the given type can be casted to the specified type.
|
||||
/// </summary>
|
||||
/// <param name="to">The destination type of the cast.</param>
|
||||
/// <param name="implicitly">If only implicit casts should be considered.</param>
|
||||
/// <returns>If the cast can be performed.</returns>
|
||||
public static bool IsCastableTo(this Type from, Type to, bool implicitly = false)
|
||||
{
|
||||
return to.IsAssignableFrom(from) || from.HasCastDefined(to, implicitly);
|
||||
}
|
||||
|
||||
private static bool HasCastDefined(this Type from, Type to, bool implicitly)
|
||||
{
|
||||
if ((from.IsPrimitive || from.IsEnum) && (to.IsPrimitive || to.IsEnum))
|
||||
{
|
||||
if (!implicitly)
|
||||
{
|
||||
return from == to || (from != typeof(bool) && to != typeof(bool));
|
||||
}
|
||||
|
||||
IEnumerable<Type> lowerTypes = Enumerable.Empty<Type>();
|
||||
foreach (Type[] types in _primitiveTypeCastHierarchy)
|
||||
{
|
||||
if (types.Any(t => t == to))
|
||||
{
|
||||
return lowerTypes.Any(t => t == from);
|
||||
}
|
||||
|
||||
lowerTypes = lowerTypes.Concat(types);
|
||||
}
|
||||
|
||||
return false; // IntPtr, UIntPtr, Enum, Boolean
|
||||
}
|
||||
|
||||
return IsCastDefined(to, m => m.GetParameters()[0].ParameterType, _ => from, implicitly, false)
|
||||
|| IsCastDefined(from, _ => to, m => m.ReturnType, implicitly, true);
|
||||
}
|
||||
|
||||
private static bool IsCastDefined(Type type, Func<MethodInfo, Type> baseType, Func<MethodInfo, Type> derivedType, bool implicitly, bool lookInBase)
|
||||
{
|
||||
BindingFlags flags = BindingFlags.Public | BindingFlags.Static | (lookInBase ? BindingFlags.FlattenHierarchy : BindingFlags.DeclaredOnly);
|
||||
MethodInfo[] methods = type.GetMethods(flags);
|
||||
|
||||
return methods.Where(m => m.Name == "op_Implicit" || (!implicitly && m.Name == "op_Explicit"))
|
||||
.Any(m => baseType(m).IsAssignableFrom(derivedType(m)));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Dynamically casts an object to the specified type.
|
||||
/// </summary>
|
||||
/// <param name="type">The destination type of the cast.</param>
|
||||
/// <param name="data">The object to cast.</param>
|
||||
/// <returns>The dynamically casted object.</returns>
|
||||
public static object Cast(this Type type, object data)
|
||||
{
|
||||
if (type.IsInstanceOfType(data))
|
||||
{
|
||||
return data;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
return Convert.ChangeType(data, type);
|
||||
}
|
||||
catch (InvalidCastException)
|
||||
{
|
||||
Type srcType = data.GetType();
|
||||
ParameterExpression dataParam = Expression.Parameter(srcType, "data");
|
||||
Expression body = Expression.Convert(Expression.Convert(dataParam, srcType), type);
|
||||
|
||||
Delegate run = Expression.Lambda(body, dataParam).Compile();
|
||||
return run.DynamicInvoke(data);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Determines if the given method is an override.</summary>
|
||||
/// <returns>If the method is an override.</returns>
|
||||
public static bool IsOverride(this MethodInfo methodInfo)
|
||||
{
|
||||
return methodInfo.GetBaseDefinition().DeclaringType != methodInfo.DeclaringType;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets if the provider has the specified attribute.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The attribute to test.</typeparam>
|
||||
/// <param name="provider">The attribute provider.</param>
|
||||
/// <param name="searchInherited">If base declarations should be searched.</param>
|
||||
/// <returns>If the attribute is present.</returns>
|
||||
public static bool HasAttribute<T>(this ICustomAttributeProvider provider, bool searchInherited = true) where T : Attribute
|
||||
{
|
||||
try
|
||||
{
|
||||
return provider.IsDefined(typeof(T), searchInherited);
|
||||
}
|
||||
catch (MissingMethodException)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a formatted display name for a given type.
|
||||
/// </summary>
|
||||
/// <param name="type">The type to generate a display name for.</param>
|
||||
/// <param name="includeNamespace">If the namespace should be included when generating the typename.</param>
|
||||
/// <returns>The generated display name.</returns>
|
||||
public static string GetDisplayName(this Type type, bool includeNamespace = false)
|
||||
{
|
||||
if (type.IsArray)
|
||||
{
|
||||
int rank = type.GetArrayRank();
|
||||
string innerTypeName = GetDisplayName(type.GetElementType(), includeNamespace);
|
||||
return $"{innerTypeName}[{new string(',', rank - 1)}]";
|
||||
}
|
||||
|
||||
if (_typeDisplayNames.ContainsKey(type))
|
||||
{
|
||||
string baseName = _typeDisplayNames[type];
|
||||
if (type.IsGenericType && !type.IsConstructedGenericType)
|
||||
{
|
||||
Type[] genericArgs = type.GetGenericArguments();
|
||||
return $"{baseName}<{new string(',', genericArgs.Length - 1)}>";
|
||||
}
|
||||
|
||||
return baseName;
|
||||
}
|
||||
|
||||
if (type.IsGenericType)
|
||||
{
|
||||
Type baseType = type.GetGenericTypeDefinition();
|
||||
Type[] genericArgs = type.GetGenericArguments();
|
||||
|
||||
if (_valueTupleTypes.Contains(baseType))
|
||||
{
|
||||
return GetTupleDisplayName(type, includeNamespace);
|
||||
}
|
||||
|
||||
if (type.IsConstructedGenericType)
|
||||
{
|
||||
string[] genericNames = new string[genericArgs.Length];
|
||||
for (int i = 0; i < genericArgs.Length; i++)
|
||||
{
|
||||
genericNames[i] = GetDisplayName(genericArgs[i], includeNamespace);
|
||||
}
|
||||
|
||||
string baseName = GetDisplayName(baseType, includeNamespace).Split('<')[0];
|
||||
return $"{baseName}<{string.Join(", ", genericNames)}>";
|
||||
}
|
||||
|
||||
string typeName = includeNamespace
|
||||
? type.FullName
|
||||
: type.Name;
|
||||
|
||||
return $"{typeName.Split('`')[0]}<{new string(',', genericArgs.Length - 1)}>";
|
||||
}
|
||||
|
||||
Type declaringType = type.DeclaringType;
|
||||
if (declaringType != null)
|
||||
{
|
||||
string declaringName = GetDisplayName(declaringType, includeNamespace);
|
||||
return $"{declaringName}.{type.Name}";
|
||||
}
|
||||
|
||||
return includeNamespace
|
||||
? type.FullName
|
||||
: type.Name;
|
||||
}
|
||||
|
||||
private static string GetTupleDisplayName(this Type type, bool includeNamespace = false)
|
||||
{
|
||||
IEnumerable<string> parts = type
|
||||
.GetGenericArguments()
|
||||
.Select(x => x.GetDisplayName(includeNamespace));
|
||||
|
||||
return $"({string.Join(", ", parts)})";
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Determines if two methods from different types have the same signature.
|
||||
/// </summary>
|
||||
/// <param name="a">First method</param>
|
||||
/// <param name="b">Second method</param>
|
||||
/// <returns><c>true</c> if they are equal</returns>
|
||||
public static bool AreMethodsEqual(MethodInfo a, MethodInfo b)
|
||||
{
|
||||
if (a.Name != b.Name) return false;
|
||||
|
||||
ParameterInfo[] paramsA = a.GetParameters();
|
||||
ParameterInfo[] paramsB = b.GetParameters();
|
||||
|
||||
if (paramsA.Length != paramsB.Length) return false;
|
||||
for (int i = 0; i < paramsA.Length; i++)
|
||||
{
|
||||
ParameterInfo pa = paramsA[i];
|
||||
ParameterInfo pb = paramsB[i];
|
||||
|
||||
if (pa.Name != pb.Name) return false;
|
||||
if (pa.HasDefaultValue != pb.HasDefaultValue) return false;
|
||||
|
||||
Type ta = pa.ParameterType;
|
||||
Type tb = pb.ParameterType;
|
||||
|
||||
if (!ta.ContainsGenericParameters && !tb.ContainsGenericParameters)
|
||||
{
|
||||
if (ta != tb) return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (a.IsGenericMethod != b.IsGenericMethod) return false;
|
||||
if (a.IsGenericMethod && b.IsGenericMethod)
|
||||
{
|
||||
Type[] genericA = a.GetGenericArguments();
|
||||
Type[] genericB = b.GetGenericArguments();
|
||||
|
||||
if (genericA.Length != genericB.Length) return false;
|
||||
for (int i = 0; i < genericA.Length; i++)
|
||||
{
|
||||
Type ga = genericA[i];
|
||||
Type gb = genericB[i];
|
||||
|
||||
if (ga.Name != gb.Name) return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Rebases a method onto a new type by finding the corresponding method with an equal signature.
|
||||
/// </summary>
|
||||
/// <param name="method">Method to rebase</param>
|
||||
/// <param name="newBase">New type to rebase the method onto</param>
|
||||
/// <returns>The rebased method</returns>
|
||||
public static MethodInfo RebaseMethod(this MethodInfo method, Type newBase)
|
||||
{
|
||||
BindingFlags flags = BindingFlags.Default;
|
||||
|
||||
flags |= method.IsStatic
|
||||
? BindingFlags.Static
|
||||
: BindingFlags.Instance;
|
||||
|
||||
flags |= method.IsPublic
|
||||
? BindingFlags.Public
|
||||
: BindingFlags.NonPublic;
|
||||
|
||||
MethodInfo[] candidates = newBase.GetMethods(flags)
|
||||
.Where(x => AreMethodsEqual(x, method))
|
||||
.ToArray();
|
||||
|
||||
if (candidates.Length == 0)
|
||||
{
|
||||
throw new ArgumentException($"Could not rebase method {method} onto type {newBase} as no matching candidates were found");
|
||||
}
|
||||
|
||||
if (candidates.Length > 1)
|
||||
{
|
||||
throw new ArgumentException($"Could not rebase method {method} onto type {newBase} as too many matching candidates were found");
|
||||
}
|
||||
|
||||
return candidates[0];
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 095d8e0dd1a06544485e6498a6907792
|
||||
timeCreated: 1544062910
|
||||
licenseType: Store
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,41 @@
|
|||
using System;
|
||||
|
||||
namespace QFSW.QC.Utilities
|
||||
{
|
||||
public static class StringExtensions
|
||||
{
|
||||
public static bool ContainsCaseInsensitive(this string source, string value)
|
||||
{
|
||||
if (string.IsNullOrEmpty(source))
|
||||
{
|
||||
if (string.IsNullOrEmpty(value)) { return true; }
|
||||
else { return false; }
|
||||
}
|
||||
|
||||
#if UNITY_WEBGL
|
||||
return source.ToLower().Contains(value.ToLower());
|
||||
#else
|
||||
return source.Contains(value, StringComparison.OrdinalIgnoreCase);
|
||||
#endif
|
||||
}
|
||||
|
||||
public static bool Contains(this string source, string value, StringComparison comp)
|
||||
{
|
||||
return source?.IndexOf(value, comp) >= 0;
|
||||
}
|
||||
|
||||
public static int CountFromIndex(this string source, char target, int index)
|
||||
{
|
||||
int count = 0;
|
||||
for (int i = index; i < source.Length; i++)
|
||||
{
|
||||
if (source[i] == target)
|
||||
{
|
||||
count++;
|
||||
}
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,13 @@
|
|||
fileFormatVersion: 2
|
||||
guid: ac9ccb14571900847893f62b5ebaa305
|
||||
timeCreated: 1561417301
|
||||
licenseType: Store
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,214 @@
|
|||
using QFSW.QC.Containers;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace QFSW.QC
|
||||
{
|
||||
public static class TextProcessing
|
||||
{
|
||||
public static readonly char[] DefaultLeftScopers = { '<', '[', '(', '{', '"' };
|
||||
public static readonly char[] DefaultRightScopers = { '>', ']', ')', '}', '"' };
|
||||
|
||||
public static string ReduceScope(this string input, int maxReduction = -1)
|
||||
{
|
||||
return input.ReduceScope(DefaultLeftScopers, DefaultRightScopers, maxReduction);
|
||||
}
|
||||
|
||||
public static string ReduceScope(this string input, char leftScoper, char rightScoper, int maxReduction = -1)
|
||||
{
|
||||
return input.ReduceScope(leftScoper.AsArraySingle(), rightScoper.AsArraySingle(), maxReduction);
|
||||
}
|
||||
|
||||
public static string ReduceScope<T>(this string input, T leftScopers, T rightScopers, int maxReduction = -1)
|
||||
where T : IReadOnlyList<char>
|
||||
{
|
||||
if (leftScopers.Count != rightScopers.Count)
|
||||
{
|
||||
throw new ArgumentException("There must be an equal number of corresponding left and right scopers");
|
||||
}
|
||||
|
||||
if (string.IsNullOrWhiteSpace(input))
|
||||
{
|
||||
return string.Empty;
|
||||
}
|
||||
|
||||
string trimmedInput = input.Trim();
|
||||
|
||||
if (maxReduction == 0)
|
||||
{
|
||||
return trimmedInput;
|
||||
}
|
||||
|
||||
for (int i = 0; i < leftScopers.Count; i++)
|
||||
{
|
||||
char leftScoper = leftScopers[i];
|
||||
char rightScoper = rightScopers[i];
|
||||
|
||||
if (leftScoper == rightScoper)
|
||||
{
|
||||
string descopedInput = trimmedInput;
|
||||
bool descoped = false;
|
||||
while (descopedInput[0] == leftScoper && descopedInput[descopedInput.Length - 1] == rightScoper)
|
||||
{
|
||||
descoped = true;
|
||||
descopedInput = descopedInput.Substring(1, descopedInput.Length - 2).Trim();
|
||||
if (descopedInput.Length == 0) { break; }
|
||||
}
|
||||
|
||||
for (int j = 0; j < descopedInput.Length; j++)
|
||||
{
|
||||
if (descopedInput[j] == leftScoper && (j == 0 || descopedInput[j - 1] != '\\'))
|
||||
{
|
||||
descoped = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (descoped) { return descopedInput.ReduceScope(leftScopers, rightScopers, maxReduction - 1); }
|
||||
}
|
||||
else
|
||||
{
|
||||
if (trimmedInput[0] == leftScoper && trimmedInput[trimmedInput.Length - 1] == rightScoper)
|
||||
{
|
||||
int scope = 1;
|
||||
for (int j = 1; j < trimmedInput.Length - 1; j++)
|
||||
{
|
||||
if (trimmedInput[j] == leftScoper) { scope++; }
|
||||
else if (trimmedInput[j] == rightScoper) { scope--; }
|
||||
|
||||
if (scope == 0)
|
||||
{
|
||||
return trimmedInput;
|
||||
}
|
||||
}
|
||||
|
||||
return trimmedInput.Substring(1, trimmedInput.Length - 2).ReduceScope(leftScopers, rightScopers, maxReduction - 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return input;
|
||||
}
|
||||
|
||||
public static string[] SplitScoped(this string input, char splitChar, bool autoReduceScope = false)
|
||||
{
|
||||
return input.SplitScoped(splitChar, -1, autoReduceScope);
|
||||
}
|
||||
|
||||
public static string[] SplitScoped(this string input, char splitChar, int maxCount, bool autoReduceScope = false)
|
||||
{
|
||||
return input.SplitScoped(splitChar, DefaultLeftScopers, DefaultRightScopers, maxCount, autoReduceScope);
|
||||
}
|
||||
|
||||
public static string[] SplitScoped(this string input, char splitChar, char leftScoper, char rightScoper, bool autoReduceScope = false)
|
||||
{
|
||||
return input.SplitScoped(splitChar, leftScoper, rightScoper, -1, autoReduceScope);
|
||||
}
|
||||
|
||||
public static string[] SplitScoped(this string input, char splitChar, char leftScoper, char rightScoper, int maxCount, bool autoReduceScope = false)
|
||||
{
|
||||
return input.SplitScoped(splitChar, leftScoper.AsArraySingle(), rightScoper.AsArraySingle(), maxCount, autoReduceScope);
|
||||
}
|
||||
|
||||
public static string[] SplitScoped<T>(this string input, char splitChar, T leftScopers, T rightScopers, bool autoReduceScope = false)
|
||||
where T : IReadOnlyList<char>
|
||||
{
|
||||
return input.SplitScoped(splitChar, leftScopers, rightScopers, -1, autoReduceScope);
|
||||
}
|
||||
|
||||
public static string[] SplitScoped<T>(this string input, char splitChar, T leftScopers, T rightScopers, int maxCount, bool autoReduceScope = false)
|
||||
where T : IReadOnlyList<char>
|
||||
{
|
||||
if (autoReduceScope) { input = input.ReduceScope(leftScopers, rightScopers); }
|
||||
if (string.IsNullOrWhiteSpace(input)) { return Array.Empty<string>(); }
|
||||
|
||||
IEnumerable<int> rawSplitIndices = GetScopedSplitPoints(input, splitChar, leftScopers, rightScopers);
|
||||
int[] splitIndices;
|
||||
if (maxCount > 0)
|
||||
{
|
||||
splitIndices = rawSplitIndices.Take(maxCount - 1).ToArray();
|
||||
}
|
||||
else
|
||||
{
|
||||
splitIndices = rawSplitIndices.ToArray();
|
||||
}
|
||||
|
||||
// Return single array when no splits occurred
|
||||
if (splitIndices.Length == 0)
|
||||
{
|
||||
return new[] { input };
|
||||
}
|
||||
|
||||
string[] splitString = new string[splitIndices.Length + 1];
|
||||
int lastSplitIndex = 0;
|
||||
for (int i = 0; i < splitIndices.Length; i++)
|
||||
{
|
||||
splitString[i] = input.Substring(lastSplitIndex, splitIndices[i] - lastSplitIndex).Trim();
|
||||
lastSplitIndex = splitIndices[i] + 1;
|
||||
}
|
||||
|
||||
splitString[splitIndices.Length] = input.Substring(lastSplitIndex).Trim();
|
||||
return splitString;
|
||||
}
|
||||
|
||||
public static IEnumerable<int> GetScopedSplitPoints<T>(string input, char splitChar, T leftScopers, T rightScopers)
|
||||
where T : IReadOnlyList<char>
|
||||
{
|
||||
if (leftScopers.Count != rightScopers.Count)
|
||||
{
|
||||
throw new ArgumentException("There must be an equal number of corresponding left and right scopers");
|
||||
}
|
||||
|
||||
int[] scopes = new int[leftScopers.Count];
|
||||
for (int i = 0; i < input.Length; i++)
|
||||
{
|
||||
if (i == 0 || input[i - 1] != '\\')
|
||||
{
|
||||
for (int j = 0; j < leftScopers.Count; j++)
|
||||
{
|
||||
char leftScoper = leftScopers[j];
|
||||
char rightScoper = rightScopers[j];
|
||||
|
||||
if (input[i] == leftScoper && leftScoper == rightScoper) { scopes[j] = 1 - scopes[j]; }
|
||||
else if (input[i] == leftScoper) { scopes[j]++; }
|
||||
else if (input[i] == rightScoper) { scopes[j]--; }
|
||||
}
|
||||
}
|
||||
|
||||
if (input[i] == splitChar && scopes.All(x => x == 0))
|
||||
{
|
||||
yield return i;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static bool CanSplitScoped(this string input, char splitChar)
|
||||
{
|
||||
return input.CanSplitScoped(splitChar, DefaultLeftScopers, DefaultRightScopers);
|
||||
}
|
||||
|
||||
|
||||
public static bool CanSplitScoped(this string input, char splitChar, char leftScoper, char rightScoper)
|
||||
{
|
||||
return input.CanSplitScoped(splitChar, leftScoper.AsArraySingle(), rightScoper.AsArraySingle());
|
||||
}
|
||||
|
||||
public static bool CanSplitScoped<T>(this string input, char splitChar, T leftScopers, T rightScopers)
|
||||
where T : IReadOnlyList<char>
|
||||
{
|
||||
return GetScopedSplitPoints(input, splitChar, leftScopers, rightScopers).Any();
|
||||
}
|
||||
|
||||
public static string UnescapeText(this string input, char escapeChar) { return input.UnescapeText(escapeChar.AsArraySingle()); }
|
||||
public static string UnescapeText<T>(this string input, T escapeChars)
|
||||
where T : IReadOnlyCollection<char>
|
||||
{
|
||||
foreach (char escapeChar in escapeChars)
|
||||
{
|
||||
input = input.Replace($"\\{escapeChar}", escapeChar.ToString());
|
||||
}
|
||||
|
||||
return input;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 8fc02e3f995d8444db9bad572a47be03
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,10 @@
|
|||
<linker>
|
||||
<assembly fullname="QFSW.QC" preserve="all"/>
|
||||
<assembly fullname="QFSW.QC.Parsers" preserve="all"/>
|
||||
<assembly fullname="QFSW.QC.Grammar" preserve="all"/>
|
||||
<assembly fullname="QFSW.QC.Serializers" preserve="all"/>
|
||||
<assembly fullname="QFSW.QC.Extras" preserve="all"/>
|
||||
<assembly fullname="System.Core">
|
||||
<type fullname="System.Linq.Expressions.Interpreter.LightLambda" preserve="all" />
|
||||
</assembly>
|
||||
</linker>
|
|
@ -0,0 +1,7 @@
|
|||
fileFormatVersion: 2
|
||||
guid: b3569c4d6f4f03e449d1e3afa1c8afd8
|
||||
TextScriptImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,8 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 59dec0d3cfad221488e6b8ad38e6414d
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,219 @@
|
|||
// Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,*)' with 'UnityObjectToClipPos(*)'
|
||||
|
||||
Shader "QFSW/Blur"
|
||||
{
|
||||
Properties
|
||||
{
|
||||
_Color("Main Color", Color) = (1,1,1,1)
|
||||
_OverlayColor("Overlay Color", Color) = (1,1,1,1)
|
||||
_MainTex("Tint Color (RGB)", 2D) = "white" {}
|
||||
_Radius("Radius", Range(0, 20)) = 1
|
||||
}
|
||||
|
||||
Category
|
||||
{
|
||||
|
||||
Tags{ "Queue" = "Transparent" "IgnoreProjector" = "True" "RenderType" = "Opaque" }
|
||||
Blend SrcAlpha OneMinusSrcAlpha
|
||||
SubShader{
|
||||
|
||||
GrabPass{
|
||||
Tags{ "LightMode" = "Always" }
|
||||
}
|
||||
Pass{
|
||||
Tags{ "LightMode" = "Always" }
|
||||
|
||||
CGPROGRAM
|
||||
#pragma vertex vert
|
||||
#pragma fragment frag
|
||||
#pragma fragmentoption ARB_precision_hint_fastest
|
||||
#include "UnityCG.cginc"
|
||||
|
||||
struct appdata_t
|
||||
{
|
||||
float4 vertex : POSITION;
|
||||
float2 texcoord: TEXCOORD0;
|
||||
fixed4 color : COLOR;
|
||||
};
|
||||
|
||||
struct v2f
|
||||
{
|
||||
float4 vertex : POSITION;
|
||||
float4 uvgrab : TEXCOORD0;
|
||||
fixed4 color : COLOR;
|
||||
};
|
||||
|
||||
v2f vert(appdata_t v)
|
||||
{
|
||||
v2f o;
|
||||
o.vertex = UnityObjectToClipPos(v.vertex);
|
||||
#if UNITY_UV_STARTS_AT_TOP
|
||||
float scale = -1.0;
|
||||
#else
|
||||
float scale = 1.0;
|
||||
#endif
|
||||
o.uvgrab.xy = (float2(o.vertex.x, o.vertex.y*scale) + o.vertex.w) * 0.5;
|
||||
o.uvgrab.zw = o.vertex.zw;
|
||||
o.color = v.color;
|
||||
return o;
|
||||
}
|
||||
|
||||
sampler2D _GrabTexture;
|
||||
float4 _GrabTexture_TexelSize;
|
||||
uniform float _Radius;
|
||||
uniform float _BlurMultiplier = 1;
|
||||
|
||||
half4 frag(v2f i) : COLOR
|
||||
{
|
||||
_Radius *= _BlurMultiplier;
|
||||
_Radius *= i.color.a;
|
||||
half4 sum = half4(0,0,0,0);
|
||||
#define GRABPIXEL(weight, kernelx) tex2Dproj(_GrabTexture, UNITY_PROJ_COORD(float4(i.uvgrab.x + _GrabTexture_TexelSize.x * kernelx * _Radius, i.uvgrab.y, i.uvgrab.z, i.uvgrab.w))) * weight
|
||||
sum += GRABPIXEL(0.05, -4.0);
|
||||
sum += GRABPIXEL(0.09, -3.0);
|
||||
sum += GRABPIXEL(0.12, -2.0);
|
||||
sum += GRABPIXEL(0.15, -1.0);
|
||||
sum += GRABPIXEL(0.18, 0.0);
|
||||
sum += GRABPIXEL(0.15, +1.0);
|
||||
sum += GRABPIXEL(0.12, +2.0);
|
||||
sum += GRABPIXEL(0.09, +3.0);
|
||||
sum += GRABPIXEL(0.05, +4.0);
|
||||
|
||||
return sum;
|
||||
}
|
||||
ENDCG
|
||||
}
|
||||
|
||||
GrabPass
|
||||
{
|
||||
Tags{ "LightMode" = "Always" }
|
||||
}
|
||||
Pass{
|
||||
Tags{ "LightMode" = "Always" }
|
||||
|
||||
CGPROGRAM
|
||||
#pragma vertex vert
|
||||
#pragma fragment frag
|
||||
#pragma fragmentoption ARB_precision_hint_fastest
|
||||
#include "UnityCG.cginc"
|
||||
|
||||
struct appdata_t
|
||||
{
|
||||
float4 vertex : POSITION;
|
||||
float2 texcoord: TEXCOORD0;
|
||||
fixed4 color : COLOR;
|
||||
};
|
||||
|
||||
struct v2f {
|
||||
float4 vertex : POSITION;
|
||||
float4 uvgrab : TEXCOORD0;
|
||||
fixed4 color : COLOR;
|
||||
};
|
||||
|
||||
v2f vert(appdata_t v) {
|
||||
v2f o;
|
||||
o.vertex = UnityObjectToClipPos(v.vertex);
|
||||
#if UNITY_UV_STARTS_AT_TOP
|
||||
float scale = -1.0;
|
||||
#else
|
||||
float scale = 1.0;
|
||||
#endif
|
||||
o.uvgrab.xy = (float2(o.vertex.x, o.vertex.y*scale) + o.vertex.w) * 0.5;
|
||||
o.uvgrab.zw = o.vertex.zw;
|
||||
o.color = v.color;
|
||||
return o;
|
||||
}
|
||||
|
||||
sampler2D _GrabTexture;
|
||||
float4 _GrabTexture_TexelSize;
|
||||
uniform float _Radius;
|
||||
uniform float _BlurMultiplier = 1;
|
||||
|
||||
half4 frag(v2f i) : COLOR{
|
||||
_Radius *= _BlurMultiplier;
|
||||
_Radius *= i.color.a;
|
||||
half4 sum = half4(0,0,0,0);
|
||||
#define GRABPIXEL(weight,kernely) tex2Dproj( _GrabTexture, UNITY_PROJ_COORD(float4(i.uvgrab.x, i.uvgrab.y + _GrabTexture_TexelSize.y * kernely*_Radius, i.uvgrab.z, i.uvgrab.w))) * weight
|
||||
|
||||
sum += GRABPIXEL(0.05, -4.0);
|
||||
sum += GRABPIXEL(0.09, -3.0);
|
||||
sum += GRABPIXEL(0.12, -2.0);
|
||||
sum += GRABPIXEL(0.15, -1.0);
|
||||
sum += GRABPIXEL(0.18, 0.0);
|
||||
sum += GRABPIXEL(0.15, +1.0);
|
||||
sum += GRABPIXEL(0.12, +2.0);
|
||||
sum += GRABPIXEL(0.09, +3.0);
|
||||
sum += GRABPIXEL(0.05, +4.0);
|
||||
|
||||
return sum;
|
||||
}
|
||||
ENDCG
|
||||
}
|
||||
|
||||
GrabPass{
|
||||
Tags{ "LightMode" = "Always" }
|
||||
}
|
||||
Pass{
|
||||
Tags{ "LightMode" = "Always" }
|
||||
|
||||
CGPROGRAM
|
||||
#pragma vertex vert
|
||||
#pragma fragment frag
|
||||
#pragma fragmentoption ARB_precision_hint_fastest
|
||||
#include "UnityCG.cginc"
|
||||
|
||||
struct appdata_t {
|
||||
float4 vertex : POSITION;
|
||||
float2 texcoord: TEXCOORD0;
|
||||
float4 color: COLOR;
|
||||
};
|
||||
|
||||
struct v2f
|
||||
{
|
||||
float4 vertex : POSITION;
|
||||
float4 uvgrab : TEXCOORD0;
|
||||
float2 uvmain : TEXCOORD1;
|
||||
float4 color : COLOR;
|
||||
};
|
||||
|
||||
float4 _MainTex_ST;
|
||||
|
||||
v2f vert(appdata_t v) {
|
||||
v2f o;
|
||||
o.vertex = UnityObjectToClipPos(v.vertex);
|
||||
#if UNITY_UV_STARTS_AT_TOP
|
||||
float scale = -1.0;
|
||||
#else
|
||||
float scale = 1.0;
|
||||
#endif
|
||||
o.uvgrab.xy = (float2(o.vertex.x, o.vertex.y*scale) + o.vertex.w) * 0.5;
|
||||
o.uvgrab.zw = o.vertex.zw;
|
||||
o.uvmain = TRANSFORM_TEX(v.texcoord, _MainTex);
|
||||
o.color = v.color;
|
||||
return o;
|
||||
}
|
||||
|
||||
fixed4 _Color;
|
||||
fixed4 _OverlayColor;
|
||||
sampler2D _GrabTexture;
|
||||
float4 _GrabTexture_TexelSize;
|
||||
sampler2D _MainTex;
|
||||
|
||||
half4 frag(v2f i) : COLOR
|
||||
{
|
||||
half4 blurredCol = tex2Dproj(_GrabTexture, UNITY_PROJ_COORD(i.uvgrab)); // Gets the color of what is behind it and blurred
|
||||
half4 texCol = tex2D(_MainTex, i.uvmain); // Gets the color of the supplied texture
|
||||
half4 tint = texCol * _Color; // Gets the tint color to apply
|
||||
|
||||
half4 col = blurredCol * tint; // Tints the color
|
||||
col = col * (1 - _OverlayColor.a) + _OverlayColor * _OverlayColor.a; // Blends it with the overlay color
|
||||
col *= i.color;
|
||||
col = blurredCol * (1 - texCol.a) + col * texCol.a; // Blends it using the tex color so transparent regions stay transparent
|
||||
|
||||
return col;
|
||||
}
|
||||
ENDCG
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 3fba250d711269d47864fade9116867c
|
||||
ShaderImporter:
|
||||
externalObjects: {}
|
||||
defaultTextures: []
|
||||
nonModifiableTextures: []
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,8 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 4750aea94a3727649a4fd1df0cd87fc5
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
After Width: | Height: | Size: 106 KiB |
|
@ -0,0 +1,121 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 0a00d33b88ebe3f4eb5dfb0d2a1c0726
|
||||
TextureImporter:
|
||||
fileIDToRecycleName: {}
|
||||
externalObjects: {}
|
||||
serializedVersion: 7
|
||||
mipmaps:
|
||||
mipMapMode: 0
|
||||
enableMipMap: 1
|
||||
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
|
||||
isReadable: 0
|
||||
streamingMipmaps: 0
|
||||
streamingMipmapsPriority: 0
|
||||
grayScaleToAlpha: 0
|
||||
generateCubemap: 6
|
||||
cubemapConvolution: 0
|
||||
seamlessCubemap: 0
|
||||
textureFormat: 1
|
||||
maxTextureSize: 2048
|
||||
textureSettings:
|
||||
serializedVersion: 2
|
||||
filterMode: -1
|
||||
aniso: -1
|
||||
mipBias: -100
|
||||
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
|
||||
maxTextureSizeSet: 0
|
||||
compressionQualitySet: 0
|
||||
textureFormatSet: 0
|
||||
platformSettings:
|
||||
- serializedVersion: 2
|
||||
buildTarget: DefaultTexturePlatform
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
- serializedVersion: 2
|
||||
buildTarget: Standalone
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: 4
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 1
|
||||
androidETC2FallbackOverride: 0
|
||||
- serializedVersion: 2
|
||||
buildTarget: XboxOne
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
- serializedVersion: 2
|
||||
buildTarget: Windows Store Apps
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
spriteSheet:
|
||||
serializedVersion: 2
|
||||
sprites: []
|
||||
outline: []
|
||||
physicsShape: []
|
||||
bones: []
|
||||
spriteID: a493569414aca02479e5838bc4b201dc
|
||||
vertices: []
|
||||
indices:
|
||||
edges: []
|
||||
weights: []
|
||||
spritePackingTag:
|
||||
pSDRemoveMatte: 0
|
||||
pSDShowRemoveMatteOption: 0
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
After Width: | Height: | Size: 124 KiB |
|
@ -0,0 +1,143 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 3b4c5868913f036409451b4765150dd3
|
||||
TextureImporter:
|
||||
fileIDToRecycleName: {}
|
||||
externalObjects: {}
|
||||
serializedVersion: 9
|
||||
mipmaps:
|
||||
mipMapMode: 0
|
||||
enableMipMap: 1
|
||||
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
|
||||
isReadable: 0
|
||||
streamingMipmaps: 0
|
||||
streamingMipmapsPriority: 0
|
||||
grayScaleToAlpha: 0
|
||||
generateCubemap: 6
|
||||
cubemapConvolution: 0
|
||||
seamlessCubemap: 0
|
||||
textureFormat: 1
|
||||
maxTextureSize: 2048
|
||||
textureSettings:
|
||||
serializedVersion: 2
|
||||
filterMode: -1
|
||||
aniso: 1
|
||||
mipBias: -100
|
||||
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
|
||||
maxTextureSizeSet: 0
|
||||
compressionQualitySet: 0
|
||||
textureFormatSet: 0
|
||||
platformSettings:
|
||||
- serializedVersion: 2
|
||||
buildTarget: DefaultTexturePlatform
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
- serializedVersion: 2
|
||||
buildTarget: Standalone
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
- serializedVersion: 2
|
||||
buildTarget: iPhone
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
- serializedVersion: 2
|
||||
buildTarget: Android
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
- serializedVersion: 2
|
||||
buildTarget: Windows Store Apps
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
- serializedVersion: 2
|
||||
buildTarget: WebGL
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
spriteSheet:
|
||||
serializedVersion: 2
|
||||
sprites: []
|
||||
outline: []
|
||||
physicsShape: []
|
||||
bones: []
|
||||
spriteID: 74a7715c93db7b740bb6fc2b674fb937
|
||||
vertices: []
|
||||
indices:
|
||||
edges: []
|
||||
weights: []
|
||||
spritePackingTag:
|
||||
pSDRemoveMatte: 0
|
||||
pSDShowRemoveMatteOption: 0
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
After Width: | Height: | Size: 18 KiB |
|
@ -0,0 +1,121 @@
|
|||
fileFormatVersion: 2
|
||||
guid: b4d81ddc1591c4948b549eda7f0e9c50
|
||||
TextureImporter:
|
||||
fileIDToRecycleName: {}
|
||||
externalObjects: {}
|
||||
serializedVersion: 7
|
||||
mipmaps:
|
||||
mipMapMode: 0
|
||||
enableMipMap: 1
|
||||
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
|
||||
isReadable: 0
|
||||
streamingMipmaps: 0
|
||||
streamingMipmapsPriority: 0
|
||||
grayScaleToAlpha: 0
|
||||
generateCubemap: 6
|
||||
cubemapConvolution: 0
|
||||
seamlessCubemap: 0
|
||||
textureFormat: 1
|
||||
maxTextureSize: 2048
|
||||
textureSettings:
|
||||
serializedVersion: 2
|
||||
filterMode: -1
|
||||
aniso: -1
|
||||
mipBias: -100
|
||||
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
|
||||
maxTextureSizeSet: 0
|
||||
compressionQualitySet: 0
|
||||
textureFormatSet: 0
|
||||
platformSettings:
|
||||
- serializedVersion: 2
|
||||
buildTarget: DefaultTexturePlatform
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
- serializedVersion: 2
|
||||
buildTarget: Standalone
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: 4
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 1
|
||||
androidETC2FallbackOverride: 0
|
||||
- serializedVersion: 2
|
||||
buildTarget: XboxOne
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
- serializedVersion: 2
|
||||
buildTarget: Windows Store Apps
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
spriteSheet:
|
||||
serializedVersion: 2
|
||||
sprites: []
|
||||
outline: []
|
||||
physicsShape: []
|
||||
bones: []
|
||||
spriteID: 01ef2571c3a7dca4c9d87e3445ea2964
|
||||
vertices: []
|
||||
indices:
|
||||
edges: []
|
||||
weights: []
|
||||
spritePackingTag:
|
||||
pSDRemoveMatte: 0
|
||||
pSDShowRemoveMatteOption: 0
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
After Width: | Height: | Size: 25 KiB |
|
@ -0,0 +1,143 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 99f5a2cb8513e1a49819dc39f036320a
|
||||
TextureImporter:
|
||||
fileIDToRecycleName: {}
|
||||
externalObjects: {}
|
||||
serializedVersion: 9
|
||||
mipmaps:
|
||||
mipMapMode: 0
|
||||
enableMipMap: 1
|
||||
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
|
||||
isReadable: 0
|
||||
streamingMipmaps: 0
|
||||
streamingMipmapsPriority: 0
|
||||
grayScaleToAlpha: 0
|
||||
generateCubemap: 6
|
||||
cubemapConvolution: 0
|
||||
seamlessCubemap: 0
|
||||
textureFormat: 1
|
||||
maxTextureSize: 2048
|
||||
textureSettings:
|
||||
serializedVersion: 2
|
||||
filterMode: -1
|
||||
aniso: -1
|
||||
mipBias: -100
|
||||
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
|
||||
maxTextureSizeSet: 0
|
||||
compressionQualitySet: 0
|
||||
textureFormatSet: 0
|
||||
platformSettings:
|
||||
- serializedVersion: 2
|
||||
buildTarget: DefaultTexturePlatform
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
- serializedVersion: 2
|
||||
buildTarget: Standalone
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
- serializedVersion: 2
|
||||
buildTarget: iPhone
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
- serializedVersion: 2
|
||||
buildTarget: Android
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
- serializedVersion: 2
|
||||
buildTarget: Windows Store Apps
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
- serializedVersion: 2
|
||||
buildTarget: WebGL
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
spriteSheet:
|
||||
serializedVersion: 2
|
||||
sprites: []
|
||||
outline: []
|
||||
physicsShape: []
|
||||
bones: []
|
||||
spriteID: 78f26b5a2fd9c8a449665effcf2d1a33
|
||||
vertices: []
|
||||
indices:
|
||||
edges: []
|
||||
weights: []
|
||||
spritePackingTag:
|
||||
pSDRemoveMatte: 0
|
||||
pSDShowRemoveMatteOption: 0
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
After Width: | Height: | Size: 14 KiB |
|
@ -0,0 +1,143 @@
|
|||
fileFormatVersion: 2
|
||||
guid: b765d10f7f039904ebfb9e4db1f949b0
|
||||
TextureImporter:
|
||||
fileIDToRecycleName: {}
|
||||
externalObjects: {}
|
||||
serializedVersion: 9
|
||||
mipmaps:
|
||||
mipMapMode: 0
|
||||
enableMipMap: 1
|
||||
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
|
||||
isReadable: 0
|
||||
streamingMipmaps: 0
|
||||
streamingMipmapsPriority: 0
|
||||
grayScaleToAlpha: 0
|
||||
generateCubemap: 6
|
||||
cubemapConvolution: 0
|
||||
seamlessCubemap: 0
|
||||
textureFormat: 1
|
||||
maxTextureSize: 2048
|
||||
textureSettings:
|
||||
serializedVersion: 2
|
||||
filterMode: -1
|
||||
aniso: -1
|
||||
mipBias: -100
|
||||
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: 700
|
||||
spriteBorder: {x: 45, y: 45, z: 45, w: 45}
|
||||
spriteGenerateFallbackPhysicsShape: 1
|
||||
alphaUsage: 1
|
||||
alphaIsTransparency: 1
|
||||
spriteTessellationDetail: -1
|
||||
textureType: 8
|
||||
textureShape: 1
|
||||
singleChannelComponent: 0
|
||||
maxTextureSizeSet: 0
|
||||
compressionQualitySet: 0
|
||||
textureFormatSet: 0
|
||||
platformSettings:
|
||||
- serializedVersion: 2
|
||||
buildTarget: DefaultTexturePlatform
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
- serializedVersion: 2
|
||||
buildTarget: Standalone
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
- serializedVersion: 2
|
||||
buildTarget: iPhone
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
- serializedVersion: 2
|
||||
buildTarget: Android
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
- serializedVersion: 2
|
||||
buildTarget: Windows Store Apps
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
- serializedVersion: 2
|
||||
buildTarget: WebGL
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
spriteSheet:
|
||||
serializedVersion: 2
|
||||
sprites: []
|
||||
outline: []
|
||||
physicsShape: []
|
||||
bones: []
|
||||
spriteID: 9aadd7a7f818c2444a85fa992475615a
|
||||
vertices: []
|
||||
indices:
|
||||
edges: []
|
||||
weights: []
|
||||
spritePackingTag:
|
||||
pSDRemoveMatte: 0
|
||||
pSDShowRemoveMatteOption: 0
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,7 @@
|
|||
This asset is governed by the Asset Store EULA; however, the following components are governed by the licenses indicated below:
|
||||
|
||||
A. Office Code Pro
|
||||
- OFL: see Fonts/LICENSE.txt
|
||||
|
||||
B. CSharpCompiler
|
||||
- MIT: see Extras/exec/CSharpCompiler/LICENSE.txt
|
|
@ -0,0 +1,7 @@
|
|||
fileFormatVersion: 2
|
||||
guid: c73db89ef64357640b17d95065ca2626
|
||||
TextScriptImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,334 @@
|
|||
V2.5.4
|
||||
Addition 0121: Console zoom can now be triggered with hotkeys (default: ctrl+ and ctrl-)
|
||||
Addition 0122: Hotkey for dragging the console is now configurable (default: shift click)
|
||||
Addition 0123: AreActionsExecuting added to query if the console is currently executing actions
|
||||
Change 0064: Optimised input handling under new input system
|
||||
Bug Fix 0064: Fixed bug where speechmarks were not parsed properly for GameObject arguments
|
||||
|
||||
V2.5.3
|
||||
Addition 0120: New core command: max-logs
|
||||
Change 0063: QC will now ignore compiler generated types during table generation resulting in faster load times
|
||||
Bug Fix 0063: Fixed a native crash that would occur under IL2CPP with GeNa installed
|
||||
|
||||
V2.5.2
|
||||
Addition 0119: Added maximum log size setting to prevent huge logs from crashing the console
|
||||
Change 0062: Default prefab now has a maximum log count of 1024 logs
|
||||
Bug Fix 0062: Fixed grammar in error message for when there are no invocation targets
|
||||
|
||||
V2.5.1
|
||||
Addition 0118: Included SRP friendly prefab and theme variants: 'Quantum Console (SRP)' and 'Default Theme (SRP)'
|
||||
Bug Fix 0061: Fixed a case where loggers could initialize too late causing errors when initialize on startup is disabled
|
||||
|
||||
V2.5.0
|
||||
Addition 0113: [CommandPrefix] can now be applied to entire assemblies
|
||||
Addition 0114: New extra command: http.get
|
||||
Addition 0115: New extra command: http.put
|
||||
Addition 0116: New extra command: http.post
|
||||
Addition 0117: New extra command: http.delete
|
||||
Change 0058: Non static invocation will now throw an exception if no targets could be found
|
||||
Change 0059: Non static non MonoBehaviour commands not using MonoTargetType.Registry are now explicitly rejected
|
||||
Change 0060: call-instance now unwraps the inner exception
|
||||
Change 0061: man now uses pretty printing for declaring type names
|
||||
Bug Fix 0059: Fixed a bug where JSON strings would be parsed as expression bodies
|
||||
Bug Fix 0060: Fixed nested type names not being serialized correctly
|
||||
|
||||
V2.4.7
|
||||
Bug Fix 0057: Console display will no longer incorrectly parse rich tags from invoked command
|
||||
Bug Fix 0058: Generic class commands now still work when the command method has overloads
|
||||
|
||||
V2.4.6
|
||||
Addition 0110: Commands declared in generic classes are now supported
|
||||
Addition 0111: New extra command: quit
|
||||
Addition 0112: New extra command: capture-screenshot
|
||||
Change 0057: Improved the default format for timestamps
|
||||
Bug Fix 0055: Fixed issues with new input system when the device does not support a keyboard
|
||||
Bug Fix 0056: Fixed false positives of the IL2CPP primitive operator warning
|
||||
|
||||
V2.4.5
|
||||
Change 0056: The OnLog event now receives an ILog, containing both the log text and type
|
||||
Bug Fix 0054: Fixed a bug where destroyed objects were not removed from the registry
|
||||
|
||||
V2.4.4
|
||||
Bug Fix 0053: Fixed a bug where the max log lines setting would not work properly
|
||||
|
||||
V2.4.3
|
||||
Bug Fix 0052: Fixed ReadKey action on new input system
|
||||
|
||||
V2.4.2
|
||||
Note: In order to keep QC looking the same as before when using the included Blur material, set the Panel Color in the theme to white
|
||||
Change 0055: The blur shader now responds to vertex colors, meaning it is affected by the color of the Image/Sprite renderer
|
||||
Bug Fix 0051: Fixed the QC_DISABLED preprocessor
|
||||
|
||||
V2.4.1
|
||||
Addition 0109: Command suggestions are now clickable
|
||||
Change 0054: call-static now unwraps the inner exception
|
||||
Bug Fix 0048: Fixed instances of the command name not including prefixes in its manual
|
||||
Bug Fix 0049: Fixed an issue where changes to the console scaling in edit mode would be lost
|
||||
Bug Fix 0050: Resolved an error that could occur during certain operator syntax checks
|
||||
|
||||
V2.4.0
|
||||
Note: due to restructuring it is recommended that you remove your current installation before updating
|
||||
Addition 0106: Added the Command Actions system
|
||||
Addition 0107: Logs can now be made to the console without a leading newline
|
||||
Addition 0108: Timestamp format can now be configured via the QuantumTheme
|
||||
Change 0052: Blank log lines are now allowed
|
||||
Change 0053: Hardcoded color formatting has been removed
|
||||
Bug Fix 0047: Fixed the banner being rendered incorrectly on HighDPI displays
|
||||
|
||||
V2.3.7
|
||||
Addition 0105: Native support for new input system
|
||||
|
||||
V2.3.6
|
||||
Change 0051: Optimised text processing code to reduce allocations
|
||||
Bug Fix 0046: Type parser/serializer now support tuple syntax
|
||||
|
||||
V2.3.5
|
||||
Change 0050: Optimised get-object-info
|
||||
Addition 0101: Console UI can now be resized at runtime
|
||||
Addition 0102: New extra command: get-scene-hierarchy
|
||||
Addition 0103: New extra command: write-file
|
||||
Addition 0104: New extra command: read-file
|
||||
|
||||
V2.3.4
|
||||
Change 0046: Improved hotkey handling so there are no longer false positives or collisions
|
||||
Change 0047: Improved when the console steals input and no longer does it on mobile platforms
|
||||
Change 0048: Improved performance of GameObject parser
|
||||
Change 0049: Reverted the invocation message changes introduced in V2.3.3
|
||||
Addition 0097: New user extendable preprocessor system
|
||||
Addition 0098: New extra command: call-static
|
||||
Addition 0099: New extra command: call-instance
|
||||
Addition 0100: Addition of [NoInject] for all injection based systems
|
||||
Bug Fix 0041: Fixed a singleton QC destroying itself if the gameobject is disabled then enabled
|
||||
Bug Fix 0042: Fixed the GameObject parser being unable to parse inactive DontDestroyOnLoad objects
|
||||
Bug Fix 0043: Fixed IL2CPP alloc crash that could be encountered in a multi target command invocation
|
||||
Bug Fix 0044: Inner exceptions in binary operator invocation are now properly displayed in the console
|
||||
Bug Fix 0045: The AutoScroll:Always option now works
|
||||
|
||||
V2.3.3
|
||||
Brand new documentation: https://qfsw.co.uk/docs/QC/
|
||||
Change 0045: Improved invocation messages for commands without a return
|
||||
Addition 0093: New MonoTargetType: SingleInactive
|
||||
Addition 0094: New MonoTargetType: AllInactive
|
||||
Addition 0095: Added logging level option and command
|
||||
Addition 0096: Added TryAddCommand to processor for runtime addition of commands
|
||||
Bug Fix 0039: Primitive parser now behave correctly on non English locales
|
||||
Bug Fix 0040: Fixed primitive operators with high stripping level enabled
|
||||
|
||||
V2.3.2
|
||||
Change 0043: Optimised command table generation
|
||||
Change 0044: Changed sort order so that it is higher than default
|
||||
Bug Fix 0035: Fixed a bug where fuzzy case sensitive command suggestion sorting would not work
|
||||
Bug Fix 0036: Primitive casts in expression bodies now work in IL2CPP
|
||||
Bug Fix 0037: Fixed [Preserve] error reported in specific 2018.3 versions
|
||||
Bug Fix 0038: Fixed a bug where the UI control panel would not receive theme updates
|
||||
|
||||
V2.3.1
|
||||
Change 0043: Vectors and Quaternions now use recursive parsing for their constituents
|
||||
Change 0044: Boolean parser now accepts yes and no values
|
||||
Bug Fix 0035: Reworked scoping so that nested collections using different scope tokens works again e.g. [(1,2),(3,4)]
|
||||
Bug Fix 0036: Fixed many stripping issues when high stripping level is enabled
|
||||
|
||||
V2.3.0
|
||||
Upgrade Note: TMP and 2018.3+ are now required, full upgrade guide at https://www.qfsw.co.uk/docs/QC/Upgrade230/
|
||||
Addition 0071: UI can now be scaled at runtime
|
||||
Addition 0072: New user extendable serialization system
|
||||
Addition 0073: ITuples can now be serialized (.NET 4.6 compatibility level only)
|
||||
Addition 0074: Vector2Int/Vector3Int can now be serialized
|
||||
Addition 0075: New user extendable parser system
|
||||
Addition 0076: HashSets/LinkedList/ConcurrentStack/ConcurrentQueue/ConcurrentBags are now a parseable arguments
|
||||
Addition 0077: IEnumerable/ICollection/IReadOnlyCollection/IList/IReadOnlyLists are now a parseable arguments
|
||||
Addition 0078: Vector2Int/Vector3Ints are now a parseable arguments
|
||||
Addition 0079: Tuple/ValueTuples are now parseable arguments
|
||||
Addition 0080: New user extendable custom grammar construct system
|
||||
Addition 0081: Expression bodies can now be used to use one command as an argument to another - {expr}
|
||||
Addition 0082: Nullable expression bodies allow null values to pass through - {expr}?
|
||||
Addition 0083: Boolean values/expressions can now be negated with !
|
||||
Addition 0084: Binary operators can now be used in the console input (+ - * / %)
|
||||
Addition 0085: QC now has a proper singleton mode
|
||||
Addition 0086: New [QcIgnore] attribute which informs QC to ignore classes/assemblies
|
||||
Addition 0087: New command: user-commands
|
||||
Addition 0088: New command: qc-script-extern
|
||||
Addition 0089: New extra command: instantiate-prefab
|
||||
Addition 0090: New extra command: instantiate-model
|
||||
Addition 0091: New extra command: destroy-component
|
||||
Addition 0092: Stadia and Lumin platforms have been added to the command platforms
|
||||
Change 0032: Visual theme of the UI has been greatly improved
|
||||
Change 0033: Command table generation is now multithreaded and over 10x faster
|
||||
Change 0034: Parsing and serialization is now significantly faster
|
||||
Change 0035: Improved console text regeneration so that it happens at most once per frame
|
||||
Change 0036: Internal naming conventions and APIs have been overhauled
|
||||
Change 0037: Custom inspectors now work properly on 2019.3+
|
||||
Change 0038: man command now displays the declaring type(s)
|
||||
Change 0039: get-object-info command now displays direct children
|
||||
Change 0040: Key configuration has been moved to QuantumKeyConfiguration
|
||||
Change 0041: Increased the scroll sensitivity
|
||||
Change 0042: [CommandPrefix] can now be used on structs
|
||||
Bug Fix 0025: Fixed the drag not working
|
||||
Bug Fix 0026: Fixed a bug where the targets of a multicast command would not be alphanumerically ordered
|
||||
Bug Fix 0027: Multidimensional array type names are now serialized correctly
|
||||
Bug Fix 0028: Multidimensional array type names are now parsed correctly
|
||||
Bug Fix 0029: Fixed a concurrency bug with QC's async logging
|
||||
Bug Fix 0030: Job counter UI now receives theme changes
|
||||
Bug Fix 0031: Fixed a bug where generics could trigger rich formatting in the input field
|
||||
Bug Fix 0032: Fixed a bug where ColorText would fail on IL2CPP with non opaque colors
|
||||
Bug Fix 0033: BadImageFormatException issue has been tracked upstream to Mono and is now ignored
|
||||
Bug Fix 0034: Removed leading blank line in get-object-info
|
||||
|
||||
V2.2.2
|
||||
Addition 0064: Quantum Console now has a brand new look
|
||||
Addition 0065: Non static commands can now be used on non-monobehaviours (Quantum Registry must be used)
|
||||
Addition 0066: Formatting in registry errors is now greatly improved
|
||||
Addition 0067: Quantum Theme can now take a custom material and color
|
||||
Addition 0068: Quantum Console can now be dragged (default shift + click)
|
||||
Addition 0069: New extra command: start-coroutine
|
||||
Addition 0070: New extra command: msaa
|
||||
Change 0029: Improved readability of collection formatters on dark theme
|
||||
Change 0030: Improved readability Quantum Theme inspector on dark theme
|
||||
Change 0031: Improved extra command get-object-info
|
||||
Bug Fix 0022: Improved stability of TMP upgrader
|
||||
Bug Fix 0023: Fixed stability issues with theme application
|
||||
Bug Fix 0024: Fixed a bug where QC would complain about weak delegates even if they were not being used as a command
|
||||
|
||||
V2.2.1
|
||||
Addition 0064: New MonoTargetType: Singleton
|
||||
Addition 0065: New extra command: bind
|
||||
Addition 0066: New extra command: unbind
|
||||
Addition 0067: New extra command: unbind-all
|
||||
Addition 0068: New extra command: display-bindings
|
||||
Change 0029: Many parts of Quantum Console have been massively optimised
|
||||
Bug Fix 0022: Fixed a bug where the input field would not focus the first time the console is opened
|
||||
|
||||
V2.2.0
|
||||
Addition 0060: Added TMP support
|
||||
Addition 0061: Added support for backwards command suggestion cycling
|
||||
Addition 0062: New console command: verbose-errors
|
||||
Addition 0063: New console command: verbose-logging
|
||||
Change 0026: Improved bool parsing to support on/off and 1/0
|
||||
Change 0027: Errors are now more user friendly when using enum arguments
|
||||
Change 0028: Optimised text generation to reduce string size
|
||||
|
||||
V2.1.3
|
||||
Addition 0057: Font can now be controlled from the Quantum Theme
|
||||
Addition 0058: Added QC_DISABLE_BUILTIN_ALL to disable all built in commands
|
||||
Addition 0059: Added QC_DISABLE_BUILTIN_EXTRA to disable all extra commands
|
||||
Bug Fix 0021: Fixed a bug where abstract and virtual commands would cause duplicates to appear
|
||||
|
||||
V2.1.2
|
||||
Addition 0039: Maximum number of logs can now be restricted
|
||||
Addition 0040: New extra command: enum-info (added enum colouring to default theme)
|
||||
Addition 0041: New extra command: all-scenes
|
||||
Addition 0042: New extra command: loaded-scenes
|
||||
Addition 0043: New extra command: active-scene
|
||||
Addition 0044: New extra command: set-active-scene
|
||||
Addition 0045: New extra command: unload-scene
|
||||
Addition 0046: New extra command: unload-scene-index
|
||||
Addition 0047: New extra command: max-fps
|
||||
Addition 0048: New extra command: vsync
|
||||
Addition 0049: New extra command: set-resolution
|
||||
Addition 0050: New extra command: current-resolutin
|
||||
Addition 0051: New extra command: supported-resolutions
|
||||
Addition 0052: New extra command: fullscreen
|
||||
Addition 0053: New extra command: screen-dpi
|
||||
Addition 0054: New extra command: screen-orientation
|
||||
Addition 0055: New extra command: time-scale
|
||||
Addition 0056: Added MobilePlatforms shortcut to Platform
|
||||
Change 0020: QC no longer needs the .NET 4.6 API compatability level and only the scripting backend
|
||||
Change 0021: QC now internally uses string builders for improved performance
|
||||
Change 0022: Default theme now has IEnumerators default to line seperation and ICollections to [a, b, c]
|
||||
Change 0023: Extra commands now use their own assembly
|
||||
Change 0024: Scene commands have been moved to their own file
|
||||
Change 0025: Scene load/unload commands are now async
|
||||
Bug Fix 0016: Fixed a bug where auto named commands and command prefixes would not work on fields or classes in Roslyn
|
||||
Bug Fix 0017: Fixed a bug where initialize on startup option would not hide the console
|
||||
Bug Fix 0018: Fixed a bug where whitespace would be treated as args
|
||||
Bug Fix 0019: Fixed the Switch enum value having the incorrect bit value
|
||||
Bug Fix 0020: Fixed .NET auto upgrader
|
||||
|
||||
V2.1.1
|
||||
Addition 0037: Added [CommandPrefix] attribute. Adding this to a class will prepend its prefix to all commands created within the class
|
||||
Addition 0038: Console will now automatically open when a log of the specified severity is encountered
|
||||
|
||||
V2.1.0
|
||||
Addition 0036: Async commands are now fully supported
|
||||
Change 0017: exec and exec-extern are now async commands
|
||||
Change 0018: exec and all related code has been moved to Extras/exec for easy removal if desired
|
||||
Change 0019: exec will no longer appear on iOS, PS4, Switch or Xbox One
|
||||
Bug Fix 0013: Input text no longer becomes highlighted when using the command history
|
||||
Bug Fix 0014: get-object-info command will now throw a proper error on failure
|
||||
Bug Fix 0015: Fixed a bug where TypeFormatters and thus theme objects would be corrupted when moving across specific Unity versions
|
||||
|
||||
V2.0.2
|
||||
Addition 0033: Added visibility toggle for scene view mode
|
||||
Addition 0034: QC can now be easily disabled on release builds, builds etc.
|
||||
Addition 0035: Added verbose modes to exception handling and log interception
|
||||
|
||||
V2.0.1
|
||||
Addition 0030: Async and thread safe support for logs and Debug.Logs
|
||||
Addition 0031: Option to initialise the console on startup without activating it
|
||||
Addition 0032: Scene persistence option
|
||||
Change 0016: Exposed the Toggle function to the public API
|
||||
Bug Fix 0011: Fixed a bug where logs and Debug.Logs occuring before the console was initialised would be dropped
|
||||
Bug Fix 0012: Stopped editor warnings on 2018.3+
|
||||
|
||||
V2.0.0
|
||||
Note: It is recommended you remove Quantum Console from your project before downloading this update
|
||||
Addition 0010: Generic commands are now supported
|
||||
Addition 0011: Macros are now supported
|
||||
Addition 0012: New Quantum Theme system; themes are fully customisable and control formatting of returns
|
||||
Addition 0013: Case sensitivity is now an option for command autocompletion
|
||||
Addition 0014: Optional popup display for suggested commands
|
||||
Addition 0015: Namespace system has been added for type resolution
|
||||
Addition 0016: Nested collections are now supported as arguments
|
||||
Addition 0017: Stacks and Queues are now supported as arguments
|
||||
Addition 0018: Type parser now supports primitives, arrays, generics and namespaces
|
||||
Addition 0019: Type formatter has been massively improved
|
||||
Addition 0020: Formatter now supports Dictionaries and KeyValuePairs
|
||||
Addition 0021: 'null' is now supported as an argument for all reference types
|
||||
Addition 0022: Toggleable timestamps for logs
|
||||
Addition 0023: Autoscrolling feature for the Quantum Console
|
||||
Addition 0024: Improved formatting for inputted commands in the console log
|
||||
Addition 0025: New extra command: add-component
|
||||
Addition 0026: New extra command: teleport-relative
|
||||
Addition 0027: New extra command: set-parent
|
||||
Addition 0028: New extra command: rotate
|
||||
Addition 0029: Brand new demo scene
|
||||
Change 0003: Return serialization has been massively improved
|
||||
Change 0004: Invocation and serialiazation have been decoupled
|
||||
Change 0005: Text processing has been hugely improved, properly supporting escape characters and scope control
|
||||
Change 0006: Color and vector parsing has been improved
|
||||
Change 0007: Scroll sensitivity has been increased
|
||||
Change 0008: Source has been restructured
|
||||
Change 0009: All parsing related functionality has been moved to QuantumParser
|
||||
Change 0010: All registry related functionality has been moved to QuantumRegistry
|
||||
Change 0011: Registry commands are now generic
|
||||
Change 0012: Formatting in get-object-info has been improved
|
||||
Change 0013: CTRL and CMD are now one option in keybindings, and SHIFT has been added as a modifier
|
||||
Change 0014: Removed various command aliases
|
||||
Change 0015: exec and exec-extern have been removed from WebGL
|
||||
Bug Fix 0002: Autocompletion sort order for fuzzy searches has been improved
|
||||
Bug Fix 0003: Command history is no longer cleared on console clear
|
||||
Bug Fix 0004: Fixed a bug where 'double' type would be displayed as 'int'
|
||||
Bug Fix 0005: Exception style logs are now formatted correctly
|
||||
Bug Fix 0006: Fixed GetRegistryContents<T>
|
||||
Bug Fix 0007: Fixed a bug where writer commands were generated for readonly/const fields
|
||||
Bug Fix 0008: CloseOnSubmit now works
|
||||
Bug Fix 0009: Fixed a bug where commands with unsupported array typed parameters would not be rejected
|
||||
Bug Fix 0010: Fixed a bug where the inspector would throw errors during playmode
|
||||
|
||||
V1.0.2
|
||||
Addition 0006: Arrays are now a supported parameter type
|
||||
Addition 0007: Lists are now a supported paramater type
|
||||
Addition 0008: Processor now properly formats generic types
|
||||
Addition 0009: Arrays, Lists and all other IEnumerables will now be properly formatted when returned
|
||||
Change 0002: Improved internal assemblies
|
||||
|
||||
V1.0.1
|
||||
Addition 0002: Added support for delegate commands
|
||||
Addition 0003: Enums are now a supported parameter type
|
||||
Addition 0004: New extra command: load-scene
|
||||
Addition 0005: New extra command: send-message
|
||||
Change 0001: Improved internal code organisation
|
||||
Bug Fix 0001: Better supports 2018.3b
|
||||
|
||||
V1.0.0
|
||||
Initial release
|
|
@ -0,0 +1,7 @@
|
|||
fileFormatVersion: 2
|
||||
guid: da7b1060a39034f64b9568c74ba675d8
|
||||
TextScriptImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,8 @@
|
|||
fileFormatVersion: 2
|
||||
guid: ed61ebfbaaf591f40a51900ce1a5c898
|
||||
timeCreated: 1541374714
|
||||
licenseType: Store
|
||||
DefaultImporter:
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -231,6 +231,8 @@ MonoBehaviour:
|
|||
m_Script: {fileID: 11500000, guid: b64a96362efa9ba44802d57e2e074f27, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
_defaultValue:
|
||||
_prefix:
|
||||
_postfix:
|
||||
--- !u!1 &9027889519720641281
|
||||
GameObject:
|
||||
|
@ -438,8 +440,8 @@ MonoBehaviour:
|
|||
m_Script: {fileID: 11500000, guid: 28b9e93c12a050746982d0ae2c8dab98, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
_scoreAdd: 0
|
||||
_timeBonus: 30
|
||||
_selfDestroy: 0
|
||||
--- !u!1 &9027889519819089751
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
|
@ -752,37 +754,37 @@ PrefabInstance:
|
|||
- target: {fileID: 925482383945416140, guid: 12c9d9623955d4e48825c5b19ea0b159,
|
||||
type: 3}
|
||||
propertyPath: m_LocalPosition.x
|
||||
value: -577.1286
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 925482383945416140, guid: 12c9d9623955d4e48825c5b19ea0b159,
|
||||
type: 3}
|
||||
propertyPath: m_LocalPosition.y
|
||||
value: -183.81604
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 925482383945416140, guid: 12c9d9623955d4e48825c5b19ea0b159,
|
||||
type: 3}
|
||||
propertyPath: m_LocalPosition.z
|
||||
value: 932.67645
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 925482383945416140, guid: 12c9d9623955d4e48825c5b19ea0b159,
|
||||
type: 3}
|
||||
propertyPath: m_LocalRotation.w
|
||||
value: 0.6990287
|
||||
value: 1
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 925482383945416140, guid: 12c9d9623955d4e48825c5b19ea0b159,
|
||||
type: 3}
|
||||
propertyPath: m_LocalRotation.x
|
||||
value: -0.17240688
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 925482383945416140, guid: 12c9d9623955d4e48825c5b19ea0b159,
|
||||
type: 3}
|
||||
propertyPath: m_LocalRotation.y
|
||||
value: -0.6825062
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 925482383945416140, guid: 12c9d9623955d4e48825c5b19ea0b159,
|
||||
type: 3}
|
||||
propertyPath: m_LocalRotation.z
|
||||
value: -0.1257779
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 925482383945416140, guid: 12c9d9623955d4e48825c5b19ea0b159,
|
||||
type: 3}
|
||||
|
@ -834,7 +836,8 @@ PrefabInstance:
|
|||
propertyPath: m_Enabled
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
m_RemovedComponents: []
|
||||
m_RemovedComponents:
|
||||
- {fileID: 925482383945416143, guid: 12c9d9623955d4e48825c5b19ea0b159, type: 3}
|
||||
m_SourcePrefab: {fileID: 100100000, guid: 12c9d9623955d4e48825c5b19ea0b159, type: 3}
|
||||
--- !u!4 &5145598549098378746 stripped
|
||||
Transform:
|
||||
|
|
|
@ -1138,7 +1138,9 @@ MonoBehaviour:
|
|||
m_Script: {fileID: 11500000, guid: 4a14752bce1e85a47ad22bd4e89cbe2f, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
_postfix:
|
||||
_defaultValue:
|
||||
_prefix:
|
||||
_postfix: " \u044D\u043D."
|
||||
--- !u!1 &1647452393
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
|
@ -3639,11 +3641,11 @@ MonoBehaviour:
|
|||
targetRigidbody2D: {fileID: 0}
|
||||
targetTransform: {fileID: 7985013476349946332}
|
||||
_result:
|
||||
position: {x: 104.326294, y: -5.5460205, z: -1932.3633}
|
||||
up: {x: 0, y: 1, z: 0}
|
||||
forward: {x: -0.001450564, y: 0.002455365, z: 0.99999595}
|
||||
color: {r: 1, g: 1, b: 1, a: 1}
|
||||
size: 1
|
||||
position: {x: 0, y: 0, z: 0}
|
||||
up: {x: 0, y: 0, z: 0}
|
||||
forward: {x: 0, y: 0, z: 0}
|
||||
color: {r: 0, g: 0, b: 0, a: 0}
|
||||
size: 0
|
||||
percent: 0
|
||||
_finalResult:
|
||||
position: {x: 104.326294, y: -5.5460205, z: -1932.3633}
|
||||
|
@ -3749,7 +3751,7 @@ MonoBehaviour:
|
|||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
_mainPanel: {fileID: 2874212760557784321}
|
||||
_tutorPanel: {fileID: 1955516150}
|
||||
_tutorPanel: {fileID: 9202471761446870197}
|
||||
_progressBarImage: {fileID: 3460062592487292032}
|
||||
LeftTrigger: {fileID: -5982496924579745919, guid: e39f4b35a6db18348b41eb0262520e69,
|
||||
type: 3}
|
||||
|
@ -3931,6 +3933,8 @@ MonoBehaviour:
|
|||
m_Script: {fileID: 11500000, guid: b64a96362efa9ba44802d57e2e074f27, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
_defaultValue:
|
||||
_prefix:
|
||||
_postfix:
|
||||
--- !u!1 &7985013476380022744
|
||||
GameObject:
|
||||
|
@ -4190,6 +4194,8 @@ MonoBehaviour:
|
|||
m_Script: {fileID: 11500000, guid: 726321230e0043c409946c98a7055152, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
_defaultValue:
|
||||
_prefix:
|
||||
_postfix: " \u043A\u043C/\u0447"
|
||||
--- !u!1 &7985013476728618132
|
||||
GameObject:
|
||||
|
@ -7506,201 +7512,6 @@ PrefabInstance:
|
|||
m_Modification:
|
||||
m_TransformParent: {fileID: 7185685602648263643}
|
||||
m_Modifications:
|
||||
- target: {fileID: 2197034094981908278, guid: 4a88f6f36bda305499bdcac5bcc22d90,
|
||||
type: 3}
|
||||
propertyPath: savedFill
|
||||
value: 1
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 2197034094981908278, guid: 4a88f6f36bda305499bdcac5bcc22d90,
|
||||
type: 3}
|
||||
propertyPath: savedUp.x
|
||||
value: 3.1465978e-13
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 2197034094981908278, guid: 4a88f6f36bda305499bdcac5bcc22d90,
|
||||
type: 3}
|
||||
propertyPath: savedUp.y
|
||||
value: 1
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 2197034094981908278, guid: 4a88f6f36bda305499bdcac5bcc22d90,
|
||||
type: 3}
|
||||
propertyPath: savedUp.z
|
||||
value: 2.201165e-11
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 2197034094981908278, guid: 4a88f6f36bda305499bdcac5bcc22d90,
|
||||
type: 3}
|
||||
propertyPath: savedPos.x
|
||||
value: 0.00828664
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 2197034094981908278, guid: 4a88f6f36bda305499bdcac5bcc22d90,
|
||||
type: 3}
|
||||
propertyPath: savedPos.y
|
||||
value: 18.494493
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 2197034094981908278, guid: 4a88f6f36bda305499bdcac5bcc22d90,
|
||||
type: 3}
|
||||
propertyPath: savedPos.z
|
||||
value: -0.11507933
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 2197034094981908278, guid: 4a88f6f36bda305499bdcac5bcc22d90,
|
||||
type: 3}
|
||||
propertyPath: savedColor.a
|
||||
value: 1
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 2197034094981908278, guid: 4a88f6f36bda305499bdcac5bcc22d90,
|
||||
type: 3}
|
||||
propertyPath: savedColor.b
|
||||
value: 1
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 2197034094981908278, guid: 4a88f6f36bda305499bdcac5bcc22d90,
|
||||
type: 3}
|
||||
propertyPath: savedColor.g
|
||||
value: 1
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 2197034094981908278, guid: 4a88f6f36bda305499bdcac5bcc22d90,
|
||||
type: 3}
|
||||
propertyPath: savedColor.r
|
||||
value: 1
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 2197034094981908278, guid: 4a88f6f36bda305499bdcac5bcc22d90,
|
||||
type: 3}
|
||||
propertyPath: savedRectSize.x
|
||||
value: 663.338
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 2197034094981908278, guid: 4a88f6f36bda305499bdcac5bcc22d90,
|
||||
type: 3}
|
||||
propertyPath: savedRectSize.y
|
||||
value: 63.013
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 3068211644373382748, guid: 4a88f6f36bda305499bdcac5bcc22d90,
|
||||
type: 3}
|
||||
propertyPath: savedFill
|
||||
value: 1
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 3068211644373382748, guid: 4a88f6f36bda305499bdcac5bcc22d90,
|
||||
type: 3}
|
||||
propertyPath: savedUp.x
|
||||
value: 3.1465978e-13
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 3068211644373382748, guid: 4a88f6f36bda305499bdcac5bcc22d90,
|
||||
type: 3}
|
||||
propertyPath: savedUp.y
|
||||
value: 1
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 3068211644373382748, guid: 4a88f6f36bda305499bdcac5bcc22d90,
|
||||
type: 3}
|
||||
propertyPath: savedUp.z
|
||||
value: 2.201165e-11
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 3068211644373382748, guid: 4a88f6f36bda305499bdcac5bcc22d90,
|
||||
type: 3}
|
||||
propertyPath: savedPos.x
|
||||
value: 0.00828664
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 3068211644373382748, guid: 4a88f6f36bda305499bdcac5bcc22d90,
|
||||
type: 3}
|
||||
propertyPath: savedPos.y
|
||||
value: 18.494493
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 3068211644373382748, guid: 4a88f6f36bda305499bdcac5bcc22d90,
|
||||
type: 3}
|
||||
propertyPath: savedPos.z
|
||||
value: -0.11507933
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 3068211644373382748, guid: 4a88f6f36bda305499bdcac5bcc22d90,
|
||||
type: 3}
|
||||
propertyPath: savedColor.a
|
||||
value: 1
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 3068211644373382748, guid: 4a88f6f36bda305499bdcac5bcc22d90,
|
||||
type: 3}
|
||||
propertyPath: savedColor.g
|
||||
value: 1
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 3068211644373382748, guid: 4a88f6f36bda305499bdcac5bcc22d90,
|
||||
type: 3}
|
||||
propertyPath: savedColor.r
|
||||
value: 0.71158946
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 3068211644373382748, guid: 4a88f6f36bda305499bdcac5bcc22d90,
|
||||
type: 3}
|
||||
propertyPath: savedRectSize.x
|
||||
value: 663.338
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 3068211644373382748, guid: 4a88f6f36bda305499bdcac5bcc22d90,
|
||||
type: 3}
|
||||
propertyPath: savedRectSize.y
|
||||
value: 63.013
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 4913003076036444960, guid: 4a88f6f36bda305499bdcac5bcc22d90,
|
||||
type: 3}
|
||||
propertyPath: savedFill
|
||||
value: 1
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 4913003076036444960, guid: 4a88f6f36bda305499bdcac5bcc22d90,
|
||||
type: 3}
|
||||
propertyPath: savedUp.x
|
||||
value: 3.1465978e-13
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 4913003076036444960, guid: 4a88f6f36bda305499bdcac5bcc22d90,
|
||||
type: 3}
|
||||
propertyPath: savedUp.y
|
||||
value: 1
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 4913003076036444960, guid: 4a88f6f36bda305499bdcac5bcc22d90,
|
||||
type: 3}
|
||||
propertyPath: savedUp.z
|
||||
value: 2.201165e-11
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 4913003076036444960, guid: 4a88f6f36bda305499bdcac5bcc22d90,
|
||||
type: 3}
|
||||
propertyPath: savedPos.x
|
||||
value: 0.009404147
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 4913003076036444960, guid: 4a88f6f36bda305499bdcac5bcc22d90,
|
||||
type: 3}
|
||||
propertyPath: savedPos.y
|
||||
value: -190.99933
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 4913003076036444960, guid: 4a88f6f36bda305499bdcac5bcc22d90,
|
||||
type: 3}
|
||||
propertyPath: savedPos.z
|
||||
value: 0.14092928
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 4913003076036444960, guid: 4a88f6f36bda305499bdcac5bcc22d90,
|
||||
type: 3}
|
||||
propertyPath: savedColor.a
|
||||
value: 1
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 4913003076036444960, guid: 4a88f6f36bda305499bdcac5bcc22d90,
|
||||
type: 3}
|
||||
propertyPath: savedColor.b
|
||||
value: 1
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 4913003076036444960, guid: 4a88f6f36bda305499bdcac5bcc22d90,
|
||||
type: 3}
|
||||
propertyPath: savedColor.g
|
||||
value: 1
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 4913003076036444960, guid: 4a88f6f36bda305499bdcac5bcc22d90,
|
||||
type: 3}
|
||||
propertyPath: savedColor.r
|
||||
value: 1
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 4913003076036444960, guid: 4a88f6f36bda305499bdcac5bcc22d90,
|
||||
type: 3}
|
||||
propertyPath: savedRectSize.x
|
||||
value: 271.883
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 4913003076036444960, guid: 4a88f6f36bda305499bdcac5bcc22d90,
|
||||
type: 3}
|
||||
propertyPath: savedRectSize.y
|
||||
value: 271.883
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 6365554433948213058, guid: 4a88f6f36bda305499bdcac5bcc22d90,
|
||||
type: 3}
|
||||
propertyPath: m_Alpha
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 9202471761387014830, guid: 4a88f6f36bda305499bdcac5bcc22d90,
|
||||
type: 3}
|
||||
propertyPath: m_Pivot.x
|
||||
|
@ -7811,11 +7622,6 @@ PrefabInstance:
|
|||
propertyPath: m_Name
|
||||
value: VisorCanvas
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 9202471761387014834, guid: 4a88f6f36bda305499bdcac5bcc22d90,
|
||||
type: 3}
|
||||
propertyPath: angle
|
||||
value: 180
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 9202471761387014835, guid: 4a88f6f36bda305499bdcac5bcc22d90,
|
||||
type: 3}
|
||||
propertyPath: m_Camera
|
||||
|
@ -7823,24 +7629,6 @@ PrefabInstance:
|
|||
objectReference: {fileID: 7185685602646741319}
|
||||
m_RemovedComponents: []
|
||||
m_SourcePrefab: {fileID: 100100000, guid: 4a88f6f36bda305499bdcac5bcc22d90, type: 3}
|
||||
--- !u!1 &1184396203059313786 stripped
|
||||
GameObject:
|
||||
m_CorrespondingSourceObject: {fileID: 8059874730754158137, guid: 4a88f6f36bda305499bdcac5bcc22d90,
|
||||
type: 3}
|
||||
m_PrefabInstance: {fileID: 9202471760028783171}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
--- !u!225 &1955516150
|
||||
CanvasGroup:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 1184396203059313786}
|
||||
m_Enabled: 1
|
||||
m_Alpha: 1
|
||||
m_Interactable: 1
|
||||
m_BlocksRaycasts: 1
|
||||
m_IgnoreParentGroups: 0
|
||||
--- !u!225 &2874212760557784321 stripped
|
||||
CanvasGroup:
|
||||
m_CorrespondingSourceObject: {fileID: 6365554433948213058, guid: 4a88f6f36bda305499bdcac5bcc22d90,
|
||||
|
@ -7859,3 +7647,9 @@ MonoBehaviour:
|
|||
m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
--- !u!225 &9202471761446870197 stripped
|
||||
CanvasGroup:
|
||||
m_CorrespondingSourceObject: {fileID: 1955516150, guid: 4a88f6f36bda305499bdcac5bcc22d90,
|
||||
type: 3}
|
||||
m_PrefabInstance: {fileID: 9202471760028783171}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
|
|
|
@ -0,0 +1,8 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 6c1eeffb375f85242b020d6da947ffc4
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,131 @@
|
|||
%YAML 1.1
|
||||
%TAG !u! tag:unity3d.com,2011:
|
||||
--- !u!1001 &3809675095417365283
|
||||
PrefabInstance:
|
||||
m_ObjectHideFlags: 0
|
||||
serializedVersion: 2
|
||||
m_Modification:
|
||||
m_TransformParent: {fileID: 0}
|
||||
m_Modifications:
|
||||
- target: {fileID: 1011916610372698401, guid: d5c0d58890a7e7840b47863ed98e5c6e,
|
||||
type: 3}
|
||||
propertyPath: Prefix
|
||||
value: '+ '
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 1011916610372698401, guid: d5c0d58890a7e7840b47863ed98e5c6e,
|
||||
type: 3}
|
||||
propertyPath: Postfix
|
||||
value: " \u043E\u0447\u043A\u043E\u0432"
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 2756876663177930824, guid: d5c0d58890a7e7840b47863ed98e5c6e,
|
||||
type: 3}
|
||||
propertyPath: m_Pivot.x
|
||||
value: 0.5
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 2756876663177930824, guid: d5c0d58890a7e7840b47863ed98e5c6e,
|
||||
type: 3}
|
||||
propertyPath: m_Pivot.y
|
||||
value: 0.5
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 2756876663177930824, guid: d5c0d58890a7e7840b47863ed98e5c6e,
|
||||
type: 3}
|
||||
propertyPath: m_RootOrder
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 2756876663177930824, guid: d5c0d58890a7e7840b47863ed98e5c6e,
|
||||
type: 3}
|
||||
propertyPath: m_AnchorMax.x
|
||||
value: 0.5
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 2756876663177930824, guid: d5c0d58890a7e7840b47863ed98e5c6e,
|
||||
type: 3}
|
||||
propertyPath: m_AnchorMax.y
|
||||
value: 0.5
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 2756876663177930824, guid: d5c0d58890a7e7840b47863ed98e5c6e,
|
||||
type: 3}
|
||||
propertyPath: m_AnchorMin.x
|
||||
value: 0.5
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 2756876663177930824, guid: d5c0d58890a7e7840b47863ed98e5c6e,
|
||||
type: 3}
|
||||
propertyPath: m_AnchorMin.y
|
||||
value: 0.5
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 2756876663177930824, guid: d5c0d58890a7e7840b47863ed98e5c6e,
|
||||
type: 3}
|
||||
propertyPath: m_SizeDelta.x
|
||||
value: 209.39
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 2756876663177930824, guid: d5c0d58890a7e7840b47863ed98e5c6e,
|
||||
type: 3}
|
||||
propertyPath: m_SizeDelta.y
|
||||
value: 100
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 2756876663177930824, guid: d5c0d58890a7e7840b47863ed98e5c6e,
|
||||
type: 3}
|
||||
propertyPath: m_LocalPosition.x
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 2756876663177930824, guid: d5c0d58890a7e7840b47863ed98e5c6e,
|
||||
type: 3}
|
||||
propertyPath: m_LocalPosition.y
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 2756876663177930824, guid: d5c0d58890a7e7840b47863ed98e5c6e,
|
||||
type: 3}
|
||||
propertyPath: m_LocalPosition.z
|
||||
value: -0.1
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 2756876663177930824, guid: d5c0d58890a7e7840b47863ed98e5c6e,
|
||||
type: 3}
|
||||
propertyPath: m_LocalRotation.w
|
||||
value: 1
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 2756876663177930824, guid: d5c0d58890a7e7840b47863ed98e5c6e,
|
||||
type: 3}
|
||||
propertyPath: m_LocalRotation.x
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 2756876663177930824, guid: d5c0d58890a7e7840b47863ed98e5c6e,
|
||||
type: 3}
|
||||
propertyPath: m_LocalRotation.y
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 2756876663177930824, guid: d5c0d58890a7e7840b47863ed98e5c6e,
|
||||
type: 3}
|
||||
propertyPath: m_LocalRotation.z
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 2756876663177930824, guid: d5c0d58890a7e7840b47863ed98e5c6e,
|
||||
type: 3}
|
||||
propertyPath: m_AnchoredPosition.x
|
||||
value: -54.7
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 2756876663177930824, guid: d5c0d58890a7e7840b47863ed98e5c6e,
|
||||
type: 3}
|
||||
propertyPath: m_AnchoredPosition.y
|
||||
value: -82.3
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 2756876663177930824, guid: d5c0d58890a7e7840b47863ed98e5c6e,
|
||||
type: 3}
|
||||
propertyPath: m_LocalEulerAnglesHint.x
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 2756876663177930824, guid: d5c0d58890a7e7840b47863ed98e5c6e,
|
||||
type: 3}
|
||||
propertyPath: m_LocalEulerAnglesHint.y
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 2756876663177930824, guid: d5c0d58890a7e7840b47863ed98e5c6e,
|
||||
type: 3}
|
||||
propertyPath: m_LocalEulerAnglesHint.z
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 4969609539872308112, guid: d5c0d58890a7e7840b47863ed98e5c6e,
|
||||
type: 3}
|
||||
propertyPath: m_Name
|
||||
value: UIPopup (Score)
|
||||
objectReference: {fileID: 0}
|
||||
m_RemovedComponents: []
|
||||
m_SourcePrefab: {fileID: 100100000, guid: d5c0d58890a7e7840b47863ed98e5c6e, type: 3}
|
|
@ -0,0 +1,7 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 02053ceef6c8f96458984eefd26124b0
|
||||
PrefabImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,131 @@
|
|||
%YAML 1.1
|
||||
%TAG !u! tag:unity3d.com,2011:
|
||||
--- !u!1001 &7864455548232232849
|
||||
PrefabInstance:
|
||||
m_ObjectHideFlags: 0
|
||||
serializedVersion: 2
|
||||
m_Modification:
|
||||
m_TransformParent: {fileID: 0}
|
||||
m_Modifications:
|
||||
- target: {fileID: 1011916610372698401, guid: d5c0d58890a7e7840b47863ed98e5c6e,
|
||||
type: 3}
|
||||
propertyPath: Prefix
|
||||
value: '+ '
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 1011916610372698401, guid: d5c0d58890a7e7840b47863ed98e5c6e,
|
||||
type: 3}
|
||||
propertyPath: Postfix
|
||||
value: " \u0441\u0435\u043A"
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 2756876663177930824, guid: d5c0d58890a7e7840b47863ed98e5c6e,
|
||||
type: 3}
|
||||
propertyPath: m_Pivot.x
|
||||
value: 0.5
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 2756876663177930824, guid: d5c0d58890a7e7840b47863ed98e5c6e,
|
||||
type: 3}
|
||||
propertyPath: m_Pivot.y
|
||||
value: 0.5
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 2756876663177930824, guid: d5c0d58890a7e7840b47863ed98e5c6e,
|
||||
type: 3}
|
||||
propertyPath: m_RootOrder
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 2756876663177930824, guid: d5c0d58890a7e7840b47863ed98e5c6e,
|
||||
type: 3}
|
||||
propertyPath: m_AnchorMax.x
|
||||
value: 0.5
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 2756876663177930824, guid: d5c0d58890a7e7840b47863ed98e5c6e,
|
||||
type: 3}
|
||||
propertyPath: m_AnchorMax.y
|
||||
value: 0.5
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 2756876663177930824, guid: d5c0d58890a7e7840b47863ed98e5c6e,
|
||||
type: 3}
|
||||
propertyPath: m_AnchorMin.x
|
||||
value: 0.5
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 2756876663177930824, guid: d5c0d58890a7e7840b47863ed98e5c6e,
|
||||
type: 3}
|
||||
propertyPath: m_AnchorMin.y
|
||||
value: 0.5
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 2756876663177930824, guid: d5c0d58890a7e7840b47863ed98e5c6e,
|
||||
type: 3}
|
||||
propertyPath: m_SizeDelta.x
|
||||
value: 209.39
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 2756876663177930824, guid: d5c0d58890a7e7840b47863ed98e5c6e,
|
||||
type: 3}
|
||||
propertyPath: m_SizeDelta.y
|
||||
value: 100
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 2756876663177930824, guid: d5c0d58890a7e7840b47863ed98e5c6e,
|
||||
type: 3}
|
||||
propertyPath: m_LocalPosition.x
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 2756876663177930824, guid: d5c0d58890a7e7840b47863ed98e5c6e,
|
||||
type: 3}
|
||||
propertyPath: m_LocalPosition.y
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 2756876663177930824, guid: d5c0d58890a7e7840b47863ed98e5c6e,
|
||||
type: 3}
|
||||
propertyPath: m_LocalPosition.z
|
||||
value: -0.1
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 2756876663177930824, guid: d5c0d58890a7e7840b47863ed98e5c6e,
|
||||
type: 3}
|
||||
propertyPath: m_LocalRotation.w
|
||||
value: 1
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 2756876663177930824, guid: d5c0d58890a7e7840b47863ed98e5c6e,
|
||||
type: 3}
|
||||
propertyPath: m_LocalRotation.x
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 2756876663177930824, guid: d5c0d58890a7e7840b47863ed98e5c6e,
|
||||
type: 3}
|
||||
propertyPath: m_LocalRotation.y
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 2756876663177930824, guid: d5c0d58890a7e7840b47863ed98e5c6e,
|
||||
type: 3}
|
||||
propertyPath: m_LocalRotation.z
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 2756876663177930824, guid: d5c0d58890a7e7840b47863ed98e5c6e,
|
||||
type: 3}
|
||||
propertyPath: m_AnchoredPosition.x
|
||||
value: -54.7
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 2756876663177930824, guid: d5c0d58890a7e7840b47863ed98e5c6e,
|
||||
type: 3}
|
||||
propertyPath: m_AnchoredPosition.y
|
||||
value: -82.3
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 2756876663177930824, guid: d5c0d58890a7e7840b47863ed98e5c6e,
|
||||
type: 3}
|
||||
propertyPath: m_LocalEulerAnglesHint.x
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 2756876663177930824, guid: d5c0d58890a7e7840b47863ed98e5c6e,
|
||||
type: 3}
|
||||
propertyPath: m_LocalEulerAnglesHint.y
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 2756876663177930824, guid: d5c0d58890a7e7840b47863ed98e5c6e,
|
||||
type: 3}
|
||||
propertyPath: m_LocalEulerAnglesHint.z
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 4969609539872308112, guid: d5c0d58890a7e7840b47863ed98e5c6e,
|
||||
type: 3}
|
||||
propertyPath: m_Name
|
||||
value: UIPopup (Time)
|
||||
objectReference: {fileID: 0}
|
||||
m_RemovedComponents: []
|
||||
m_SourcePrefab: {fileID: 100100000, guid: d5c0d58890a7e7840b47863ed98e5c6e, type: 3}
|
|
@ -0,0 +1,7 @@
|
|||
fileFormatVersion: 2
|
||||
guid: c86fad07ffc84b14f854c246948dbfac
|
||||
PrefabImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,222 @@
|
|||
%YAML 1.1
|
||||
%TAG !u! tag:unity3d.com,2011:
|
||||
--- !u!1 &200318615579008512
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
serializedVersion: 6
|
||||
m_Component:
|
||||
- component: {fileID: 7333867837070813280}
|
||||
- component: {fileID: 4997159387300029257}
|
||||
- component: {fileID: 5337496564380876370}
|
||||
- component: {fileID: 2004703880053495574}
|
||||
- component: {fileID: 7234202513872361131}
|
||||
m_Layer: 0
|
||||
m_Name: Text (TMP)
|
||||
m_TagString: Untagged
|
||||
m_Icon: {fileID: 0}
|
||||
m_NavMeshLayer: 0
|
||||
m_StaticEditorFlags: 0
|
||||
m_IsActive: 1
|
||||
--- !u!224 &7333867837070813280
|
||||
RectTransform:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 200318615579008512}
|
||||
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: 2756876663177930824}
|
||||
m_RootOrder: 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!222 &4997159387300029257
|
||||
CanvasRenderer:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 200318615579008512}
|
||||
m_CullTransparentMesh: 1
|
||||
--- !u!114 &5337496564380876370
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 200318615579008512}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: f4688fdb7df04437aeb418b961361dc5, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
m_Material: {fileID: 0}
|
||||
m_Color: {r: 1, g: 1, b: 1, 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_text: New Text
|
||||
m_isRightToLeft: 0
|
||||
m_fontAsset: {fileID: 11400000, guid: 8f586378b4e144a9851e7b34d9b748ee, type: 2}
|
||||
m_sharedMaterial: {fileID: 2180264, guid: 8f586378b4e144a9851e7b34d9b748ee, type: 2}
|
||||
m_fontSharedMaterials: []
|
||||
m_fontMaterial: {fileID: 0}
|
||||
m_fontMaterials: []
|
||||
m_fontColor32:
|
||||
serializedVersion: 2
|
||||
rgba: 4294967295
|
||||
m_fontColor: {r: 1, g: 1, b: 1, a: 1}
|
||||
m_enableVertexGradient: 0
|
||||
m_colorMode: 3
|
||||
m_fontColorGradient:
|
||||
topLeft: {r: 1, g: 1, b: 1, a: 1}
|
||||
topRight: {r: 1, g: 1, b: 1, a: 1}
|
||||
bottomLeft: {r: 1, g: 1, b: 1, a: 1}
|
||||
bottomRight: {r: 1, g: 1, b: 1, a: 1}
|
||||
m_fontColorGradientPreset: {fileID: 0}
|
||||
m_spriteAsset: {fileID: 0}
|
||||
m_tintAllSprites: 0
|
||||
m_StyleSheet: {fileID: 0}
|
||||
m_TextStyleHashCode: -1183493901
|
||||
m_overrideHtmlColors: 0
|
||||
m_faceColor:
|
||||
serializedVersion: 2
|
||||
rgba: 4294967295
|
||||
m_fontSize: 45.8
|
||||
m_fontSizeBase: 36
|
||||
m_fontWeight: 400
|
||||
m_enableAutoSizing: 1
|
||||
m_fontSizeMin: 18
|
||||
m_fontSizeMax: 72
|
||||
m_fontStyle: 1
|
||||
m_HorizontalAlignment: 2
|
||||
m_VerticalAlignment: 512
|
||||
m_textAlignment: 65535
|
||||
m_characterSpacing: 0
|
||||
m_wordSpacing: 0
|
||||
m_lineSpacing: 0
|
||||
m_lineSpacingMax: 0
|
||||
m_paragraphSpacing: 0
|
||||
m_charWidthMaxAdj: 0
|
||||
m_enableWordWrapping: 1
|
||||
m_wordWrappingRatios: 0.4
|
||||
m_overflowMode: 0
|
||||
m_linkedTextComponent: {fileID: 0}
|
||||
parentLinkedComponent: {fileID: 0}
|
||||
m_enableKerning: 1
|
||||
m_enableExtraPadding: 0
|
||||
checkPaddingRequired: 0
|
||||
m_isRichText: 1
|
||||
m_parseCtrlCharacters: 1
|
||||
m_isOrthographic: 1
|
||||
m_isCullingEnabled: 0
|
||||
m_horizontalMapping: 0
|
||||
m_verticalMapping: 0
|
||||
m_uvLineOffset: 0
|
||||
m_geometrySortingOrder: 0
|
||||
m_IsTextObjectScaleStatic: 0
|
||||
m_VertexBufferAutoSizeReduction: 0
|
||||
m_useMaxVisibleDescender: 1
|
||||
m_pageToDisplay: 1
|
||||
m_margin: {x: 0, y: 0, z: 0, w: 0}
|
||||
m_isUsingLegacyAnimationComponent: 0
|
||||
m_isVolumetricText: 0
|
||||
m_hasFontAssetChanged: 0
|
||||
m_baseMaterial: {fileID: 0}
|
||||
m_maskOffset: {x: 0, y: 0, z: 0, w: 0}
|
||||
--- !u!114 &2004703880053495574
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 200318615579008512}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: 4e62188adca544cf1b96ccf1630f15f9, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
DoNotTesselate: 0
|
||||
savedPos: {x: 0, y: 0, z: 0}
|
||||
savedUp: {x: 0, y: 0, z: 0}
|
||||
savedRectSize: {x: 0, y: 0}
|
||||
savedColor: {r: 0, g: 0, b: 0, a: 0}
|
||||
savedTextUV0: {x: 0, y: 0, z: 0, w: 0}
|
||||
savedFill: 0
|
||||
--- !u!114 &7234202513872361131
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 200318615579008512}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: 004b8ec0c25535c409b1f6115963d476, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
Dirty: 0
|
||||
--- !u!1 &4969609539872308112
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
serializedVersion: 6
|
||||
m_Component:
|
||||
- component: {fileID: 2756876663177930824}
|
||||
- component: {fileID: 1011916610372698401}
|
||||
m_Layer: 0
|
||||
m_Name: UIPopup
|
||||
m_TagString: Untagged
|
||||
m_Icon: {fileID: 0}
|
||||
m_NavMeshLayer: 0
|
||||
m_StaticEditorFlags: 0
|
||||
m_IsActive: 1
|
||||
--- !u!224 &2756876663177930824
|
||||
RectTransform:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 4969609539872308112}
|
||||
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
|
||||
m_LocalPosition: {x: 0, y: 0, z: -0.1}
|
||||
m_LocalScale: {x: 1, y: 1, z: 1}
|
||||
m_ConstrainProportionsScale: 0
|
||||
m_Children:
|
||||
- {fileID: 7333867837070813280}
|
||||
m_Father: {fileID: 0}
|
||||
m_RootOrder: 0
|
||||
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: -54.7, y: -82.3}
|
||||
m_SizeDelta: {x: 209.39, y: 100}
|
||||
m_Pivot: {x: 0.5, y: 0.5}
|
||||
--- !u!114 &1011916610372698401
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 4969609539872308112}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: c3a122f9d31deb2449916718b05c92bc, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
_text: {fileID: 5337496564380876370}
|
|
@ -0,0 +1,7 @@
|
|||
fileFormatVersion: 2
|
||||
guid: d5c0d58890a7e7840b47863ed98e5c6e
|
||||
PrefabImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -1,5 +1,226 @@
|
|||
%YAML 1.1
|
||||
%TAG !u! tag:unity3d.com,2011:
|
||||
--- !u!1 &2146129770
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
serializedVersion: 6
|
||||
m_Component:
|
||||
- component: {fileID: 2146129771}
|
||||
m_Layer: 0
|
||||
m_Name: PopupSpawnPos
|
||||
m_TagString: Untagged
|
||||
m_Icon: {fileID: 0}
|
||||
m_NavMeshLayer: 0
|
||||
m_StaticEditorFlags: 0
|
||||
m_IsActive: 1
|
||||
--- !u!224 &2146129771
|
||||
RectTransform:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 2146129770}
|
||||
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: 1860358267194598677}
|
||||
m_RootOrder: 4
|
||||
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: 244, y: 0}
|
||||
m_SizeDelta: {x: 100, y: 100}
|
||||
m_Pivot: {x: 0.5, y: 0.5}
|
||||
--- !u!1 &1564034533108096379
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
serializedVersion: 6
|
||||
m_Component:
|
||||
- component: {fileID: 4004537012386243882}
|
||||
- component: {fileID: 1162760457737044675}
|
||||
- component: {fileID: 7688394229909313368}
|
||||
- component: {fileID: 3562044667756752820}
|
||||
- component: {fileID: 5239063720710252651}
|
||||
- component: {fileID: 1023336064}
|
||||
m_Layer: 0
|
||||
m_Name: BonusText
|
||||
m_TagString: Untagged
|
||||
m_Icon: {fileID: 0}
|
||||
m_NavMeshLayer: 0
|
||||
m_StaticEditorFlags: 0
|
||||
m_IsActive: 1
|
||||
--- !u!224 &4004537012386243882
|
||||
RectTransform:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 1564034533108096379}
|
||||
m_LocalRotation: {x: -0, y: -0, z: -0, w: 1}
|
||||
m_LocalPosition: {x: 0, y: 0, z: 0.036112145}
|
||||
m_LocalScale: {x: 1, y: 1, z: 1}
|
||||
m_ConstrainProportionsScale: 0
|
||||
m_Children: []
|
||||
m_Father: {fileID: 1860358267194598677}
|
||||
m_RootOrder: 3
|
||||
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: -419}
|
||||
m_SizeDelta: {x: 395.774, y: 129.583}
|
||||
m_Pivot: {x: 0.5, y: 0.5}
|
||||
--- !u!222 &1162760457737044675
|
||||
CanvasRenderer:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 1564034533108096379}
|
||||
m_CullTransparentMesh: 1
|
||||
--- !u!114 &7688394229909313368
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 1564034533108096379}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: f4688fdb7df04437aeb418b961361dc5, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
m_Material: {fileID: 0}
|
||||
m_Color: {r: 1, g: 1, b: 1, 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_text: 10
|
||||
m_isRightToLeft: 0
|
||||
m_fontAsset: {fileID: 11400000, guid: 8f586378b4e144a9851e7b34d9b748ee, type: 2}
|
||||
m_sharedMaterial: {fileID: 2180264, guid: 8f586378b4e144a9851e7b34d9b748ee, type: 2}
|
||||
m_fontSharedMaterials: []
|
||||
m_fontMaterial: {fileID: 0}
|
||||
m_fontMaterials: []
|
||||
m_fontColor32:
|
||||
serializedVersion: 2
|
||||
rgba: 4294967295
|
||||
m_fontColor: {r: 1, g: 1, b: 1, a: 1}
|
||||
m_enableVertexGradient: 0
|
||||
m_colorMode: 3
|
||||
m_fontColorGradient:
|
||||
topLeft: {r: 1, g: 1, b: 1, a: 1}
|
||||
topRight: {r: 1, g: 1, b: 1, a: 1}
|
||||
bottomLeft: {r: 1, g: 1, b: 1, a: 1}
|
||||
bottomRight: {r: 1, g: 1, b: 1, a: 1}
|
||||
m_fontColorGradientPreset: {fileID: 0}
|
||||
m_spriteAsset: {fileID: 0}
|
||||
m_tintAllSprites: 0
|
||||
m_StyleSheet: {fileID: 0}
|
||||
m_TextStyleHashCode: -1183493901
|
||||
m_overrideHtmlColors: 0
|
||||
m_faceColor:
|
||||
serializedVersion: 2
|
||||
rgba: 4294967295
|
||||
m_fontSize: 83.91
|
||||
m_fontSizeBase: 36
|
||||
m_fontWeight: 400
|
||||
m_enableAutoSizing: 1
|
||||
m_fontSizeMin: 18
|
||||
m_fontSizeMax: 83.91
|
||||
m_fontStyle: 1
|
||||
m_HorizontalAlignment: 2
|
||||
m_VerticalAlignment: 512
|
||||
m_textAlignment: 65535
|
||||
m_characterSpacing: 0
|
||||
m_wordSpacing: 0
|
||||
m_lineSpacing: 0
|
||||
m_lineSpacingMax: 0
|
||||
m_paragraphSpacing: 0
|
||||
m_charWidthMaxAdj: 0
|
||||
m_enableWordWrapping: 1
|
||||
m_wordWrappingRatios: 0.4
|
||||
m_overflowMode: 0
|
||||
m_linkedTextComponent: {fileID: 0}
|
||||
parentLinkedComponent: {fileID: 0}
|
||||
m_enableKerning: 1
|
||||
m_enableExtraPadding: 0
|
||||
checkPaddingRequired: 0
|
||||
m_isRichText: 1
|
||||
m_parseCtrlCharacters: 1
|
||||
m_isOrthographic: 1
|
||||
m_isCullingEnabled: 0
|
||||
m_horizontalMapping: 0
|
||||
m_verticalMapping: 0
|
||||
m_uvLineOffset: 0
|
||||
m_geometrySortingOrder: 0
|
||||
m_IsTextObjectScaleStatic: 0
|
||||
m_VertexBufferAutoSizeReduction: 0
|
||||
m_useMaxVisibleDescender: 1
|
||||
m_pageToDisplay: 1
|
||||
m_margin: {x: 0, y: 0, z: 0, w: 0}
|
||||
m_isUsingLegacyAnimationComponent: 0
|
||||
m_isVolumetricText: 0
|
||||
m_hasFontAssetChanged: 0
|
||||
m_baseMaterial: {fileID: 0}
|
||||
m_maskOffset: {x: 0, y: 0, z: 0, w: 0}
|
||||
--- !u!114 &3562044667756752820
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 1564034533108096379}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: 4e62188adca544cf1b96ccf1630f15f9, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
DoNotTesselate: 0
|
||||
savedPos: {x: 0, y: 0, z: 0}
|
||||
savedUp: {x: 0, y: 0, z: 0}
|
||||
savedRectSize: {x: 0, y: 0}
|
||||
savedColor: {r: 0, g: 0, b: 0, a: 0}
|
||||
savedTextUV0: {x: 0, y: 0, z: 0, w: 0}
|
||||
savedFill: 0
|
||||
--- !u!114 &5239063720710252651
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 1564034533108096379}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: 004b8ec0c25535c409b1f6115963d476, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
Dirty: 0
|
||||
--- !u!114 &1023336064
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 1564034533108096379}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: 232c3975195049046b093176c334caab, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
_defaultValue:
|
||||
_prefix: '(x '
|
||||
_postfix: )
|
||||
--- !u!1 &1607195224622154761
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
|
@ -90,12 +311,12 @@ MonoBehaviour:
|
|||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
DoNotTesselate: 0
|
||||
savedPos: {x: 0, y: 0, z: 0}
|
||||
savedUp: {x: 0, y: 0, z: 0}
|
||||
savedRectSize: {x: 0, y: 0}
|
||||
savedColor: {r: 0, g: 0, b: 0, a: 0}
|
||||
savedPos: {x: 0.000051498588, y: 18.492935, z: 0.0000001550396}
|
||||
savedUp: {x: 3.1465978e-13, y: 1, z: 2.201165e-11}
|
||||
savedRectSize: {x: 663.338, y: 63.013}
|
||||
savedColor: {r: 0.71158946, g: 1, b: 0, a: 1}
|
||||
savedTextUV0: {x: 0, y: 0, z: 0, w: 0}
|
||||
savedFill: 0
|
||||
savedFill: 1
|
||||
--- !u!1 &2456473982007753813
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
|
@ -134,7 +355,7 @@ RectTransform:
|
|||
m_AnchorMin: {x: 0.5, y: 0.5}
|
||||
m_AnchorMax: {x: 0.5, y: 0.5}
|
||||
m_AnchoredPosition: {x: 0, y: 117}
|
||||
m_SizeDelta: {x: 367.076, y: 91.769}
|
||||
m_SizeDelta: {x: 632.123, y: 91.769}
|
||||
m_Pivot: {x: 0.5, y: 0.5}
|
||||
--- !u!222 &6310987546111005199
|
||||
CanvasRenderer:
|
||||
|
@ -356,12 +577,12 @@ MonoBehaviour:
|
|||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
DoNotTesselate: 0
|
||||
savedPos: {x: 0, y: 0, z: 0}
|
||||
savedUp: {x: 0, y: 0, z: 0}
|
||||
savedRectSize: {x: 0, y: 0}
|
||||
savedColor: {r: 0, g: 0, b: 0, a: 0}
|
||||
savedPos: {x: 0.000051498537, y: -190.99998, z: -0.0003197979}
|
||||
savedUp: {x: 3.1465978e-13, y: 1, z: 2.201165e-11}
|
||||
savedRectSize: {x: 271.883, y: 271.883}
|
||||
savedColor: {r: 1, g: 1, b: 1, a: 1}
|
||||
savedTextUV0: {x: 0, y: 0, z: 0, w: 0}
|
||||
savedFill: 0
|
||||
savedFill: 1
|
||||
--- !u!1 &3589229234049084828
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
|
@ -394,6 +615,9 @@ RectTransform:
|
|||
- {fileID: 9202471760983386593}
|
||||
- {fileID: 9202471760714427097}
|
||||
- {fileID: 9202471760488186011}
|
||||
- {fileID: 4004537012386243882}
|
||||
- {fileID: 2146129771}
|
||||
- {fileID: 326048764444127262}
|
||||
m_Father: {fileID: 9202471761387014830}
|
||||
m_RootOrder: 0
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||
|
@ -410,7 +634,7 @@ CanvasGroup:
|
|||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 3589229234049084828}
|
||||
m_Enabled: 1
|
||||
m_Alpha: 1
|
||||
m_Alpha: 0
|
||||
m_Interactable: 1
|
||||
m_BlocksRaycasts: 1
|
||||
m_IgnoreParentGroups: 0
|
||||
|
@ -505,12 +729,215 @@ MonoBehaviour:
|
|||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
DoNotTesselate: 0
|
||||
savedPos: {x: 0.000051498588, y: 18.492935, z: 0.0000001550396}
|
||||
savedUp: {x: 3.1465978e-13, y: 1, z: 2.201165e-11}
|
||||
savedRectSize: {x: 663.338, y: 63.013}
|
||||
savedColor: {r: 1, g: 1, b: 1, a: 1}
|
||||
savedTextUV0: {x: 0, y: 0, z: 0, w: 0}
|
||||
savedFill: 1
|
||||
--- !u!1 &5910555295511923874
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
serializedVersion: 6
|
||||
m_Component:
|
||||
- component: {fileID: 326048764444127262}
|
||||
- component: {fileID: 6255781262072940109}
|
||||
- component: {fileID: 8650261210416225506}
|
||||
- component: {fileID: 7869725402744582542}
|
||||
- component: {fileID: 8801838980126204425}
|
||||
- component: {fileID: 4266446464926029223}
|
||||
- component: {fileID: 6170361849501489470}
|
||||
m_Layer: 0
|
||||
m_Name: Text (TMP)
|
||||
m_TagString: Untagged
|
||||
m_Icon: {fileID: 0}
|
||||
m_NavMeshLayer: 0
|
||||
m_StaticEditorFlags: 0
|
||||
m_IsActive: 1
|
||||
--- !u!224 &326048764444127262
|
||||
RectTransform:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 5910555295511923874}
|
||||
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: 1860358267194598677}
|
||||
m_RootOrder: 5
|
||||
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: 305}
|
||||
m_SizeDelta: {x: 200, y: 50}
|
||||
m_Pivot: {x: 0.5, y: 0.5}
|
||||
--- !u!222 &6255781262072940109
|
||||
CanvasRenderer:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 5910555295511923874}
|
||||
m_CullTransparentMesh: 1
|
||||
--- !u!114 &8650261210416225506
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 5910555295511923874}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: f4688fdb7df04437aeb418b961361dc5, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
m_Material: {fileID: 0}
|
||||
m_Color: {r: 1, g: 1, b: 1, 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_text: "\u0412\u0440\u0435\u043C\u044F:"
|
||||
m_isRightToLeft: 0
|
||||
m_fontAsset: {fileID: 11400000, guid: 8f586378b4e144a9851e7b34d9b748ee, type: 2}
|
||||
m_sharedMaterial: {fileID: 2180264, guid: 8f586378b4e144a9851e7b34d9b748ee, type: 2}
|
||||
m_fontSharedMaterials: []
|
||||
m_fontMaterial: {fileID: 0}
|
||||
m_fontMaterials: []
|
||||
m_fontColor32:
|
||||
serializedVersion: 2
|
||||
rgba: 4294967295
|
||||
m_fontColor: {r: 1, g: 1, b: 1, a: 1}
|
||||
m_enableVertexGradient: 0
|
||||
m_colorMode: 3
|
||||
m_fontColorGradient:
|
||||
topLeft: {r: 1, g: 1, b: 1, a: 1}
|
||||
topRight: {r: 1, g: 1, b: 1, a: 1}
|
||||
bottomLeft: {r: 1, g: 1, b: 1, a: 1}
|
||||
bottomRight: {r: 1, g: 1, b: 1, a: 1}
|
||||
m_fontColorGradientPreset: {fileID: 0}
|
||||
m_spriteAsset: {fileID: 0}
|
||||
m_tintAllSprites: 0
|
||||
m_StyleSheet: {fileID: 0}
|
||||
m_TextStyleHashCode: -1183493901
|
||||
m_overrideHtmlColors: 0
|
||||
m_faceColor:
|
||||
serializedVersion: 2
|
||||
rgba: 4294967295
|
||||
m_fontSize: 36
|
||||
m_fontSizeBase: 36
|
||||
m_fontWeight: 400
|
||||
m_enableAutoSizing: 0
|
||||
m_fontSizeMin: 18
|
||||
m_fontSizeMax: 72
|
||||
m_fontStyle: 0
|
||||
m_HorizontalAlignment: 2
|
||||
m_VerticalAlignment: 512
|
||||
m_textAlignment: 65535
|
||||
m_characterSpacing: 0
|
||||
m_wordSpacing: 0
|
||||
m_lineSpacing: 0
|
||||
m_lineSpacingMax: 0
|
||||
m_paragraphSpacing: 0
|
||||
m_charWidthMaxAdj: 0
|
||||
m_enableWordWrapping: 1
|
||||
m_wordWrappingRatios: 0.4
|
||||
m_overflowMode: 0
|
||||
m_linkedTextComponent: {fileID: 0}
|
||||
parentLinkedComponent: {fileID: 0}
|
||||
m_enableKerning: 1
|
||||
m_enableExtraPadding: 0
|
||||
checkPaddingRequired: 0
|
||||
m_isRichText: 1
|
||||
m_parseCtrlCharacters: 1
|
||||
m_isOrthographic: 1
|
||||
m_isCullingEnabled: 0
|
||||
m_horizontalMapping: 0
|
||||
m_verticalMapping: 0
|
||||
m_uvLineOffset: 0
|
||||
m_geometrySortingOrder: 0
|
||||
m_IsTextObjectScaleStatic: 0
|
||||
m_VertexBufferAutoSizeReduction: 0
|
||||
m_useMaxVisibleDescender: 1
|
||||
m_pageToDisplay: 1
|
||||
m_margin: {x: 0, y: 0, z: 0, w: 0}
|
||||
m_isUsingLegacyAnimationComponent: 0
|
||||
m_isVolumetricText: 0
|
||||
m_hasFontAssetChanged: 0
|
||||
m_baseMaterial: {fileID: 0}
|
||||
m_maskOffset: {x: 0, y: 0, z: 0, w: 0}
|
||||
--- !u!114 &7869725402744582542
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 5910555295511923874}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: 4e62188adca544cf1b96ccf1630f15f9, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
DoNotTesselate: 0
|
||||
savedPos: {x: 0, y: 0, z: 0}
|
||||
savedUp: {x: 0, y: 0, z: 0}
|
||||
savedRectSize: {x: 0, y: 0}
|
||||
savedColor: {r: 0, g: 0, b: 0, a: 0}
|
||||
savedTextUV0: {x: 0, y: 0, z: 0, w: 0}
|
||||
savedFill: 0
|
||||
--- !u!114 &8801838980126204425
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 5910555295511923874}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: 004b8ec0c25535c409b1f6115963d476, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
Dirty: 0
|
||||
--- !u!114 &4266446464926029223
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 5910555295511923874}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: 4e62188adca544cf1b96ccf1630f15f9, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
DoNotTesselate: 0
|
||||
savedPos: {x: 0, y: 0, z: 0}
|
||||
savedUp: {x: 0, y: 0, z: 0}
|
||||
savedRectSize: {x: 0, y: 0}
|
||||
savedColor: {r: 0, g: 0, b: 0, a: 0}
|
||||
savedTextUV0: {x: 0, y: 0, z: 0, w: 0}
|
||||
savedFill: 0
|
||||
--- !u!114 &6170361849501489470
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 5910555295511923874}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: 004b8ec0c25535c409b1f6115963d476, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
Dirty: 0
|
||||
--- !u!1 &8059874730754158137
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
|
@ -520,6 +947,7 @@ GameObject:
|
|||
serializedVersion: 6
|
||||
m_Component:
|
||||
- component: {fileID: 3341415872416724787}
|
||||
- component: {fileID: 1955516150}
|
||||
m_Layer: 0
|
||||
m_Name: StartTutorial
|
||||
m_TagString: Untagged
|
||||
|
@ -550,6 +978,18 @@ RectTransform:
|
|||
m_AnchoredPosition: {x: 0, y: 0}
|
||||
m_SizeDelta: {x: 100, y: 100}
|
||||
m_Pivot: {x: 0.5, y: 0.5}
|
||||
--- !u!225 &1955516150
|
||||
CanvasGroup:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 8059874730754158137}
|
||||
m_Enabled: 1
|
||||
m_Alpha: 1
|
||||
m_Interactable: 1
|
||||
m_BlocksRaycasts: 1
|
||||
m_IgnoreParentGroups: 0
|
||||
--- !u!1 &9202471760488186004
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
|
@ -563,9 +1003,9 @@ GameObject:
|
|||
- component: {fileID: 9202471760488186015}
|
||||
- component: {fileID: 9202471760488186008}
|
||||
- component: {fileID: 9202471760488186009}
|
||||
- component: {fileID: 9202471760488186010}
|
||||
- component: {fileID: 1530766295}
|
||||
m_Layer: 0
|
||||
m_Name: Text (TMP) (1)
|
||||
m_Name: ScoreText
|
||||
m_TagString: Untagged
|
||||
m_Icon: {fileID: 0}
|
||||
m_NavMeshLayer: 0
|
||||
|
@ -720,7 +1160,7 @@ MonoBehaviour:
|
|||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
Dirty: 0
|
||||
--- !u!114 &9202471760488186010
|
||||
--- !u!114 &1530766295
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
|
@ -729,10 +1169,12 @@ MonoBehaviour:
|
|||
m_GameObject: {fileID: 9202471760488186004}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: 4a14752bce1e85a47ad22bd4e89cbe2f, type: 3}
|
||||
m_Script: {fileID: 11500000, guid: 5fac8287982008c4aad577d37f0e885c, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
_postfix: " \u043E\u0447."
|
||||
_defaultValue: "0 \u043E\u0447."
|
||||
_prefix:
|
||||
_postfix: " \u043E\u0447\u043A\u043E\u0432"
|
||||
--- !u!1 &9202471760714427098
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
|
@ -748,7 +1190,7 @@ GameObject:
|
|||
- component: {fileID: 9202471760714427103}
|
||||
- component: {fileID: 9202471760714427107}
|
||||
m_Layer: 0
|
||||
m_Name: Text (TMP)
|
||||
m_Name: TimerText
|
||||
m_TagString: Untagged
|
||||
m_Icon: {fileID: 0}
|
||||
m_NavMeshLayer: 0
|
||||
|
@ -915,6 +1357,8 @@ MonoBehaviour:
|
|||
m_Script: {fileID: 11500000, guid: b64a96362efa9ba44802d57e2e074f27, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
_defaultValue:
|
||||
_prefix:
|
||||
_postfix:
|
||||
--- !u!1 &9202471760983386594
|
||||
GameObject:
|
||||
|
@ -1006,7 +1450,7 @@ MonoBehaviour:
|
|||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
DoNotTesselate: 0
|
||||
savedPos: {x: 0.00828664, y: -64.99654, z: -0.32008088}
|
||||
savedPos: {x: 0.000051498555, y: -64.99994, z: -0.15967491}
|
||||
savedUp: {x: 1.12754275e-13, y: 1, z: 3.42218e-11}
|
||||
savedRectSize: {x: 1932.7, y: 1329.5757}
|
||||
savedColor: {r: 1, g: 1, b: 1, a: 1}
|
||||
|
@ -1132,7 +1576,7 @@ MonoBehaviour:
|
|||
interactable: 1
|
||||
blocksRaycasts: 1
|
||||
forceUseBoxCollider: 0
|
||||
angle: 1
|
||||
angle: 180
|
||||
preserveAspect: 1
|
||||
vertAngle: 90
|
||||
ringFill: 0.5
|
||||
|
|
|
@ -8795,7 +8795,7 @@ PrefabInstance:
|
|||
type: 3}
|
||||
propertyPath: OnSubmit.m_PersistentCalls.m_Calls.Array.data[0].m_Target
|
||||
value:
|
||||
objectReference: {fileID: 0}
|
||||
objectReference: {fileID: 1586040768636592466}
|
||||
- target: {fileID: 5385305708475918454, guid: 8a70b6ef2260a1848b78f80fbf4e786d,
|
||||
type: 3}
|
||||
propertyPath: OnSubmit.m_PersistentCalls.m_Calls.Array.data[1].m_Target
|
||||
|
@ -9158,6 +9158,18 @@ PrefabInstance:
|
|||
objectReference: {fileID: 1381913585}
|
||||
m_RemovedComponents: []
|
||||
m_SourcePrefab: {fileID: 100100000, guid: 59bb54bf798778349a37c58fbf18880c, type: 3}
|
||||
--- !u!114 &1586040768636592466 stripped
|
||||
MonoBehaviour:
|
||||
m_CorrespondingSourceObject: {fileID: 1586040770268846765, guid: 59bb54bf798778349a37c58fbf18880c,
|
||||
type: 3}
|
||||
m_PrefabInstance: {fileID: 1586040768636592465}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 0}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: ea6843af62cab9c4b8dabeba902a4262, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
--- !u!114 &3804151737227041911 stripped
|
||||
MonoBehaviour:
|
||||
m_CorrespondingSourceObject: {fileID: 5385305708475918454, guid: 8a70b6ef2260a1848b78f80fbf4e786d,
|
||||
|
|
|
@ -1,8 +1,92 @@
|
|||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Events;
|
||||
|
||||
public class ScoreController : MonoBehaviour
|
||||
public class ScoreController : MonoBehaviour, ITextChangable
|
||||
{
|
||||
public event Action<float> OnScoreChange;
|
||||
|
||||
|
||||
private LeaderboardController _leaderboardController;
|
||||
private float _currentScore = 0;
|
||||
|
||||
private bool _decreaseBonus;
|
||||
private Coroutine _decreaseReloadCoroutine;
|
||||
|
||||
private UIPopupController _UIPopupController;
|
||||
|
||||
public UnityEvent<object> OnTextChange => _OnTextChange;
|
||||
private UnityEvent<object> _OnTextChange = new UnityEvent<object>();
|
||||
|
||||
private BonusController _bonusController;
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
_bonusController = FindObjectOfType<BonusController>();
|
||||
_UIPopupController = FindObjectOfType<UIPopupController>();
|
||||
_leaderboardController = FindObjectOfType<LeaderboardController>();
|
||||
}
|
||||
|
||||
[ContextMenu("Debug add score")]
|
||||
private void DebugAddScore()
|
||||
{
|
||||
AddScore(100, true);
|
||||
}
|
||||
[ContextMenu("Debug add score in time")]
|
||||
private void DebugAddScoreInTime()
|
||||
{
|
||||
AddScoreInTime(100, 2, false);
|
||||
}
|
||||
|
||||
|
||||
public void AddScoreInTime(float ammount, float time, bool useBonus)
|
||||
{
|
||||
StartCoroutine(ScoreInTime_Coroutine(ammount,time,useBonus));
|
||||
}
|
||||
|
||||
private IEnumerator ScoreInTime_Coroutine(float ammount, float time, bool useBonus)
|
||||
{
|
||||
var timeOffset = time / ammount;
|
||||
|
||||
for (int i = 0; i < ammount; i++)
|
||||
{
|
||||
AddScore(1, useBonus, false);
|
||||
yield return new WaitForSeconds(timeOffset);
|
||||
}
|
||||
}
|
||||
|
||||
public void AddScore(float ammount, bool useBonus = false, bool usePopup = true)
|
||||
{
|
||||
float resScore = ammount;
|
||||
|
||||
if (useBonus)
|
||||
{
|
||||
_bonusController.DecreaseReload();
|
||||
resScore *= _bonusController.BonusValue;
|
||||
}
|
||||
|
||||
_currentScore += resScore;
|
||||
PlayerSetup.Instance.SetPlayerScore(_currentScore);
|
||||
OnScoreChange?.Invoke(_currentScore);
|
||||
|
||||
if (usePopup)
|
||||
{
|
||||
_UIPopupController.SpawnPopup
|
||||
(
|
||||
resScore.ToString(),
|
||||
UIMagnetType.Score,
|
||||
() => {
|
||||
_OnTextChange?.Invoke(_currentScore);
|
||||
_bonusController.UseBonus();
|
||||
}
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
_OnTextChange?.Invoke(_currentScore);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -5,9 +5,18 @@ public class BaseItem : MonoBehaviour, IInteractable
|
|||
[SerializeField]
|
||||
private float _scoreAdd = 0;
|
||||
|
||||
protected ScoreController _scoreController;
|
||||
|
||||
protected virtual void Awake()
|
||||
{
|
||||
_scoreController = FindObjectOfType<ScoreController>();
|
||||
}
|
||||
|
||||
public virtual void Interact()
|
||||
{
|
||||
PlayerSetup.Instance.AddScore(_scoreAdd);
|
||||
if (_scoreAdd > 0)
|
||||
_scoreController.AddScore(_scoreAdd, true);
|
||||
|
||||
Destroy(gameObject);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,8 +9,9 @@ public class EnergyItem : BaseItem
|
|||
|
||||
private EnergyController _energyController;
|
||||
|
||||
private void Awake()
|
||||
protected override void Awake()
|
||||
{
|
||||
base.Awake();
|
||||
_energyController = FindObjectOfType<EnergyController>();
|
||||
}
|
||||
|
||||
|
|
|
@ -20,7 +20,6 @@ public class GameManager : MonoBehaviour
|
|||
private EnergyController _energyController;
|
||||
private vTimerCounter _timerCounter;
|
||||
private EndGameModule _endGameModule;
|
||||
private LeaderboardController _leaderboardController;
|
||||
|
||||
private bool _successEnd;
|
||||
|
||||
|
@ -61,7 +60,6 @@ public class GameManager : MonoBehaviour
|
|||
|
||||
private void InitReferences()
|
||||
{
|
||||
_leaderboardController = FindObjectOfType<LeaderboardController>();
|
||||
_endGameModule = FindObjectOfType<EndGameModule>();
|
||||
_timerCounter = FindObjectOfType<vTimerCounter>();
|
||||
}
|
||||
|
@ -79,14 +77,13 @@ public class GameManager : MonoBehaviour
|
|||
{
|
||||
case GameState.Started:
|
||||
{
|
||||
var player = PlayerSetup.Instance.CreateNewPlayer();
|
||||
_leaderboardController.InitPlayerInfo(player);
|
||||
PlayerSetup.Instance.CreateNewPlayer();
|
||||
|
||||
_UITextShow?.ShowTimer
|
||||
(
|
||||
3,
|
||||
"ÑÒÀÐÒ!",
|
||||
0,
|
||||
1,
|
||||
null,
|
||||
() => { OnGameStarted?.Invoke(); }
|
||||
);
|
||||
|
|
|
@ -3,6 +3,7 @@ using System.Collections;
|
|||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Events;
|
||||
using UnityEngine.UI;
|
||||
|
||||
public class LeaderboardController : MonoBehaviour
|
||||
|
@ -19,10 +20,10 @@ public class LeaderboardController : MonoBehaviour
|
|||
|
||||
private void Start()
|
||||
{
|
||||
UpdateLeaderboard(0);
|
||||
UpdateLeaderboard();
|
||||
}
|
||||
|
||||
private void UpdateLeaderboard(float newScore)
|
||||
private void UpdateLeaderboard()
|
||||
{
|
||||
_entries.ForEach(x => Destroy(x.gameObject));
|
||||
_entries.Clear();
|
||||
|
@ -38,15 +39,10 @@ public class LeaderboardController : MonoBehaviour
|
|||
}
|
||||
}
|
||||
|
||||
[ContextMenu("Debug submit")]
|
||||
public void SubmitNewEntry()
|
||||
{
|
||||
PlayerSetup.Instance.SetPlayerName(_nameInputField.text);
|
||||
PlayerSetup.Instance.SavePlayer();
|
||||
UpdateLeaderboard(0);
|
||||
}
|
||||
|
||||
public void InitPlayerInfo(Player player)
|
||||
{
|
||||
player.OnScoreChange += UpdateLeaderboard;
|
||||
UpdateLeaderboard();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -14,7 +14,7 @@ public class LeaderboardEntry : MonoBehaviour
|
|||
[SerializeField]
|
||||
private List<GameObject> _medals = new List<GameObject>();
|
||||
|
||||
public void Init(Player player, int index)
|
||||
public void Init(Player player, int index, bool selected = false)
|
||||
{
|
||||
if (index < 3)
|
||||
{
|
||||
|
@ -24,5 +24,10 @@ public class LeaderboardEntry : MonoBehaviour
|
|||
_numText.SetText($"{index + 1}");
|
||||
_nameText.SetText(player.Name);
|
||||
_scoreText.SetText($"{player.Score}");
|
||||
|
||||
if (selected)
|
||||
{
|
||||
_nameText.SetText("GREEEEN");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,20 +7,12 @@ using UnityEngine;
|
|||
public class Player
|
||||
{
|
||||
public string Name;
|
||||
public float Score
|
||||
{
|
||||
get => _score;
|
||||
set
|
||||
{
|
||||
_score = value;
|
||||
OnScoreChange?.Invoke(_score);
|
||||
}
|
||||
}
|
||||
public float Score;
|
||||
|
||||
private float _score;
|
||||
|
||||
public List<MonumentInfo> UnlockedMonumets = new List<MonumentInfo>();
|
||||
public event Action<float> OnScoreChange;
|
||||
|
||||
}
|
||||
|
||||
[CreateAssetMenu(fileName = "PlayerInfo")]
|
||||
|
|
|
@ -10,6 +10,7 @@ public class PlayerSetup : MonoBehaviour
|
|||
[SerializeField]
|
||||
private Player _currentPlayer;
|
||||
|
||||
public Player CurrentPlayer => _currentPlayer;
|
||||
public PlayerInfo PlayerInfo => _playerInfo;
|
||||
|
||||
private void Awake()
|
||||
|
@ -29,28 +30,23 @@ public class PlayerSetup : MonoBehaviour
|
|||
public Player CreateNewPlayer()
|
||||
{
|
||||
_currentPlayer = new Player();
|
||||
SavePlayer();
|
||||
return _currentPlayer;
|
||||
}
|
||||
|
||||
public void SetPlayerScore(float value)
|
||||
{
|
||||
_currentPlayer.Score = value;
|
||||
}
|
||||
|
||||
public void AddScore(float ammount)
|
||||
{
|
||||
_currentPlayer.Score += ammount;
|
||||
}
|
||||
|
||||
public void SetPlayerName(string name)
|
||||
{
|
||||
_currentPlayer.Name = name;
|
||||
}
|
||||
|
||||
public void SetPlayerScore(float score)
|
||||
{
|
||||
_currentPlayer.Score = score;
|
||||
}
|
||||
|
||||
public void UnlockMonument(MonumentInfo info)
|
||||
{
|
||||
_currentPlayer.UnlockedMonumets.Add(info);
|
||||
AddScore(info.Score);
|
||||
}
|
||||
|
||||
public bool TryFindMonument(MonumentInfo info)
|
||||
|
|
|
@ -9,8 +9,9 @@ public class TimeBonus : BaseItem
|
|||
|
||||
private vTimerCounter _timerCounter;
|
||||
|
||||
private void Awake()
|
||||
protected override void Awake()
|
||||
{
|
||||
base.Awake();
|
||||
_timerCounter = FindObjectOfType<vTimerCounter>();
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,8 @@
|
|||
public class UIScoreText : UITextDisplayBase
|
||||
{
|
||||
protected override void Awake()
|
||||
{
|
||||
base.Awake();
|
||||
_textChanger = FindObjectOfType<ScoreController>();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 5fac8287982008c4aad577d37f0e885c
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,8 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 07bfafa14538ac741b2cb55975986490
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1 @@
|
|||
{"Keys":["com.unity.services.core.cloud-environment","com.unity.services.core.version"],"Values":[{"m_Value":"production","m_IsReadOnly":false},{"m_Value":"1.4.3","m_IsReadOnly":true}]}
|
|
@ -0,0 +1,7 @@
|
|||
fileFormatVersion: 2
|
||||
guid: ed0a60712ef404f4b9e202287acbbd51
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,8 @@
|
|||
public class UIBonusText : UITextDisplayBase
|
||||
{
|
||||
protected override void Awake()
|
||||
{
|
||||
base.Awake();
|
||||
_textChanger = FindObjectOfType<BonusController>();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 232c3975195049046b093176c334caab
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,8 @@
|
|||
public class UILBPositionText : UITextDisplayBase
|
||||
{
|
||||
protected override void Awake()
|
||||
{
|
||||
base.Awake();
|
||||
_textChanger = FindObjectOfType<DynamicLeaderboard>();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 0e3d7a2fa3fb554409a4dba369eeb968
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,17 @@
|
|||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
public class UIPopup : MonoBehaviour
|
||||
{
|
||||
[SerializeField]
|
||||
private TMPro.TextMeshProUGUI _text;
|
||||
|
||||
public string Prefix;
|
||||
public string Postfix;
|
||||
|
||||
public void Init(string message)
|
||||
{
|
||||
_text.SetText(Prefix + message + Postfix);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: c3a122f9d31deb2449916718b05c92bc
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,27 @@
|
|||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
public class UIPopupController : MonoBehaviour
|
||||
{
|
||||
[SerializeField]
|
||||
private RectTransform _root;
|
||||
[SerializeField]
|
||||
private RectTransform _spawnPoint;
|
||||
|
||||
[SerializeField]
|
||||
private List<UIPopupPair> _UIPairs = new List<UIPopupPair>();
|
||||
|
||||
public void SpawnPopup(string message, UIMagnetType type, Action onComplete)
|
||||
{
|
||||
var selectedPair = _UIPairs.Find(x => x.UIMagnetType == type);
|
||||
|
||||
var scorePoint = Instantiate(selectedPair.Popup, _root);
|
||||
scorePoint.Init(message);
|
||||
|
||||
scorePoint.GetComponent<RectTransform>().anchoredPosition = _spawnPoint.anchoredPosition;
|
||||
RectTransform target = selectedPair.MovePositon;
|
||||
scorePoint.GetComponent<RectTransform>().LeanMoveLocal(target.anchoredPosition, 1).setOnComplete(onComplete).setEaseInExpo().setDestroyOnComplete(true);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: f96f1a3355094dd418d467074ae4856a
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,18 @@
|
|||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
[System.Serializable]
|
||||
public class UIPopupPair
|
||||
{
|
||||
public UIPopup Popup;
|
||||
public RectTransform MovePositon;
|
||||
public UIMagnetType UIMagnetType;
|
||||
}
|
||||
|
||||
[System.Serializable]
|
||||
public enum UIMagnetType
|
||||
{
|
||||
Score,
|
||||
Time
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 1e607e6927a512e45929a4405df20a1b
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -8,11 +8,16 @@ public class UITextDisplayBase : MonoBehaviour
|
|||
protected TMPro.TextMeshProUGUI _text;
|
||||
protected ITextChangable _textChanger;
|
||||
[SerializeField]
|
||||
protected string _defaultValue = string.Empty;
|
||||
[SerializeField]
|
||||
protected string _prefix;
|
||||
[SerializeField]
|
||||
protected string _postfix;
|
||||
|
||||
protected virtual void Awake()
|
||||
{
|
||||
_text = GetComponent<TMPro.TextMeshProUGUI>();
|
||||
_text.SetText(_defaultValue);
|
||||
}
|
||||
|
||||
protected virtual void OnEnable()
|
||||
|
@ -27,6 +32,6 @@ public class UITextDisplayBase : MonoBehaviour
|
|||
|
||||
private void UpdateText(object obj)
|
||||
{
|
||||
_text.SetText(obj.ToString() + _postfix);
|
||||
_text.SetText(_prefix + obj.ToString() + _postfix);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -15,6 +15,7 @@ public class VisorUIModule : MonoBehaviour
|
|||
[SerializeField]
|
||||
private Image _progressBarImage;
|
||||
|
||||
|
||||
public InputActionReference LeftTrigger;
|
||||
public InputActionReference RightTrigger;
|
||||
|
||||
|
|
|
@ -152,6 +152,10 @@ PlayerSettings:
|
|||
- {fileID: 0}
|
||||
- {fileID: 0}
|
||||
- {fileID: 0}
|
||||
- {fileID: 0}
|
||||
- {fileID: 0}
|
||||
- {fileID: -6517218471499782410, guid: 1a4c68ca72a83449f938d669337cb305, type: 2}
|
||||
- {fileID: 648089955447955448, guid: ac7df53da7627c941aa8b5303dd3d14f, type: 2}
|
||||
metroInputSource: 0
|
||||
wsaTransparentSwapchain: 0
|
||||
m_HolographicPauseOnTrackingLoss: 1
|
||||
|
|