6 Commits
239 changed files with 607245 additions and 14910 deletions

No files matched your search

@@ -15,7 +15,7 @@ MonoBehaviour:
m_DefaultGroup: d447fc60305c17a17bf20948ab295a45
m_currentHash:
serializedVersion: 2
Hash: 6940a0d24ee0b7d842fd97d11e078c94
Hash: 1ec1ee985689145b755c859b69691cb0
m_OptimizeCatalogSize: 0
m_BuildRemoteCatalog: 0
m_CatalogRequestsTimeout: 0
@@ -32,11 +32,6 @@ MonoBehaviour:
m_ReadOnly: 0
m_SerializedLabels: []
FlaggedDuringContentUpdateRestriction: 0
- m_GUID: 19bfe93240786974ea9d7cd70a7bb635
m_Address: Prefabs/Rooms/Level5
m_ReadOnly: 0
m_SerializedLabels: []
FlaggedDuringContentUpdateRestriction: 0
- m_GUID: 1cc66c0b13a946e1c9ec37026268e144
m_Address: Audio/Enemies/pl_metal2
m_ReadOnly: 0
@@ -62,6 +57,11 @@ MonoBehaviour:
m_ReadOnly: 0
m_SerializedLabels: []
FlaggedDuringContentUpdateRestriction: 0
- m_GUID: 26d4e4c556527924490b8018cd510eda
m_Address: Assets/Resources_moved/Audio/Enemies/bc_bite2.wav
m_ReadOnly: 0
m_SerializedLabels: []
FlaggedDuringContentUpdateRestriction: 0
- m_GUID: 28a6c7a4124141341ab7c2b7dfd3e95b
m_Address: Assets/Resources_moved/Prefabs/Levels/Level1 2.prefab
m_ReadOnly: 0
@@ -102,8 +102,8 @@ MonoBehaviour:
m_ReadOnly: 0
m_SerializedLabels: []
FlaggedDuringContentUpdateRestriction: 0
- m_GUID: 4283d6553fc7f3f4583b9bb0be9d7979
m_Address: Prefabs/Rooms/Box1
- m_GUID: 3f8f2171cc252d953b82083cc16bd1ae
m_Address: Assets/Resources_moved/Prefabs/Levels/Level6_1.prefab
m_ReadOnly: 0
m_SerializedLabels: []
FlaggedDuringContentUpdateRestriction: 0
@@ -112,6 +112,11 @@ MonoBehaviour:
m_ReadOnly: 0
m_SerializedLabels: []
FlaggedDuringContentUpdateRestriction: 0
- m_GUID: 4b279429428a13040b6d1713122cd0de
m_Address: Assets/Resources_moved/Audio/SFX/pl_pain5.wav
m_ReadOnly: 0
m_SerializedLabels: []
FlaggedDuringContentUpdateRestriction: 0
- m_GUID: 4bd64d1fcecc9c6b09d81e78b7dcfebe
m_Address: Audio/Dispatcher/take_damage1
m_ReadOnly: 0
@@ -178,18 +183,18 @@ MonoBehaviour:
m_ReadOnly: 0
m_SerializedLabels: []
FlaggedDuringContentUpdateRestriction: 0
- m_GUID: a1d9e5a04ac11a1468c744b27d442a00
m_Address: Prefabs/Rooms/Stars1
m_ReadOnly: 0
m_SerializedLabels: []
FlaggedDuringContentUpdateRestriction: 0
- m_GUID: a306df57f348ce7cf900d0b9431739ee
m_Address: launch_selectmenu
m_ReadOnly: 0
m_SerializedLabels: []
FlaggedDuringContentUpdateRestriction: 0
- m_GUID: ab5926b5200bedc49aec36c0afe6b028
m_Address: Prefabs/Rooms/Level3_Big
- m_GUID: aa138b2e21adfbf4bbbfa5bf9d54b8f2
m_Address: Assets/Resources_moved/Audio/UI/buttonclickrelease.wav
m_ReadOnly: 0
m_SerializedLabels: []
FlaggedDuringContentUpdateRestriction: 0
- m_GUID: ae6ab2c88ae248ce1b6efca892f17659
m_Address: Assets/Resources_moved/Audio/Music/TestDeath.ogg
m_ReadOnly: 0
m_SerializedLabels: []
FlaggedDuringContentUpdateRestriction: 0
@@ -203,8 +208,8 @@ MonoBehaviour:
m_ReadOnly: 0
m_SerializedLabels: []
FlaggedDuringContentUpdateRestriction: 0
- m_GUID: b3471d165fe389f479380f61034bea57
m_Address: Assets/Resources_moved/Prefabs/Levels/Level1 1.prefab
- m_GUID: b37ea8c61cc322afdad529d678612d22
m_Address: Assets/Resources_moved/Audio/Enemies/zo_attack2.wav
m_ReadOnly: 0
m_SerializedLabels: []
FlaggedDuringContentUpdateRestriction: 0
@@ -218,6 +223,11 @@ MonoBehaviour:
m_ReadOnly: 0
m_SerializedLabels: []
FlaggedDuringContentUpdateRestriction: 0
- m_GUID: c5a0ad8a615841547ac2ee613af526d8
m_Address: Assets/Resources_moved/Audio/SFX/pl_pain2.wav
m_ReadOnly: 0
m_SerializedLabels: []
FlaggedDuringContentUpdateRestriction: 0
- m_GUID: c938de3174f184741925c407a43a47f2
m_Address: Prefabs/Rooms/Level1
m_ReadOnly: 0
@@ -228,21 +238,6 @@ MonoBehaviour:
m_ReadOnly: 0
m_SerializedLabels: []
FlaggedDuringContentUpdateRestriction: 0
- m_GUID: d4eaf1439c2788c458127b9ba67e4fbf
m_Address: Prefabs/Levels/Level1
m_ReadOnly: 0
m_SerializedLabels: []
FlaggedDuringContentUpdateRestriction: 0
- m_GUID: d5b22c0e6700543419ae667d77aadaa2
m_Address: Prefabs/Rooms/Level2_Down
m_ReadOnly: 0
m_SerializedLabels: []
FlaggedDuringContentUpdateRestriction: 0
- m_GUID: dc328d8aadb0e8545978741d451e0544
m_Address: Prefabs/Rooms/Level4_Parkur
m_ReadOnly: 0
m_SerializedLabels: []
FlaggedDuringContentUpdateRestriction: 0
- m_GUID: e3a3840a7963bf841872cddb02e90151
m_Address: Prefabs/Levels/MainMenu 1
m_ReadOnly: 0
@@ -1,6 +1,9 @@
using Code.App.StateMachine;
using Code.App.StateMachine;
using Code.Audio;
using Code.Gameplay.Player;
using Code.Input;
using Code.Scenes;
using Code.Scenes.SceneEnvironments;
using Code.StateMachine;
using Code.UI;
using Cysharp.Threading.Tasks;
@@ -30,7 +33,11 @@ namespace Code.App.AppStates
Context.InputService.EnableMap(ActionMappings.UI);
Context.InputService.DebugBindAction((int)ActionMappings.UI,(int)UIActions.Continue, TryToExit);
GameOver();
Context.AudioService.PlayRandomMusicUntilHumanityWillBeDestroyedForTheySins(MusicType.Death);
Context.AudioService.ApplyStun(5000,0.5f);
GameOver().Forget();
base.EnterState();
}
@@ -45,7 +52,7 @@ namespace Code.App.AppStates
await Context.UIService.AsyncSwitchPanelTo(UIPanel.GameOver);
_gameOverPanel = (GameOverPanel)Context.UIService.CurrentPanel;
_gameOverPanel.Show();
}
private void ToMainMenu()
@@ -71,6 +78,8 @@ namespace Code.App.AppStates
Context.InputService.DisableMap(ActionMappings.UI);
Context.InputService.DebugUnbindAction((int)ActionMappings.UI,(int)UIActions.Continue, TryToExit);
Context.AudioService.GladlyAskToStopMusic(MusicType.Death, callback: Context.AudioFactory.ReleaseDeathMusic);
Context.AudioService.TransitToSnapshot(AudioSnapshotState.None);
base.ExitState();
}
}
@@ -13,10 +13,12 @@ using Code.StateMachine;
using Code.UI;
using Code.UI.Panels;
using Cysharp.Threading.Tasks;
using DG.Tweening;
using Reflex.Core;
using Reflex.Extensions;
using UnityEngine;
using UnityEngine.InputSystem;
using UnityEngine.Rendering;
using UnityEngine.SceneManagement;
namespace Code.App.AppStates
@@ -42,27 +44,18 @@ namespace Code.App.AppStates
.RegisterLoading(LoadingWork.LoadUI)
.RegisterLoading(LoadingWork.LoadModelResource)
.RegisterLoading(LoadingWork.LoadAudio);
//_playerHealth = Context.PlayerFactory.CreatePlayerHealth();
//_playerHealth.OnDamage += PlayerDamageTaken;
//_playerHealth.OnDeath += EndGame;
Context.AudioService.TransitToSnapshot(AudioSnapshotState.None);
Context.InputService.EnableMap(ActionMappings.Gameplay);
Context.InputService.DebugBindAction((int)ActionMappings.Debug, (int)DebugActions.Debug1, InstaKillDEBUG);
Context.InputService.DebugBindAction((int)ActionMappings.Debug, (int)DebugActions.Debug4, RoomPassedDEBUG);
Context.InputService.DebugBindAction((int)ActionMappings.Debug, (int)DebugActions.Debug5, Tube);
Context.InputService.DebugBindAction((int)ActionMappings.Debug, (int)DebugActions.Debug4, TakeGamageDEBUG);
// Context.SceneLoaderService.LoadSceneAsyncAwaitable((int)SceneIds.DevGen);
Context.SceneLoaderService.LoadSceneAsyncAwaitable((int)SceneIds.DevGen);
Context.LoadingManager.OnLoadingEnded += AfterSceneLoaded;
#pragma warning disable CS4014 // Because this call is not awaited, execution of the current method continues before the call is completed
WaitForLoad();
#pragma warning restore CS4014 // Because this call is not awaited, execution of the current method continues before the call is completed
WaitForLoad().Forget();
}
private async UniTask WaitForPlayerCharacterLoad() => _playerCharacter = await Context.PlayerFactory.CreatePlayer();
@@ -71,6 +64,7 @@ namespace Code.App.AppStates
await UniTask.WhenAll(
Context.UIService.AsyncSwitchPanelTo(UIPanel.Gameplay),
Context.AudioFactory.WarmGameplayMusic(),
Context.AudioFactory.WarmDeathMusic(),
Context.AudioFactory.WarmSFX(),
Context.AudioFactory.WarmDispatcher(),
Context.AudioFactory.WarmEnemies(),
@@ -118,6 +112,8 @@ namespace Code.App.AppStates
GameplaySceneEnvironment sceneEnvironment = SceneEnvironmentVariables(sceneContainer);
_volume = sceneEnvironment.volume;
PlayerInitialize(sceneEnvironment);
CameraInitialize();
@@ -159,22 +155,31 @@ namespace Code.App.AppStates
private void PlayerDamageTaken(int damage, PlayerHealth health)
{
Context.AudioService.PlayDispatcher((DispatcherSounds)Random.Range((int)DispatcherSounds.TakeDamage1,(int)DispatcherSounds.TakeDamage4));
Context.AudioService.PlayCourier((CourierSounds)Random.Range((int)CourierSounds.Damage1,(int)CourierSounds.Damage2));
DamageEffectProcess().Forget();
}
// TODO В конфиг
private async UniTaskVoid DamageEffectProcess()
{
_damagePanel.Show();
Context.AudioService.ApplyStun(200, 0.5f);
DOTween.To(() => _volume.weight, x => _volume.weight = x, 1f, 0.5f);
await UniTask.WaitForSeconds(3f);
DOTween.To(() => _volume.weight, x => _volume.weight = x, 0f, 1f);
Context.AudioService.ApplyStun(5000, 1f);
_damagePanel.Hide();
}
// DEBUG
private void InstaKillDEBUG(InputAction.CallbackContext context)
{
_playerHealth.InstaKill();
}
private void RoomPassedDEBUG(InputAction.CallbackContext context)
private void TakeGamageDEBUG(InputAction.CallbackContext context)
{
_orderService.RoomPassed();
}
private OrderDispenser _debugTube;
private void Tube(InputAction.CallbackContext context)
{
_debugTube.ThrowOrder();
}
_playerHealth.GetDamage(1);
}
// DEBUG
private bool _tickEnabled;
public override void Tick()
@@ -207,8 +212,8 @@ namespace Code.App.AppStates
Context.AudioService.OnDispatcherEnded -= _gameplayPanel.CloseDispatcher;
Context.InputService.DisableMap(ActionMappings.Gameplay);
Context.AudioService.GladlyAskToStopMusic(MusicType.Action, callback: Context.AudioFactory.ReleaseActionMusic);
Context.AudioService.GladlyAskToStopMusic(MusicType.Peaceful, callback: Context.AudioFactory.ReleasePeacefulMusic);
Context.AudioService.GladlyAskToStopMusic(MusicType.Action, time: 0f, callback: Context.AudioFactory.ReleaseActionMusic);
Context.AudioService.GladlyAskToStopMusic(MusicType.Peaceful, time: 0f, callback: Context.AudioFactory.ReleasePeacefulMusic);
Context.AudioFactory.ReleaseCourier();
Context.AudioFactory.ReleaseDispatcher();
Context.AudioFactory.ReleaseEnemies();
@@ -216,8 +221,7 @@ namespace Code.App.AppStates
Context.InputService.DebugUnbindAction((int)ActionMappings.Debug, (int)DebugActions.Debug1, InstaKillDEBUG);
Context.InputService.DebugUnbindAction((int)ActionMappings.Debug, (int)DebugActions.Debug4, RoomPassedDEBUG);
Context.InputService.DebugUnbindAction((int)ActionMappings.Debug, (int)DebugActions.Debug5, Tube);
Context.InputService.DebugUnbindAction((int)ActionMappings.Debug, (int)DebugActions.Debug4, TakeGamageDEBUG);
base.ExitState();
}
@@ -234,13 +238,15 @@ namespace Code.App.AppStates
private GameplayPanel _gameplayPanel;
private ArmsMeshProvider _armsMesh;
private DamagePanel _damagePanel;
private void UIInitialize()
{
_gameplayPanel = (GameplayPanel)Context.UIService.CurrentPanel;
_gameplayPanel.Initialize(_playerScore, _playerHealth, _orderService);
Context.AudioService.OnDispatcherStarted += _gameplayPanel.SummonDispatcher;
Context.AudioService.OnDispatcherEnded += _gameplayPanel.CloseDispatcher;
_damagePanel = _gameplayPanel.DamagePanel;
}
private void MusicInitialize()
{
@@ -262,10 +268,11 @@ namespace Code.App.AppStates
_orderService.OnOrderDelivered += OrderDelivered;
_orderService.OnOrderFailure += OrderFailure;
}
private Volume _volume;
private GameplaySceneEnvironment SceneEnvironmentVariables(Container sceneContainer)
{
var sceneEnvironment = (GameplaySceneEnvironment)sceneContainer.Resolve<CurrentSceneEnvironment>();
return sceneEnvironment;
}
@@ -67,6 +67,7 @@ namespace Code.App
containerBuilder.AddSingleton(infrastructureUnit.AddComponent<CameraStateMachine>());
}
// TODO Часть в сцены
private void InstallStaticData(ContainerBuilder containerBuilder, out IStaticDataService staticDataService)
{
staticDataService = new StaticDataService();
@@ -97,6 +98,8 @@ namespace Code.App
containerBuilder.AddSingleton(staticDataService.DispatcherSoundListConfig, typeof(DispatcherSoundListConfig));
containerBuilder.AddSingleton(staticDataService.EnemiesSoundListConfig, typeof(EnemiesSoundListConfig));
containerBuilder.AddSingleton(staticDataService.AudioSourceSettingsConfigs, typeof(Dictionary<AudioSourceType, AudioSourceSettingsConfig>));
containerBuilder.AddSingleton(staticDataService.DefaultAudioSettingsConfig, typeof(DefaultAudioSettingsConfig));
containerBuilder.AddSingleton(staticDataService.OrderServiceConfig, typeof(OrderServiceConfig));
containerBuilder.AddSingleton(staticDataService.OrderBoxConfig, typeof(OrderBoxConfig));
@@ -116,9 +119,7 @@ namespace Code.App
AttributeInjector.Inject(cameraStateMachine.StateMachineContext, container);
cameraStateMachine.Initialize();
#pragma warning disable CS4014 // Because this call is not awaited, execution of the current method continues before the call is completed
BootstrapFinish(container);
#pragma warning restore CS4014 // Because this call is not awaited, execution of the current method continues before the call is completed
BootstrapFinish(container).Forget();
}
private async UniTaskVoid BootstrapFinish(Container container)
{
@@ -11,8 +11,8 @@ namespace Code.Audio
}
public enum EnemiesSounds
{
Bastard,
Bravo,
GrandpaAttack,
RoachAttack,
RoachStep,
GrandpaStep
}
@@ -32,6 +32,8 @@ namespace Code.Audio
}
public enum CourierSounds
{
Step
Step,
Damage1,
Damage2
}
}
@@ -19,6 +19,7 @@ namespace Code.Audio
private AssetReference[] _audioTestClipsReferences;
private AssetReference[] _peacefulSoundtrack;
private AssetReference[] _actionSoundtrack;
private AssetReference[] _deathSoundtrack;
private AssetReference[] _menuSoundtrack;
private AssetReference[] _SFX;
private AssetReference[] _enemies;
@@ -27,6 +28,7 @@ namespace Code.Audio
private AsyncOperationHandle<IList<AudioClip>> _audioTestClipsHandle;
private AsyncOperationHandle<IList<AudioClip>> _menuMusicHandle;
private AsyncOperationHandle<IList<AudioClip>> _deathMusicHandle;
private AsyncOperationHandle<IList<AudioClip>> _actionMusicHandle;
private AsyncOperationHandle<IList<AudioClip>> _peacefulMusicHandle;
private AsyncOperationHandle<IList<AudioClip>> _SFXHandle;
@@ -55,6 +57,7 @@ namespace Code.Audio
_peacefulSoundtrack = soundtrackListConfig.peacefulSoundtrack;
_actionSoundtrack = soundtrackListConfig.actionSoundtrack;
_deathSoundtrack = soundtrackListConfig.deathSoundtrack;
_menuSoundtrack = soundtrackListConfig.menuSoundtrack;
_SFX = sfxListConfig.SFX;
_enemies = enemiesSoundListConfig.enemies;
@@ -63,8 +66,9 @@ namespace Code.Audio
_audioTestClipsReferences = audioTestClipsConfig.audioTestClips;
MusicDictionary.Add(MusicType.Menu, new ());
MusicDictionary.Add(MusicType.Peaceful, new ());
MusicDictionary.Add(MusicType.Death, new ());
MusicDictionary.Add(MusicType.Action, new ());
MusicDictionary.Add(MusicType.Peaceful, new ());
}
public async UniTask LoadAudioSourcePrefab(Action<GameObject> callback) =>
@@ -116,6 +120,16 @@ namespace Code.Audio
// foreach (var assetReference in _menuSoundtrack) assetReference.ReleaseAsset();
_menuMusicHandle.Release();
}
public async UniTask WarmDeathMusic()
{
_deathMusicHandle = Addressables.LoadAssetsAsync<AudioClip>(_deathSoundtrack, OnDeathTrackLoaded, Addressables.MergeMode.Union);
await _deathMusicHandle.ToUniTask();
}
public void ReleaseDeathMusic()
{
MusicDictionary[MusicType.Death].Clear();
_deathMusicHandle.Release();
}
public async UniTask WarmSFX( )
{
_SFXHandle = Addressables.LoadAssetsAsync<AudioClip>(_SFX, OnSFXLoaded, Addressables.MergeMode.Union);
@@ -172,6 +186,10 @@ namespace Code.Audio
{
MusicDictionary[MusicType.Menu].Add(audioClip);
}
private void OnDeathTrackLoaded(AudioClip audioClip)
{
MusicDictionary[MusicType.Death].Add(audioClip);
}
// private int _audioTestClipCounter;
private void OnAudioTestClipLoaded(AudioClip audioClip)
@@ -22,23 +22,30 @@ namespace Code.Audio
private AudioSource _actionMusicSource;
private AudioSource _peacefulMusicSource;
private Dictionary<AudioType,AudioMixerGroup> _audioMixerGroups = new ();
private Dictionary<AudioType, AudioMixerGroup> _audioMixerGroups = new();
private readonly AudioSourcePool _audioSourcePool;
private Dictionary<AudioSnapshotState, AudioMixerSnapshot> _snapshots = new();
// Юнити не может - говнокод поможет.
private Dictionary<AudioSnapshotState, Dictionary<AudioType, float>> _snapshotsVolumes = new();
private Dictionary<AudioSourceType, AudioSourceSettingsConfig> _settings;
public AudioService(IAudioFactory audioFactory, Dictionary<AudioSourceType, AudioSourceSettingsConfig> settings)
public AudioService(IAudioFactory audioFactory,
Dictionary<AudioSourceType, AudioSourceSettingsConfig> settings,
DefaultAudioSettingsConfig defaultAudioSettingsConfig)
{
_audioFactory = audioFactory;
_audioSourcePool = new(settings);
_settings = settings;
_snapshotsVolumes.Add(AudioSnapshotState.None,defaultAudioSettingsConfig.noneVolume);
_snapshotsVolumes.Add(AudioSnapshotState.Menu,defaultAudioSettingsConfig.menuVolume);
_snapshotsVolumes.Add(AudioSnapshotState.Action,defaultAudioSettingsConfig.actionVolume);
_snapshotsVolumes.Add(AudioSnapshotState.Peaceful,defaultAudioSettingsConfig.peacefulVolume);
}
// TODO Грязно, убрать снапшоты НАХУЙ
public float GetSetting(AudioType type)
{
_snapshots[AudioSnapshotState.Peaceful].audioMixer.GetFloat(_audioMixerGroups[type].name, out float value);
_mixer.GetFloat(_audioMixerGroups[type].name, out float value);
value = Mathf.Pow(10f, value / 20);
@@ -50,27 +57,32 @@ namespace Code.Audio
float volume = Mathf.Log10(value) * 20;
switch (type)
{
case AudioType.DeathMusic:
case AudioType.Master:
_snapshots[AudioSnapshotState.Menu].audioMixer.SetFloat(_audioMixerGroups[type].name, volume);
_snapshots[AudioSnapshotState.Peaceful].audioMixer.SetFloat(_audioMixerGroups[type].name, volume);
_snapshots[AudioSnapshotState.Action].audioMixer.SetFloat(_audioMixerGroups[type].name, volume);
_snapshotsVolumes[AudioSnapshotState.Menu][type] = value;
_snapshotsVolumes[AudioSnapshotState.Action][type] = value;
_snapshotsVolumes[AudioSnapshotState.Peaceful][type] = value;
_mixer.SetFloat(_audioMixerGroups[type].name, volume);
break;
case AudioType.ActionMusic:
_snapshots[AudioSnapshotState.Action].audioMixer.SetFloat(_audioMixerGroups[type].name, volume);
_snapshotsVolumes[AudioSnapshotState.Action][type] = value;
_mixer.SetFloat(_audioMixerGroups[type].name, volume);
break;
case AudioType.PeacefulMusic:
_snapshots[AudioSnapshotState.Peaceful].audioMixer.SetFloat(_audioMixerGroups[type].name, volume);
_snapshotsVolumes[AudioSnapshotState.Peaceful][type] = value;
_mixer.SetFloat(_audioMixerGroups[type].name, volume);
break;
case AudioType.MenuMusic:
_snapshots[AudioSnapshotState.Menu].audioMixer.SetFloat(_audioMixerGroups[type].name, volume);
break;
case AudioType.Creatures:
case AudioType.SFX:
case AudioType.DispatcherSounds:
_snapshotsVolumes[AudioSnapshotState.Menu][type] = value;
_mixer.SetFloat(_audioMixerGroups[type].name, volume);
break;
case AudioType.SFX:
case AudioType.Dispatcher:
case AudioType.Courier:
case AudioType.Enemies:
_snapshots[AudioSnapshotState.Peaceful].audioMixer.SetFloat(_audioMixerGroups[type].name, volume);
_snapshots[AudioSnapshotState.Action].audioMixer.SetFloat(_audioMixerGroups[type].name, volume);
_snapshotsVolumes[AudioSnapshotState.Action][type] = value;
_snapshotsVolumes[AudioSnapshotState.Peaceful][type] = value;
_mixer.SetFloat(_audioMixerGroups[type].name, volume);
break;
}
}
@@ -80,36 +92,34 @@ namespace Code.Audio
_mixer = _audioFactory.AudioMixer;
_musicAudioGroups.Add(MusicType.Menu, _mixer.FindMatchingGroups(AudioGroups.MenuMusicGroup)[0]);
_musicAudioGroups.Add(MusicType.Death, _mixer.FindMatchingGroups(AudioGroups.DeathMusicGroup)[0]);
_musicAudioGroups.Add(MusicType.Action, _mixer.FindMatchingGroups(AudioGroups.ActionMusicGroup)[0]);
_musicAudioGroups.Add(MusicType.Peaceful, _mixer.FindMatchingGroups(AudioGroups.PeacefulMusicGroup)[0]);
_cancellationTokenSources.Add(MusicType.Menu, new());
_cancellationTokenSources.Add(MusicType.Death, new());
_cancellationTokenSources.Add(MusicType.Action, new());
_cancellationTokenSources.Add(MusicType.Peaceful, new());
_musicAudioSources.Add(MusicType.Menu, null);
_musicAudioSources.Add(MusicType.Death, null);
_musicAudioSources.Add(MusicType.Action, null);
_musicAudioSources.Add(MusicType.Peaceful, null);
_audioMixerGroups.Add(AudioType.Master, _mixer.FindMatchingGroups(AudioGroups.MasterGroup)[0]);
_audioMixerGroups.Add(AudioType.SFX, _mixer.FindMatchingGroups(AudioGroups.SFXGroup)[0]);
_audioMixerGroups.Add(AudioType.Creatures, _mixer.FindMatchingGroups(AudioGroups.CreaturesGroup)[0]);
_audioMixerGroups.Add(AudioType.DispatcherSounds, _mixer.FindMatchingGroups(AudioGroups.DispatcherMusicGroup)[0]);
_audioMixerGroups.Add(AudioType.SFX, _mixer.FindMatchingGroups(AudioGroups.SFXGroup)[0]);
_audioMixerGroups.Add(AudioType.Dispatcher, _mixer.FindMatchingGroups(AudioGroups.DispatcherMusicGroup)[0]);
_audioMixerGroups.Add(AudioType.Courier, _mixer.FindMatchingGroups(AudioGroups.CourierGroup)[0]);
_audioMixerGroups.Add(AudioType.Enemies, _mixer.FindMatchingGroups(AudioGroups.EnemiesMusicGroup)[0]);
_audioMixerGroups.Add(AudioType.Enemies, _mixer.FindMatchingGroups(AudioGroups.EnemiesGroup)[0]);
_audioMixerGroups.Add(AudioType.MenuMusic, _musicAudioGroups[MusicType.Menu]);
_audioMixerGroups.Add(AudioType.DeathMusic, _musicAudioGroups[MusicType.Death]);
_audioMixerGroups.Add(AudioType.ActionMusic, _musicAudioGroups[MusicType.Action]);
_audioMixerGroups.Add(AudioType.PeacefulMusic, _musicAudioGroups[MusicType.Peaceful]);
_snapshots[AudioSnapshotState.None] = _mixer.FindSnapshot(AudioGroups.NoneSnapshot);
_snapshots[AudioSnapshotState.Menu] = _mixer.FindSnapshot(AudioGroups.MenuSnapshot);
_snapshots[AudioSnapshotState.Action] = _mixer.FindSnapshot(AudioGroups.ActionSnapshot);
_snapshots[AudioSnapshotState.Peaceful] = _mixer.FindSnapshot(AudioGroups.PeacefulSnapshot);
await _audioFactory.LoadAudioSourcePrefab(_audioSourcePool.Initialize);
}
#pragma warning disable CS4014 // Because this call is not awaited, execution of the current method continues before the call is completed
private Dictionary<MusicType, CancellationTokenSource> _cancellationTokenSources = new();
private Dictionary<MusicType, AudioSource> _musicAudioSources = new();
private Dictionary<MusicType, AudioMixerGroup> _musicAudioGroups = new();
@@ -129,14 +139,11 @@ namespace Code.Audio
_musicAudioSources[musicType].Play();
// await UniTask.WaitUntilValueChanged(_musicAudioSources[musicType],
// _ => !_musicAudioSources[musicType].isPlaying,
// cancellationToken: _cancellationTokenSources[musicType].Token);
await UniTask.NextFrame();
var (isCanceled, _) = await UniTask.WaitUntilValueChanged(_musicAudioSources[musicType],
_ => !_musicAudioSources[musicType].isPlaying,
cancellationToken: _cancellationTokenSources[musicType].Token).SuppressCancellationThrow();
Debug.LogError("Music skipping");
if (isCanceled)
{
_cancellationTokenSources[musicType].Dispose();
@@ -148,13 +155,13 @@ namespace Code.Audio
return;
}
PlayRandomMusicUntilHumanityWillBeDestroyedForTheySins(musicType);
PlayRandomMusicUntilHumanityWillBeDestroyedForTheySins(musicType).Forget();
}
public async UniTaskVoid GladlyAskToStopMusic(MusicType musicType,
AudioSnapshotState audioSnapshotState = AudioSnapshotState.None, float time = 1f, Action callback = null)
{
TransitToSnapshot(audioSnapshotState, time);
//TransitToSnapshot(audioSnapshotState, time);
await UniTask.WaitForSeconds(time);
@@ -162,39 +169,54 @@ namespace Code.Audio
callback?.Invoke();
}
#pragma warning restore CS4014 // Because this call is not awaited, execution of the current method continues before the call is completed
public void StopMusic()
{
_peacefulMusicSource.Stop();
_actionMusicSource.Stop();
_cancellationTokenSources[MusicType.Peaceful].Cancel();
_cancellationTokenSources[MusicType.Action].Cancel();
}
public void GladlyAskToStopMusic(Action callback = null)
{
TransitToSnapshot(AudioSnapshotState.None);
// TransitToSnapshot(AudioSnapshotState.None);
_peacefulMusicSource.Stop();
_actionMusicSource.Stop();
callback?.Invoke();
}
public void TransitToSnapshot(AudioSnapshotState state, float time = 1f)
public void TransitToSnapshot(AudioSnapshotState state, float time = 1)
{
_snapshots[state].TransitionTo(time);
foreach (var key in _audioMixerGroups.Keys)
_mixer.DOSetFloat(_audioMixerGroups[key].name, Mathf.Log10(_snapshotsVolumes[state][key]) * 20, time);
}
public void PlaySFX(SFXSounds sfxId, Vector3 position)
{
_audioSourcePool.PlayOneShot(_audioFactory.SFXAudios[(int)sfxId], position, _audioMixerGroups[AudioType.SFX]).Forget();
_audioSourcePool
.PlayOneShot(_audioFactory.SFXAudios[(int)sfxId], position, _audioMixerGroups[AudioType.SFX]).Forget();
}
public void ApplyStun(float value, float time)
{
_mixer.DOSetFloat("Stun", value, time);
}
public void PlayEnemy(EnemiesSounds enemySoundId, Vector3 position)
{
_audioSourcePool.PlayOneShot(_audioFactory.EnemiesAudios[(int)enemySoundId], position, _audioMixerGroups[AudioType.Enemies]).Forget();
_audioSourcePool.PlayOneShot(_audioFactory.EnemiesAudios[(int)enemySoundId], position,
_audioMixerGroups[AudioType.Enemies]).Forget();
}
public AudioSource GetSourceOfGroup(AudioType group)
{
AudioSource source = _audioSourcePool.GetSource();
source.outputAudioMixerGroup = _audioMixerGroups[group];
return source;
}
public AudioSource GetSourceOfGroup(AudioType group) => _audioSourcePool.GetSource();
public void ReleaseSourceOfGroup(AudioSource source) => _audioSourcePool.ReleaseSource(source);
// Чинить долго и дорого пусть Артёмов будет много, ведь он наш друг
@@ -204,18 +226,27 @@ namespace Code.Audio
public void PlayDispatcher(DispatcherSounds dispatcherSoundId)
{
OnDispatcherStarted?.Invoke();
_audioSourcePool.PlayOneShot(_audioFactory.DispatcherAudios[(int)dispatcherSoundId], _audioMixerGroups[AudioType.DispatcherSounds],
_audioSourcePool.PlayOneShot(_audioFactory.DispatcherAudios[(int)dispatcherSoundId],
_audioMixerGroups[AudioType.Dispatcher],
AudioSourceType.NoBlend, () => OnDispatcherEnded?.Invoke()).Forget();
}
public void PlayCourier(CourierSounds courierSounds)
{
_audioSourcePool.PlayOneShot(_audioFactory.CourierAudios[(int)courierSounds],
_audioMixerGroups[AudioType.Courier],
AudioSourceType.NoBlend).Forget();
}
private CancellationTokenSource _testClipCancellationTokenSource = new();
private void ResetCurrentTestAudioSource() => _currentTestClipAudioType = AudioType.Master;
private AudioType _currentTestClipAudioType;
// TODO Засунуть в словарь
public void PlayTestClip(AudioType audioType)
{
if(_currentTestClipAudioType == audioType) return;
if (_currentTestClipAudioType == audioType) return;
_testClipCancellationTokenSource.Cancel();
_testClipCancellationTokenSource = new();
@@ -225,6 +256,5 @@ namespace Code.Audio
_audioMixerGroups[audioType], _testClipCancellationTokenSource,
AudioSourceType.NoBlend, ResetCurrentTestAudioSource).Forget();
}
}
}
@@ -31,5 +31,7 @@ namespace Code.Audio
void ReleaseDispatcher();
UniTask WarmCourier();
void ReleaseCourier();
UniTask WarmDeathMusic( );
void ReleaseDeathMusic();
}
}
@@ -25,5 +25,7 @@ namespace Code.Audio
void PlayTestClip(AudioType audioType);
AudioSource GetSourceOfGroup(AudioType group);
void ReleaseSourceOfGroup(AudioSource source);
void PlayCourier(CourierSounds range);
void ApplyStun(float value, float time);
}
}
@@ -4,18 +4,19 @@ namespace Code.Audio
{
Menu,
Peaceful,
Action
Action,
Death
}
public enum AudioType
{
Master,
MenuMusic,
Creatures,
DispatcherSounds,
MenuMusic,
Dispatcher,
SFX,
Courier,
Enemies,
ActionMusic,
PeacefulMusic
PeacefulMusic,
DeathMusic
}
}
@@ -0,0 +1,27 @@
using System.Collections.Generic;
using AYellowpaper.SerializedCollections;
using UnityEngine;
using AudioType = Code.Audio.AudioType;
namespace Code.Configs
{
[CreateAssetMenu(fileName = "DefaultAudioSettingsConfig", menuName = "Audio/DefaultAudioSettings")]
public class DefaultAudioSettingsConfig : ScriptableObject
{
[Header("Menu")]
[SerializedDictionary("AudioType", "Volume")]
public SerializedDictionary<Audio.AudioType, float> menuVolume = new();
[Header("Action")]
[SerializedDictionary("AudioType", "Volume")]
public SerializedDictionary<Audio.AudioType, float> actionVolume = new();
[Header("Peaceful")]
[SerializedDictionary("AudioType", "Volume")]
public SerializedDictionary<Audio.AudioType, float> peacefulVolume = new();
[Header("None")]
[SerializedDictionary("AudioType", "Volume")]
public SerializedDictionary<Audio.AudioType, float> noneVolume = new();
}
}
@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 36d35c52933d4d4ba836f75b05c4810f
timeCreated: 1764754933
@@ -8,6 +8,7 @@ namespace Code.Configs
{
public AssetReference[] peacefulSoundtrack;
public AssetReference[] actionSoundtrack;
public AssetReference[] deathSoundtrack;
public AssetReference[] menuSoundtrack;
}
}
@@ -20,12 +20,13 @@ namespace Code.Constants
public const string ActionMusicGroup = "Action";
public const string DispatcherMusicGroup = "Dispatcher";
public const string CourierGroup = "Courier";
public const string EnemiesMusicGroup = "Enemies";
public const string EnemiesGroup = "Enemies";
public const string PeacefulSnapshot = "Peaceful";
public const string ActionSnapshot = "Action";
public const string NoneSnapshot = "None";
public const string MenuSnapshot = "Menu";
public const string MenuMusicGroup = "Menu";
public const string DeathMusicGroup = "Death";
}
}
@@ -188,11 +188,10 @@ namespace Code.Gameplay.Enemies
_canAttack = false;
_attackCooldownTimer = AttackCooldown;
}
protected virtual void ApplyEffectsToPlayer()
{
if (PlayerController)
PlayerController.BlockAbilities(3f);
PlayerController.BlockAbilities(3f); // TODO в конфиг
}
private void OnDrawGizmosSelected()
@@ -50,7 +50,7 @@ namespace Code.Gameplay.Enemies
if (!(distance <= AttackRange)) return;
audioService.PlayEnemy(EnemiesSounds.Bravo,agent.transform.position);
audioService.PlayEnemy(EnemiesSounds.RoachAttack, agent.transform.position);
DealDamage();
}
@@ -50,7 +50,7 @@ namespace Code.Gameplay.Enemies
if (!(distance <= AttackRange)) return;
audioService.PlayEnemy(EnemiesSounds.Bastard,agent.transform.position);
audioService.PlayEnemy(EnemiesSounds.GrandpaAttack,agent.transform.position);
if (Player.CustomCharacterController.IsSliding)
ApplyStun();
@@ -8,7 +8,7 @@ namespace Code.Gameplay.Enemies
{
private IAudioService _audioService;
private IAudioFactory _audioFactory;
private AudioSource _audioSource;
[SerializeField] private AudioSource _audioSource;
[SerializeField] private EnemiesSounds stepId;
[Inject]
@@ -17,13 +17,12 @@ namespace Code.Gameplay.Enemies
_audioService = audioService;
_audioSource = audioService.GetSourceOfGroup(Audio.AudioType.Enemies);
_audioSource.transform.position = transform.position;
_audioSource.spatialBlend = 0;
_audioFactory = audioFactory;
}
public void PlayStep()
{
Debug.Log("Play Step");
_audioSource.transform.position = transform.position;
_audioSource.PlayOneShot(_audioFactory.EnemiesAudios[(int)stepId]);
}
@@ -3,9 +3,11 @@ using Code.Configs;
using Cysharp.Threading.Tasks;
using Reflex.Attributes;
using Reflex.Core;
using Reflex.Extensions;
using Reflex.Injectors;
using UnityEngine;
using UnityEngine.AddressableAssets;
using UnityEngine.SceneManagement;
namespace Code.Gameplay.Enemies
{
@@ -27,15 +29,14 @@ namespace Code.Gameplay.Enemies
)
.ToUniTask();
// Работает, пока не трогаю
AttributeInjector.Inject(enemyObj, Container.ProjectContainer);
GameObjectInjector.InjectRecursive(enemyObj, SceneManager.GetActiveScene().GetSceneContainer());
return enemyObj.GetComponent<BaseEnemy>();
}
public void ReleaseEnemy(BaseEnemy enemy)
{
if (enemy == null) return;
if (!enemy) return;
enemy.gameObject.SetActive(false);
@@ -1,8 +1,7 @@
using System.Collections.Generic;
using Code.Gameplay.Orders.Order;
using Code.Scenes;
using Code.Scenes.SceneEnvironments;
using Cysharp.Threading.Tasks;
using Code.Scenes.SceneEnvironments;
using Reflex.Attributes;
using UnityEngine;
@@ -36,19 +35,10 @@ namespace Code.Generator
public void Initialize()
{
// _orderService.OrderGive();
_spawnedRooms = new List<Room>();
_roomIndexesStack = new();
Debug.LogWarning($"КОТЛЫ ГЕНЕРАЛЬСКИЕ{_orderService.DeliveryTimer}");
// CreateRoomsStack();
// SpawnInitialRoomsAsync();
_orderService.OnOrderGiven += CreateRoomsStack;
// RoomTrigger.PlayerEnteredRoom += OnPlayerEntered;
CreateInitialRoom();
}
@@ -61,7 +51,6 @@ namespace Code.Generator
Room roomToRemove = _spawnedRooms[0];
_spawnedRooms.RemoveAt(0);
// _factory.ReleaseRoom(roomToRemove);
Object.Destroy(roomToRemove.gameObject);
}
}
@@ -81,16 +70,12 @@ namespace Code.Generator
_roomIndexesStack.Add(new(RoomType.Basic, roomIndex));
remainingTime -= room.RoomTimer;
Debug.Log($"комната {room.name} время {room.RoomTimer} осталось: {remainingTime}");
}
AddPickupRoom();
Debug.Log($"добавлена зона заказа");
AddSaveRoom();
Debug.Log($"добавлена сейв зона");
Debug.Log($"стек комнат: {_roomIndexesStack.Count}");
SpawnNextRoom();
}
@@ -125,8 +110,6 @@ namespace Code.Generator
gameplaySceneEnvironment.playerSpawnPoint = instantiated.playerSpawn;
instantiated.Initialize(_orderService);
Debug.Log($"Первая комната: {instantiated.name}");
}
private void SpawnNextRoom()
{
@@ -205,18 +188,8 @@ namespace Code.Generator
segmentOriginPosition.y -= randomDoorOriginPosition.y;
current.transform.position = segmentOriginPosition;
current.transform.rotation = Quaternion.Euler(0, segmentOriginYRotation, 0);
// locationSegment.isNeedSomeDoors = true;
// locationSegment.AddBadDoorId(locationSegment.LocationSegment.GetDoorOrigins.IndexOf(randomDoorOrigin));
current.Initialize(_orderService);
// float frameOnTheBallRotation = segmentOriginYRotation + randomDoorOriginRotation.eulerAngles.y;
// if (frameOnTheBallRotation > 305f) frameOnTheBallRotation -= 360f;
// else if (frameOnTheBallRotation < -45f) frameOnTheBallRotation += 360f;
// heOnTheBall.AddSlaveLocationSegment(locationSegment.Id);
// heOnTheBall.ReplaceSlaveSegmentDoorOriginYRotation(frameOnTheBallRotation);
// heOnTheBall.isGotOnTheBall = false;
current.transform.rotation = Quaternion.Euler(0, segmentOriginYRotation, 0);
current.Initialize(_orderService);
}
}
}
@@ -1,5 +1,6 @@
using Code.Gameplay.Orders.Order;
using UnityEngine;
using UnityEngine.Rendering;
using UnityEngine.Serialization;
namespace Code.Scenes.SceneEnvironments
@@ -7,11 +8,13 @@ namespace Code.Scenes.SceneEnvironments
[System.Serializable]
public class GameplaySceneEnvironment : CurrentSceneEnvironment
{
public Transform playerSpawnPoint;
public Transform playerSpawnPoint;
public Volume volume;
public void TransitVariables(GameplaySceneEnvironment env)
{
playerSpawnPoint = env.playerSpawnPoint;
volume = env.volume;
}
}
}
@@ -34,6 +34,7 @@ namespace Code.StaticData
AudioTestClipsConfig AudioTestClipsConfig { get; }
GeneratorConfig GeneratorConfig { get; }
CourierSoundListConfig CourierSoundListConfig { get; }
DefaultAudioSettingsConfig DefaultAudioSettingsConfig { get; }
void Load();
Task<T> InstantiateAsset<T>(AssetReference assetReference) where T : Behaviour;
}
@@ -30,6 +30,7 @@ namespace Code.StaticData
public EnemiesSoundListConfig EnemiesSoundListConfig { get; private set; }
public AudioTestClipsConfig AudioTestClipsConfig { get; private set; }
public CourierSoundListConfig CourierSoundListConfig { get; private set; }
public DefaultAudioSettingsConfig DefaultAudioSettingsConfig { get; private set; }
public DrunkenGrandpaConfig DrunkenGrandpaConfig {get; private set;}
public CockroachConfig CockroachConfig { get; private set; }
@@ -67,6 +68,7 @@ namespace Code.StaticData
private void LoadAudioConfigs()
{
AudioMixerConfig = Resources.Load<AudioMixerConfig>(string.Format(StringPaths.ConfigSingle, "Audio", "AudioMixerConfig"));
DefaultAudioSettingsConfig = Resources.Load<DefaultAudioSettingsConfig>(string.Format(StringPaths.ConfigSingle, "Audio", "DefaultAudioSettingsConfig"));
SoundtrackListConfig = Resources.Load<SoundtrackListConfig>(string.Format(StringPaths.ConfigSingle, "Audio", "SoundtrackListConfig"));
AudioTestClipsConfig = Resources.Load<AudioTestClipsConfig>(string.Format(StringPaths.ConfigSingle, "Audio", "AudioTestClipsConfig"));
SFXListConfig = Resources.Load<SFXListConfig>(string.Format(StringPaths.ConfigSingle, "Audio", "SFXListConfig"));
@@ -0,0 +1,25 @@
using DG.Tweening;
using UnityEngine;
using UnityEngine.UI;
namespace Code.UI.Panels
{
public class DamagePanel : UIElement
{
[SerializeField] private Image background;
[SerializeField] private Color shownColor;
[SerializeField] private Color hiddenColor;
public override void Hide()
{
Shown = false;
// background.enabled = false;
background.DOColor(hiddenColor, 2f);
}
public override void Show()
{
Shown = true;
// background.enabled = true;
background.DOColor(shownColor, 0.3f);
}
}
}
@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: b586dbc292c44261892460f578a38e50
timeCreated: 1764769541
@@ -1,3 +1,4 @@
using DG.Tweening;
using TMPro;
using UnityEngine;
using UnityEngine.UI;
@@ -9,21 +10,27 @@ namespace Code.UI
[SerializeField] private TMP_Text scoreText;
[SerializeField] private TMP_Text gameOverText;
[SerializeField] private Image _background;
[SerializeField] private Color shownColor;
[SerializeField] private Color hiddenColor;
public void UpdateScoreText(int score) => scoreText.text = score.ToString();
public override void Hide()
{
_background.enabled = false;
scoreText.enabled = false;
gameOverText.enabled = false;
// scoreText.enabled = true;
// gameOverText.enabled = false;
scoreText.DOColor(hiddenColor, 3f);
// gameOverText.DOColor(hiddenColor, 3f);
base.Hide();
}
public override void Show()
{
_background.enabled = true;
scoreText.enabled = true;
gameOverText.enabled = true;
// _background.enabled = true;
// scoreText.enabled = true;
// gameOverText.enabled = true;
scoreText.DOColor(shownColor, 5f);
// gameOverText.DOColor(shownColor, 5f);
base.Show();
}
}
@@ -26,6 +26,9 @@ namespace Code.UI.Panels
[Header("MoneyBar")]
[SerializeField] private TMP_Text moneyText;
[SerializeField] private DamagePanel damagePanel;
public DamagePanel DamagePanel => damagePanel;
private void ScoreUpdate(int count, int money)
{
// TODO Анимация получения\потери
@@ -7,21 +7,24 @@ namespace Code.UI.Panels
public class LoadingScreen : UIElement
{
[SerializeField] private Image background;
[SerializeField] private TMP_Text loadingTitle;
[SerializeField] private TMP_Text vyapWatermark;
[SerializeField] private Image loadingImage;
// [SerializeField] private TMP_Text loadingTitle;
// [SerializeField] private TMP_Text vyapWatermark;
public override void Hide()
{
Shown = false;
background.enabled = false;
loadingTitle.enabled = false;
vyapWatermark.enabled = false;
loadingImage.enabled = false;
// loadingTitle.enabled = false;
// vyapWatermark.enabled = false;
}
public override void Show()
{
Shown = true;
background.enabled = true;
loadingTitle.enabled = true;
vyapWatermark.enabled = true;
loadingImage.enabled = true;
// loadingTitle.enabled = true;
// vyapWatermark.enabled = true;
}
}
}
@@ -14,6 +14,7 @@ namespace Code.UI
[SerializeField] private Slider master;
[SerializeField] private Slider sfx;
[SerializeField] private Slider dispatcher;
[SerializeField] private Slider courier;
[SerializeField] private Slider creatures;
[SerializeField] private Slider menuMusic;
[SerializeField] private Slider gameplayMusic;
@@ -28,10 +29,13 @@ namespace Code.UI
sfx.value = _audioService.GetSetting(AudioType.SFX);
sfx.onValueChanged.AddListener(OnSFXUpdate);
dispatcher.value = _audioService.GetSetting(AudioType.DispatcherSounds);
dispatcher.value = _audioService.GetSetting(AudioType.Dispatcher);
dispatcher.onValueChanged.AddListener(OnDispatcherUpdate);
creatures.value = _audioService.GetSetting(AudioType.Creatures);
courier.value = _audioService.GetSetting(AudioType.Courier);
courier.onValueChanged.AddListener(OnCourierUpdate);
creatures.value = _audioService.GetSetting(AudioType.Enemies);
creatures.onValueChanged.AddListener(OnEnemiesUpdate);
menuMusic.value = _audioService.GetSetting(AudioType.MenuMusic);
@@ -51,19 +55,25 @@ namespace Code.UI
_audioService.ChangeSetting(AudioType.SFX, value);
_audioService.PlayTestClip(AudioType.SFX);
}
private void OnCourierUpdate(float value)
{
_audioService.ChangeSetting(AudioType.Courier, value);
_audioService.PlayTestClip(AudioType.Courier);
}
private void OnDispatcherUpdate(float value)
{
_audioService.ChangeSetting(AudioType.DispatcherSounds, value);
_audioService.PlayTestClip(AudioType.DispatcherSounds);
_audioService.ChangeSetting(AudioType.Dispatcher, value);
_audioService.PlayTestClip(AudioType.Dispatcher);
}
private void OnEnemiesUpdate(float value)
{
_audioService.ChangeSetting(AudioType.Creatures, value);
_audioService.PlayTestClip(AudioType.Creatures);
_audioService.ChangeSetting(AudioType.Enemies, value);
_audioService.PlayTestClip(AudioType.Enemies);
}
private void OnMenuMusicUpdate(float value)
{
_audioService.ChangeSetting(AudioType.MenuMusic, value);
_audioService.ChangeSetting(AudioType.DeathMusic, value);
_audioService.PlayTestClip(AudioType.MenuMusic);
}
private void OnGameplayUpdate(float value)
@@ -1,6 +1,7 @@
fileFormatVersion: 2
guid: d4eaf1439c2788c458127b9ba67e4fbf
PrefabImporter:
guid: 45b4aa0e7c33e934493bb7d2a15a9add
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 767316a9a37abc34694c3086d846f668
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 43bd94852ddc6b34dbe9fec318fb54d8
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,17 @@
{
"name": "AYellowpaper.SerializedCollections.Editor",
"references": [
"GUID:d525ad6bd40672747bde77962f1c401e"
],
"includePlatforms": [
"Editor"
],
"excludePlatforms": [],
"allowUnsafeCode": false,
"overrideReferences": false,
"precompiledReferences": [],
"autoReferenced": true,
"defineConstraints": [],
"versionDefines": [],
"noEngineReferences": false
}
@@ -0,0 +1,14 @@
fileFormatVersion: 2
guid: 234340c04eed5674a988bc6ebde7d248
AssemblyDefinitionImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
AssetOrigin:
serializedVersion: 1
productId: 243052
packageName: Serialized Dictionary
packageVersion: 1.0.13
assetPath: Assets/Plugins/SerializedCollections/Editor/AYellowpaper.SerializedCollections.Editor.asmdef
uploadId: 632226
@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: edb739dfb1824234681f6480c75cd523
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,177 @@
fileFormatVersion: 2
guid: 8deddfed9f39d7740879d2cb0fcf7ce0
TextureImporter:
internalIDToNameTable: []
externalObjects: {}
serializedVersion: 11
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
streamingMipmaps: 0
streamingMipmapsPriority: 0
vTOnly: 0
ignoreMasterTextureLimit: 0
grayScaleToAlpha: 0
generateCubemap: 6
cubemapConvolution: 0
seamlessCubemap: 0
textureFormat: 1
maxTextureSize: 2048
textureSettings:
serializedVersion: 2
filterMode: 1
aniso: 1
mipBias: 0
wrapU: 1
wrapV: 1
wrapW: 0
nPOTScale: 0
lightmap: 0
compressionQuality: 50
spriteMode: 0
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: 2
textureShape: 1
singleChannelComponent: 0
flipbookRows: 1
flipbookColumns: 1
maxTextureSizeSet: 0
compressionQualitySet: 0
textureFormatSet: 0
ignorePngGamma: 0
applyGammaDecoding: 0
platformSettings:
- serializedVersion: 3
buildTarget: DefaultTexturePlatform
maxTextureSize: 8192
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
- serializedVersion: 3
buildTarget: Standalone
maxTextureSize: 8192
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
- serializedVersion: 3
buildTarget: iPhone
maxTextureSize: 8192
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
- serializedVersion: 3
buildTarget: Android
maxTextureSize: 8192
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
- serializedVersion: 3
buildTarget: Windows Store Apps
maxTextureSize: 8192
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
- serializedVersion: 3
buildTarget: Server
maxTextureSize: 8192
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
- serializedVersion: 3
buildTarget: WebGL
maxTextureSize: 8192
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
spriteSheet:
serializedVersion: 2
sprites: []
outline: []
physicsShape: []
bones: []
spriteID:
internalID: 0
vertices: []
indices:
edges: []
weights: []
secondaryTextures: []
nameFileIdTable: {}
spritePackingTag:
pSDRemoveMatte: 0
pSDShowRemoveMatteOption: 0
userData:
assetBundleName:
assetBundleVariant:
AssetOrigin:
serializedVersion: 1
productId: 243052
packageName: Serialized Dictionary
packageVersion: 1.0.13
assetPath: Assets/Plugins/SerializedCollections/Editor/Assets/BurgerMenu@2x.png
uploadId: 632226
@@ -0,0 +1,110 @@
.sc-close-button {
background-image: resource('d_winbtn_win_close@2x');
width: 16px;
height: 16px;
position: absolute;
right: 2px;
top: 2px;
background-color: rgba(0, 0, 0, 0);
border-left-width: 0;
border-right-width: 0;
border-top-width: 0;
border-bottom-width: 0;
}
.sc-close-button:hover {
background-color: rgba(80, 80, 80, 255);
}
.sc-close-button:active {
background-color: rgba(0, 0, 0, 0);
}
.sc-text-toggle {
margin: 0;
padding: 0;
justify-content: center;
}
.sc-text-toggle:checked {
-unity-font-style: bold;
}
.sc-text-toggle > Label {
min-width: auto;
width: 100%;
height: 100%;
}
.sc-text-toggle > .unity-radio-button__input {
display: none;
}
.sc-title {
background-color: rgba(40, 40, 40, 0.35);
padding-left: 4px;
padding-right: 3px;
padding-top: 3px;
padding-bottom: 3px;
border-left-color: rgb(25, 25, 25);
border-right-color: rgb(25, 25, 25);
border-top-color: rgb(25, 25, 25);
border-bottom-color: rgb(25, 25, 25);
border-bottom-width: 1px;
-unity-font-style: bold;
}
.sc-generator-toggle {
padding-left: 3px;
padding-right: 3px;
padding-top: 3px;
padding-bottom: 3px;
}
.sc-generator-toggle:hover {
background-color: rgb(48, 48, 48);
}
.sc-generator-toggle:checked {
background-color: rgb(77, 77, 77);
}
.sc-modification-toggle {
flex-basis: 100%;
flex-shrink: 1;
border-left-color: rgb(41, 41, 41);
border-right-color: rgb(41, 41, 41);
border-top-color: rgb(41, 41, 41);
border-bottom-color: rgb(41, 41, 41);
border-left-width: 1px;
border-right-width: 1px;
border-top-width: 1px;
border-bottom-width: 1px;
-unity-font-style: normal;
-unity-text-align: middle-center;
padding-left: 2px;
padding-right: 2px;
padding-top: 2px;
padding-bottom: 2px;
}
.sc-modification-toggle:hover {
background-color: rgb(70, 70, 70);
}
.sc-modification-toggle:checked {
background-color: rgb(80, 80, 80);
}
.sc-radio-button-group {
padding: 0;
margin: 0;
}
.sc-radio-button-group > Label {
display: none;
}
#generators-group {
flex-direction: column;
}
@@ -0,0 +1,18 @@
fileFormatVersion: 2
guid: df6c2ef835e40c94c976442569324029
ScriptedImporter:
internalIDToNameTable: []
externalObjects: {}
serializedVersion: 2
userData:
assetBundleName:
assetBundleVariant:
script: {fileID: 12385, guid: 0000000000000000e000000000000000, type: 0}
disableValidation: 0
AssetOrigin:
serializedVersion: 1
productId: 243052
packageName: Serialized Dictionary
packageVersion: 1.0.13
assetPath: Assets/Plugins/SerializedCollections/Editor/Assets/KeysGeneratorSelectorWindow.uss
uploadId: 632226
@@ -0,0 +1,26 @@
<ui:UXML xmlns:ui="UnityEngine.UIElements" xmlns:uie="UnityEditor.UIElements" xsi="http://www.w3.org/2001/XMLSchema-instance" engine="UnityEngine.UIElements" editor="UnityEditor.UIElements" noNamespaceSchemaLocation="../../../../../UIElementsSchema/UIElements.xsd" editor-extension-mode="False">
<Style src="project://database/Assets/Plugins/SerializedCollections/Editor/Assets/KeysGeneratorSelectorWindow.uss?fileID=7433441132597879392&amp;guid=df6c2ef835e40c94c976442569324029&amp;type=3#KeysGeneratorSelectorWindow" />
<ui:VisualElement style="flex-direction: row; flex-grow: 1; border-left-color: rgb(97, 97, 97); border-right-color: rgb(97, 97, 97); border-top-color: rgb(97, 97, 97); border-bottom-color: rgb(97, 97, 97); border-left-width: 2px; border-right-width: 2px; border-top-width: 2px; border-bottom-width: 2px;">
<ui:VisualElement name="LeftContent" style="flex-basis: 66%; border-left-color: rgb(25, 25, 25); border-right-color: rgb(25, 25, 25); border-top-color: rgb(25, 25, 25); border-bottom-color: rgb(25, 25, 25); border-right-width: 1px;">
<ui:Label text="Generators" display-tooltip-when-elided="true" class="sc-title" />
<ui:ScrollView scroll-deceleration-rate="0,135" elasticity="0,1" name="generators-content" style="flex-grow: 1;" />
</ui:VisualElement>
<ui:VisualElement name="RightContent" style="flex-basis: 100%;">
<ui:Label text="Inspector" display-tooltip-when-elided="true" class="sc-title" />
<ui:IMGUIContainer name="imgui-inspector" style="flex-grow: 1; margin-left: 4px; margin-right: 4px; margin-top: 4px; margin-bottom: 4px;" />
<ui:Label text="4 Elements " display-tooltip-when-elided="true" name="generated-count-label" style="padding-left: 2px; padding-right: 2px; padding-top: 2px; padding-bottom: 2px;" />
<ui:VisualElement style="flex-direction: row;">
<ui:RadioButtonGroup label="Radio Button Group" value="-1" name="modification-group" class="sc-radio-button-group" style="flex-grow: 1;">
<ui:RadioButton label="Add" name="add-modification" tooltip="Add the generated missing keys to the target." class="sc-text-toggle sc-modification-toggle" />
<ui:RadioButton label="Remove" name="remove-modification" tooltip="Remove the generated keys form the target." class="sc-text-toggle sc-modification-toggle" />
<ui:RadioButton label="Confine" name="confine-modification" tooltip="Remove all keys that are not part of the generated keys from the target." class="sc-text-toggle sc-modification-toggle" />
</ui:RadioButtonGroup>
</ui:VisualElement>
<ui:VisualElement style="flex-direction: row;">
<ui:Label display-tooltip-when-elided="true" name="result-label" style="flex-grow: 1; -unity-text-align: middle-left; padding-left: 2px; padding-right: 2px; padding-top: 2px; padding-bottom: 2px;" />
<ui:Button text="Apply" display-tooltip-when-elided="true" name="apply-button" style="width: 100px;" />
</ui:VisualElement>
</ui:VisualElement>
<ui:Button display-tooltip-when-elided="true" class="sc-close-button" />
</ui:VisualElement>
</ui:UXML>
@@ -0,0 +1,17 @@
fileFormatVersion: 2
guid: 681c8a924c8b1e14b9fe53bb7397ec3d
ScriptedImporter:
internalIDToNameTable: []
externalObjects: {}
serializedVersion: 2
userData:
assetBundleName:
assetBundleVariant:
script: {fileID: 13804, guid: 0000000000000000e000000000000000, type: 0}
AssetOrigin:
serializedVersion: 1
productId: 243052
packageName: Serialized Dictionary
packageVersion: 1.0.13
assetPath: Assets/Plugins/SerializedCollections/Editor/Assets/KeysGeneratorSelectorWindow.uxml
uploadId: 632226
@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 6398825db0c1d5348b5ec85b0c12d9c0
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 81bf46994f9232b4e8dcf467c109f046
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,23 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
namespace AYellowpaper.SerializedCollections.Editor.Data
{
[System.Serializable]
internal class ElementData
{
[SerializeField]
private bool _isListToggleActive = false;
public ElementSettings Settings { get; }
public bool ShowAsList => Settings.HasListDrawerToggle && IsListToggleActive;
public bool IsListToggleActive { get => _isListToggleActive; set => _isListToggleActive = value; }
public DisplayType EffectiveDisplayType => ShowAsList ? DisplayType.List : Settings.DisplayType;
public ElementData(ElementSettings elementSettings)
{
Settings = elementSettings;
}
}
}
@@ -0,0 +1,18 @@
fileFormatVersion: 2
guid: 650a80186cc93b54aa5627197c23ea6e
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
AssetOrigin:
serializedVersion: 1
productId: 243052
packageName: Serialized Dictionary
packageVersion: 1.0.13
assetPath: Assets/Plugins/SerializedCollections/Editor/Scripts/Data/ElementData.cs
uploadId: 632226
@@ -0,0 +1,15 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
namespace AYellowpaper.SerializedCollections.Editor.Data
{
public class ElementSettings
{
public const string DefaultName = "Not Set";
public string DisplayName { get; set; } = DefaultName;
public DisplayType DisplayType { get; set; } = DisplayType.PropertyNoLabel;
public bool HasListDrawerToggle { get; set; } = false;
}
}
@@ -0,0 +1,18 @@
fileFormatVersion: 2
guid: 12edfc8006691b7498459540b832c5eb
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
AssetOrigin:
serializedVersion: 1
productId: 243052
packageName: Serialized Dictionary
packageVersion: 1.0.13
assetPath: Assets/Plugins/SerializedCollections/Editor/Scripts/Data/ElementSettings.cs
uploadId: 632226
@@ -0,0 +1,44 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
namespace AYellowpaper.SerializedCollections.Editor.Data
{
[System.Serializable]
internal class PropertyData
{
[SerializeField]
private float _keyLabelWidth;
[SerializeField]
private ElementData _keyData;
[SerializeField]
private ElementData _valueData;
[SerializeField]
private bool _alwaysShowSearch = false;
public bool AlwaysShowSearch
{
get => _alwaysShowSearch;
set => _alwaysShowSearch = value;
}
public float KeyLabelWidth
{
get => _keyLabelWidth;
set => _keyLabelWidth = value;
}
public ElementData GetElementData(bool fieldType)
{
return fieldType == SCEditorUtility.KeyFlag ? _keyData : _valueData;
}
public PropertyData() : this(new ElementSettings(), new ElementSettings()) { }
public PropertyData(ElementSettings keySettings, ElementSettings valueSettings)
{
_keyData = new ElementData(keySettings);
_valueData = new ElementData(valueSettings);
}
}
}
@@ -0,0 +1,18 @@
fileFormatVersion: 2
guid: ba2d792dfc6653e46bee7c027202acd3
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
AssetOrigin:
serializedVersion: 1
productId: 243052
packageName: Serialized Dictionary
packageVersion: 1.0.13
assetPath: Assets/Plugins/SerializedCollections/Editor/Scripts/Data/PropertyData.cs
uploadId: 632226
@@ -0,0 +1,13 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
namespace AYellowpaper.SerializedCollections.Editor
{
public enum DisplayType
{
Property,
PropertyNoLabel,
List
}
}
@@ -0,0 +1,18 @@
fileFormatVersion: 2
guid: 37ee13dd67b545846b6b063923812943
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
AssetOrigin:
serializedVersion: 1
productId: 243052
packageName: Serialized Dictionary
packageVersion: 1.0.13
assetPath: Assets/Plugins/SerializedCollections/Editor/Scripts/DisplayType.cs
uploadId: 632226
@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: d74b279cd03ebfb4ca7d2606f3f4f11e
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 10b0c99dadaea0e42b49e323700f2eb9
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,15 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
namespace AYellowpaper.SerializedCollections.KeysGenerators
{
[KeyListGenerator("Populate Enum", typeof(System.Enum), false)]
public class EnumGenerator : KeyListGenerator
{
public override IEnumerable GetKeys(System.Type type)
{
return System.Enum.GetValues(type);
}
}
}
@@ -0,0 +1,18 @@
fileFormatVersion: 2
guid: d639de5d36bbeea4496c97cc3f1f4e81
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
AssetOrigin:
serializedVersion: 1
productId: 243052
packageName: Serialized Dictionary
packageVersion: 1.0.13
assetPath: Assets/Plugins/SerializedCollections/Editor/Scripts/KeyListGenerators/Implementors/EnumGenerator.cs
uploadId: 632226
@@ -0,0 +1,24 @@
using System;
using System.Collections;
using UnityEngine;
namespace AYellowpaper.SerializedCollections.KeysGenerators
{
[KeyListGenerator("Int Range", typeof(int))]
public class IntRangeGenerator : KeyListGenerator
{
[SerializeField]
private int _startValue = 1;
[SerializeField]
private int _endValue = 10;
public override IEnumerable GetKeys(Type type)
{
int dir = Math.Sign(_endValue - _startValue);
dir = dir == 0 ? 1 : dir;
for (int i = _startValue; i != _endValue; i += dir)
yield return i;
yield return _endValue;
}
}
}
@@ -0,0 +1,18 @@
fileFormatVersion: 2
guid: a4203f3a582fa874fb035633bd9892b4
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
AssetOrigin:
serializedVersion: 1
productId: 243052
packageName: Serialized Dictionary
packageVersion: 1.0.13
assetPath: Assets/Plugins/SerializedCollections/Editor/Scripts/KeyListGenerators/Implementors/IntRangeGenerator.cs
uploadId: 632226
@@ -0,0 +1,26 @@
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
namespace AYellowpaper.SerializedCollections.KeysGenerators
{
[KeyListGenerator("Int Stepping", typeof(int))]
public class IntSteppingGenerator : KeyListGenerator
{
[SerializeField]
private int _startIndex = 0;
[SerializeField]
private int _stepDistance = 10;
[SerializeField, Min(0)]
private int _stepCount = 1;
public override IEnumerable GetKeys(Type type)
{
for (int i = 0; i <= _stepCount; i++)
{
yield return _startIndex + i * _stepDistance;
}
}
}
}
@@ -0,0 +1,18 @@
fileFormatVersion: 2
guid: 99302d4ff0ae27b4898ced57890ed32d
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
AssetOrigin:
serializedVersion: 1
productId: 243052
packageName: Serialized Dictionary
packageVersion: 1.0.13
assetPath: Assets/Plugins/SerializedCollections/Editor/Scripts/KeyListGenerators/Implementors/IntSteppingGenerator.cs
uploadId: 632226
@@ -0,0 +1,11 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
namespace AYellowpaper.SerializedCollections.KeysGenerators
{
public abstract class KeyListGenerator : ScriptableObject
{
public abstract IEnumerable GetKeys(System.Type type);
}
}
@@ -0,0 +1,18 @@
fileFormatVersion: 2
guid: 08149f25a1b9c5e48a224a7c4d31a154
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
AssetOrigin:
serializedVersion: 1
productId: 243052
packageName: Serialized Dictionary
packageVersion: 1.0.13
assetPath: Assets/Plugins/SerializedCollections/Editor/Scripts/KeyListGenerators/KeyListGenerator.cs
uploadId: 632226
@@ -0,0 +1,19 @@
using System;
namespace AYellowpaper.SerializedCollections.KeysGenerators
{
[AttributeUsage(AttributeTargets.Class)]
public class KeyListGeneratorAttribute : Attribute
{
public readonly string Name;
public readonly Type TargetType;
public readonly bool NeedsWindow;
public KeyListGeneratorAttribute(string name, Type targetType, bool needsWindow = true)
{
Name = name;
TargetType = targetType;
NeedsWindow = needsWindow;
}
}
}
@@ -0,0 +1,18 @@
fileFormatVersion: 2
guid: 0f6065c936425ab478ecc8a8cf30d38f
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
AssetOrigin:
serializedVersion: 1
productId: 243052
packageName: Serialized Dictionary
packageVersion: 1.0.13
assetPath: Assets/Plugins/SerializedCollections/Editor/Scripts/KeyListGenerators/KeyListGeneratorAttribute.cs
uploadId: 632226
@@ -0,0 +1,36 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using UnityEditor;
using UnityEngine;
namespace AYellowpaper.SerializedCollections.KeysGenerators
{
public static class KeyListGeneratorCache
{
private static List<KeyListGeneratorData> _populators;
private static Dictionary<Type, List<KeyListGeneratorData>> _populatorsByType;
static KeyListGeneratorCache()
{
_populators = new List<KeyListGeneratorData>();
_populatorsByType = new Dictionary<Type, List<KeyListGeneratorData>>();
var populatorTypes = TypeCache.GetTypesDerivedFrom<KeyListGenerator>();
foreach (var populatorType in populatorTypes.Where(x => !x.IsAbstract))
{
var attributes = populatorType.GetCustomAttributes<KeyListGeneratorAttribute>();
foreach (var attribute in attributes)
_populators.Add(new KeyListGeneratorData(attribute.Name, attribute.TargetType, populatorType, attribute.NeedsWindow));
}
}
public static IReadOnlyList<KeyListGeneratorData> GetPopulatorsForType(Type type)
{
if (!_populatorsByType.ContainsKey(type))
_populatorsByType.Add(type, new List<KeyListGeneratorData>(_populators.Where(x => x.TargetType.IsAssignableFrom(type))));
return _populatorsByType[type];
}
}
}
@@ -0,0 +1,18 @@
fileFormatVersion: 2
guid: 7936217ae19613d4bb5e46e73a4a587c
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
AssetOrigin:
serializedVersion: 1
productId: 243052
packageName: Serialized Dictionary
packageVersion: 1.0.13
assetPath: Assets/Plugins/SerializedCollections/Editor/Scripts/KeyListGenerators/KeyListGeneratorCache.cs
uploadId: 632226
@@ -0,0 +1,20 @@
using System;
namespace AYellowpaper.SerializedCollections.KeysGenerators
{
public class KeyListGeneratorData
{
public string Name { get; set; }
public Type TargetType { get; set; }
public Type GeneratorType { get; set; }
public bool NeedsWindow { get; set; }
public KeyListGeneratorData(string name, Type targetType, Type populatorType, bool needsWindow)
{
Name = name;
TargetType = targetType;
GeneratorType = populatorType;
NeedsWindow = needsWindow;
}
}
}
@@ -0,0 +1,18 @@
fileFormatVersion: 2
guid: 8992145ced672cd46a425fb2590b80bb
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
AssetOrigin:
serializedVersion: 1
productId: 243052
packageName: Serialized Dictionary
packageVersion: 1.0.13
assetPath: Assets/Plugins/SerializedCollections/Editor/Scripts/KeyListGenerators/KeyListGeneratorData.cs
uploadId: 632226
@@ -0,0 +1,26 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;
namespace AYellowpaper.SerializedCollections.KeysGenerators
{
[CustomEditor(typeof(KeyListGenerator), true)]
public class KeyListGeneratorEditor : UnityEditor.Editor
{
public override void OnInspectorGUI()
{
var iterator = serializedObject.GetIterator();
if (iterator.Next(true))
{
// skip script name
iterator.NextVisible(true);
while (iterator.NextVisible(true))
{
EditorGUILayout.PropertyField(iterator);
}
}
serializedObject.ApplyModifiedProperties();
}
}
}
@@ -0,0 +1,18 @@
fileFormatVersion: 2
guid: 211518bea98ede643af247b6295984bd
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
AssetOrigin:
serializedVersion: 1
productId: 243052
packageName: Serialized Dictionary
packageVersion: 1.0.13
assetPath: Assets/Plugins/SerializedCollections/Editor/Scripts/KeyListGenerators/KeyListGeneratorEditor.cs
uploadId: 632226
@@ -0,0 +1,182 @@
using System;
using System.Collections.Generic;
using UnityEditor;
using UnityEngine;
using UnityEngine.UIElements;
namespace AYellowpaper.SerializedCollections.KeysGenerators
{
public class KeyListGeneratorSelectorWindow : EditorWindow
{
[SerializeField]
private int _selectedIndex;
[SerializeField]
private ModificationType _modificationType;
private KeyListGenerator _generator;
private UnityEditor.Editor _editor;
private List<KeyListGeneratorData> _generatorsData;
private Type _targetType;
private int _undoStart;
private Dictionary<Type, KeyListGenerator> _keysGenerators = new Dictionary<Type, KeyListGenerator>();
private string _detailsText;
public event Action<KeyListGenerator, ModificationType> OnApply;
private void OnEnable()
{
VisualTreeAsset document = AssetDatabase.LoadAssetAtPath<VisualTreeAsset>("Assets/Plugins/SerializedCollections/Editor/Assets/KeysGeneratorSelectorWindow.uxml");
var element = document.CloneTree();
element.style.height = new StyleLength(new Length(100, LengthUnit.Percent));
rootVisualElement.Add(element);
}
public void Initialize(IEnumerable<KeyListGeneratorData> generatorsData, Type type)
{
_targetType = type;
_selectedIndex = 0;
_modificationType = ModificationType.Add;
_undoStart = Undo.GetCurrentGroup();
_generatorsData = new List<KeyListGeneratorData>(generatorsData);
SetGeneratorIndex(0);
Undo.undoRedoPerformed += HandleUndoCallback;
rootVisualElement.Q<Button>(className: "sc-close-button").clicked += Close;
rootVisualElement.Q<RadioButton>(name = "add-modification").userData = ModificationType.Add;
rootVisualElement.Q<RadioButton>(name = "remove-modification").userData = ModificationType.Remove;
rootVisualElement.Q<RadioButton>(name = "confine-modification").userData = ModificationType.Confine;
var modificationToggles = rootVisualElement.Query<RadioButton>(className: "sc-modification-toggle");
modificationToggles.ForEach(InitializeModificationToggle);
rootVisualElement.Q<IMGUIContainer>(name = "imgui-inspector").onGUIHandler = EditorGUIHandler;
rootVisualElement.Q<Button>(name = "apply-button").clicked += ApplyButtonClicked;
var generatorsContent = rootVisualElement.Q<ScrollView>(name = "generators-content");
var radioButtonGroup = new RadioButtonGroup();
radioButtonGroup.name = "generators-group";
radioButtonGroup.AddToClassList("sc-radio-button-group");
generatorsContent.Add(radioButtonGroup);
for (int i = 0; i < _generatorsData.Count; i++)
{
var generatorData = _generatorsData[i];
var radioButton = new RadioButton(generatorData.Name);
radioButton.value = i == 0;
radioButton.AddToClassList("sc-text-toggle");
radioButton.AddToClassList("sc-generator-toggle");
radioButton.userData = i;
radioButton.RegisterValueChangedCallback(OnGeneratorClicked);
radioButtonGroup.Add(radioButton);
}
}
private void ApplyButtonClicked()
{
OnApply?.Invoke(_editor.target as KeyListGenerator, _modificationType);
OnApply = null;
Close();
}
private void EditorGUIHandler()
{
EditorGUI.BeginChangeCheck();
_editor.OnInspectorGUI();
if (EditorGUI.EndChangeCheck())
{
UpdateDetailsText();
}
}
private void InitializeModificationToggle(RadioButton obj)
{
if ((ModificationType)obj.userData == _modificationType)
obj.value = true;
obj.RegisterValueChangedCallback(OnModificationToggleClicked);
}
private void OnModificationToggleClicked(ChangeEvent<bool> evt)
{
if (!evt.newValue)
return;
var modificationType = (ModificationType)((VisualElement)evt.target).userData;
_modificationType = modificationType;
}
private void UpdateDetailsText()
{
var enumerable = _generator.GetKeys(_targetType);
int count = 0;
var enumerator = enumerable.GetEnumerator();
while (enumerator.MoveNext())
{
count++;
if (count > 100)
{
_detailsText = "over 100 Elements";
return;
}
}
_detailsText = $"{count} Elements";
rootVisualElement.Q<Label>(name = "generated-count-label").text = _detailsText;
}
private void OnDestroy()
{
Undo.undoRedoPerformed -= HandleUndoCallback;
Undo.RevertAllDownToGroup(_undoStart);
foreach (var keyGenerator in _keysGenerators)
DestroyImmediate(keyGenerator.Value);
}
private void OnGeneratorClicked(ChangeEvent<bool> evt)
{
if (!evt.newValue)
return;
SetGeneratorIndex((int)(evt.target as VisualElement).userData);
}
private void HandleUndoCallback()
{
UpdateGeneratorAndEditorIfNeeded();
Repaint();
}
private void SetGeneratorIndex(int index)
{
Undo.RecordObject(this, "Change Window");
_selectedIndex = index;
UpdateGeneratorAndEditorIfNeeded();
}
private void UpdateGeneratorAndEditorIfNeeded()
{
var targetType = _generatorsData[_selectedIndex].GeneratorType;
if (_generator != null && _generator.GetType() == targetType)
return;
_generator = GetOrCreateKeysGenerator(targetType);
if (_editor != null)
DestroyImmediate(_editor);
_editor = UnityEditor.Editor.CreateEditor(_generator);
UpdateDetailsText();
}
private KeyListGenerator GetOrCreateKeysGenerator(Type type)
{
if (!_keysGenerators.ContainsKey(type))
{
var so = (KeyListGenerator)CreateInstance(type);
so.hideFlags = HideFlags.DontSave;
_keysGenerators.Add(type, so);
}
return _keysGenerators[type];
}
}
}
@@ -0,0 +1,18 @@
fileFormatVersion: 2
guid: df07fe6d161e3334083f837a066dd949
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
AssetOrigin:
serializedVersion: 1
productId: 243052
packageName: Serialized Dictionary
packageVersion: 1.0.13
assetPath: Assets/Plugins/SerializedCollections/Editor/Scripts/KeyListGenerators/KeyListGeneratorSelectorWindow.cs
uploadId: 632226
@@ -0,0 +1,10 @@
namespace AYellowpaper.SerializedCollections
{
public enum ModificationType
{
None,
Add,
Remove,
Confine,
}
}
@@ -0,0 +1,18 @@
fileFormatVersion: 2
guid: fc2030edc0a04b74a8642773bd8c98fd
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
AssetOrigin:
serializedVersion: 1
productId: 243052
packageName: Serialized Dictionary
packageVersion: 1.0.13
assetPath: Assets/Plugins/SerializedCollections/Editor/Scripts/KeyListGenerators/ModificationType.cs
uploadId: 632226
@@ -0,0 +1,68 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;
namespace AYellowpaper.SerializedCollections.Editor
{
public class PagingElement
{
public int Page
{
get => _page;
set
{
_page = value;
EnsureValidPageIndex();
}
}
public int PageCount
{
get => _pageCount;
set
{
Debug.Assert(value >= 1, $"{nameof(PageCount)} needs to be 1 or larger but is {value}.");
_pageCount = value;
EnsureValidPageIndex();
}
}
private const int buttonWidth = 20;
private const int inputWidth = 20;
private const int labelWidth = 30;
private int _page = 1;
private int _pageCount = 1;
public PagingElement(int pageCount = 1)
{
PageCount = pageCount;
}
public float GetDesiredWidth()
{
return buttonWidth * 2 + inputWidth + labelWidth;
}
public void OnGUI(Rect rect)
{
Rect leftButton = rect.WithXAndWidth(rect.x, buttonWidth);
Rect inputRect = leftButton.AppendRight(inputWidth);
Rect labelRect = inputRect.AppendRight(labelWidth);
Rect rightButton = labelRect.AppendRight(buttonWidth);
using (new GUIEnabledScope(Page != 1))
if (GUI.Button(leftButton, "<"))
Page--;
using (new GUIEnabledScope(Page != PageCount))
if (GUI.Button(rightButton, ">"))
Page++;
Page = EditorGUI.IntField(inputRect, Page);
GUI.Label(labelRect, "/" + PageCount.ToString());
}
private void EnsureValidPageIndex()
{
_page = Mathf.Clamp(_page, 1, PageCount);
}
}
}
@@ -0,0 +1,18 @@
fileFormatVersion: 2
guid: f35ac465aece4064582910fc2c206682
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
AssetOrigin:
serializedVersion: 1
productId: 243052
packageName: Serialized Dictionary
packageVersion: 1.0.13
assetPath: Assets/Plugins/SerializedCollections/Editor/Scripts/PagingElement.cs
uploadId: 632226
@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: bead4ae311155bd46af1e99788f1d932
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 77b8ccff4f0c60943b9a54ce8d698d7f
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,21 @@
using System;
using UnityEditor;
namespace AYellowpaper.SerializedCollections.Editor.Search
{
public class EnumMatcher : Matcher
{
public override bool IsMatch(SerializedProperty property)
{
if (property.propertyType == SerializedPropertyType.Enum && SCEditorUtility.TryGetTypeFromProperty(property, out var type))
{
foreach (var text in SCEnumUtility.GetEnumCache(type).GetNamesForValue(property.enumValueFlag))
{
if (text.Contains(SearchString, StringComparison.OrdinalIgnoreCase))
return true;
}
}
return false;
}
}
}
@@ -0,0 +1,18 @@
fileFormatVersion: 2
guid: f2cf86e71fb0ff04f96ac71dd9961962
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
AssetOrigin:
serializedVersion: 1
productId: 243052
packageName: Serialized Dictionary
packageVersion: 1.0.13
assetPath: Assets/Plugins/SerializedCollections/Editor/Scripts/Search/Matchers/EnumMatcher.cs
uploadId: 632226
@@ -0,0 +1,20 @@
using UnityEditor;
namespace AYellowpaper.SerializedCollections.Editor.Search
{
public abstract class Matcher
{
public string SearchString { get; private set; }
public void Prepare(string searchString)
{
SearchString = ProcessSearchString(searchString);
}
public virtual string ProcessSearchString(string searchString)
{
return searchString;
}
public abstract bool IsMatch(SerializedProperty property);
}
}
@@ -0,0 +1,18 @@
fileFormatVersion: 2
guid: 218ea85e2d8480a498e8647aad524c8d
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
AssetOrigin:
serializedVersion: 1
productId: 243052
packageName: Serialized Dictionary
packageVersion: 1.0.13
assetPath: Assets/Plugins/SerializedCollections/Editor/Scripts/Search/Matchers/Matcher.cs
uploadId: 632226
@@ -0,0 +1,30 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
namespace AYellowpaper.SerializedCollections.Editor.Search
{
public static class Matchers
{
public static IEnumerable<Matcher> RegisteredMatchers => _registeredMatchers;
private static List<Matcher> _registeredMatchers = new List<Matcher>();
static Matchers()
{
_registeredMatchers.Add(new NumericMatcher());
_registeredMatchers.Add(new StringMatcher());
_registeredMatchers.Add(new EnumMatcher());
}
public static void AddMatcher(Matcher matcher)
{
_registeredMatchers.Add(matcher);
}
public static bool RemoveMatcher(Matcher matcher)
{
return _registeredMatchers.Remove(matcher);
}
}
}
@@ -0,0 +1,18 @@
fileFormatVersion: 2
guid: 94535827bd107e549baa23442df58bef
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
AssetOrigin:
serializedVersion: 1
productId: 243052
packageName: Serialized Dictionary
packageVersion: 1.0.13
assetPath: Assets/Plugins/SerializedCollections/Editor/Scripts/Search/Matchers/Matchers.cs
uploadId: 632226
@@ -0,0 +1,109 @@
using System.Globalization;
using UnityEditor;
using UnityEngine;
namespace AYellowpaper.SerializedCollections.Editor.Search
{
public class NumericMatcher : Matcher
{
public override string ProcessSearchString(string searchString)
{
return searchString.Replace(',', '.');
}
public override bool IsMatch(SerializedProperty property)
{
if (property.propertyType == SerializedPropertyType.Float)
{
return IsFloatMatch(property.floatValue);
}
else if (property.propertyType == SerializedPropertyType.Integer)
{
return IsIntMatch(property.intValue);
}
else if (property.propertyType == SerializedPropertyType.Quaternion)
{
var quat = property.quaternionValue;
return IsFloatMatch(quat.x) || IsFloatMatch(quat.y) || IsFloatMatch(quat.z) || IsFloatMatch(quat.w);
}
else if (property.propertyType == SerializedPropertyType.Bounds)
{
var bounds = property.boundsValue;
return IsVector3Match(bounds.center) || IsVector3Match(bounds.size);
}
else if (property.propertyType == SerializedPropertyType.BoundsInt)
{
var bounds = property.boundsIntValue;
return IsVector3Match(bounds.center) || IsVector3IntMatch(bounds.size);
}
else if (property.propertyType == SerializedPropertyType.Rect)
{
var rect = property.rectValue;
return IsVector2Match(rect.size) || IsVector2Match(rect.position);
}
else if (property.propertyType == SerializedPropertyType.RectInt)
{
var rect = property.rectIntValue;
return IsVector2IntMatch(rect.size) || IsVector2IntMatch(rect.position);
}
else if (property.propertyType == SerializedPropertyType.Vector2)
{
return IsVector2Match(property.vector2Value);
}
else if (property.propertyType == SerializedPropertyType.Vector2Int)
{
return IsVector2IntMatch(property.vector2IntValue);
}
else if (property.propertyType == SerializedPropertyType.Vector3)
{
return IsVector3Match(property.vector3Value);
}
else if (property.propertyType == SerializedPropertyType.Vector3Int)
{
return IsVector3IntMatch(property.vector3IntValue);
}
else if (property.propertyType == SerializedPropertyType.Vector4)
{
return IsVector4Match(property.vector4Value);
}
return false;
}
private bool IsFloatMatch(float val)
{
var str = val.ToString(CultureInfo.InvariantCulture);
return str.Contains(SearchString, System.StringComparison.OrdinalIgnoreCase);
}
private bool IsIntMatch(int val)
{
var str = val.ToString(CultureInfo.InvariantCulture);
return str.Contains(SearchString, System.StringComparison.OrdinalIgnoreCase);
}
private bool IsVector2Match(Vector2 vector)
{
return IsFloatMatch(vector.x) || IsFloatMatch(vector.y);
}
private bool IsVector2IntMatch(Vector2Int vector)
{
return IsIntMatch(vector.x) || IsIntMatch(vector.y);
}
private bool IsVector3Match(Vector3 vector)
{
return IsFloatMatch(vector.x) || IsFloatMatch(vector.y) || IsFloatMatch(vector.z);
}
private bool IsVector3IntMatch(Vector3Int vector)
{
return IsIntMatch(vector.x) || IsIntMatch(vector.y) || IsIntMatch(vector.z);
}
private bool IsVector4Match(Vector4 vector)
{
return IsFloatMatch(vector.x) || IsFloatMatch(vector.y) || IsFloatMatch(vector.z) || IsFloatMatch(vector.w);
}
}
}
@@ -0,0 +1,18 @@
fileFormatVersion: 2
guid: cc3ee6ec420212140bd3a86688d548de
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
AssetOrigin:
serializedVersion: 1
productId: 243052
packageName: Serialized Dictionary
packageVersion: 1.0.13
assetPath: Assets/Plugins/SerializedCollections/Editor/Scripts/Search/Matchers/NumericMatcher.cs
uploadId: 632226
@@ -0,0 +1,15 @@
using System.Globalization;
using UnityEditor;
namespace AYellowpaper.SerializedCollections.Editor.Search
{
public class StringMatcher : Matcher
{
public override bool IsMatch(SerializedProperty property)
{
if ((property.propertyType is SerializedPropertyType.String or SerializedPropertyType.Character) && property.stringValue.Contains(SearchString, System.StringComparison.OrdinalIgnoreCase))
return true;
return false;
}
}
}
@@ -0,0 +1,18 @@
fileFormatVersion: 2
guid: be8bbc3471f8ad04b8da6366285443c6
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
AssetOrigin:
serializedVersion: 1
productId: 243052
packageName: Serialized Dictionary
packageVersion: 1.0.13
assetPath: Assets/Plugins/SerializedCollections/Editor/Scripts/Search/Matchers/StringMatcher.cs
uploadId: 632226
@@ -0,0 +1,22 @@
using System.Collections;
using System.Collections.Generic;
using UnityEditor;
using UnityEngine;
namespace AYellowpaper.SerializedCollections.Editor.Search
{
public class PropertySearchResult
{
public SerializedProperty Property;
public PropertySearchResult(SerializedProperty property)
{
Property = property;
}
public override string ToString()
{
return $"Found match in in {Property.propertyPath}";
}
}
}
@@ -0,0 +1,18 @@
fileFormatVersion: 2
guid: 33b4e4c67054c4d488fa66ff14bd3120
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
AssetOrigin:
serializedVersion: 1
productId: 243052
packageName: Serialized Dictionary
packageVersion: 1.0.13
assetPath: Assets/Plugins/SerializedCollections/Editor/Scripts/Search/PropertySearchResult.cs
uploadId: 632226
@@ -0,0 +1,66 @@
using System.Collections.Generic;
using UnityEditor;
namespace AYellowpaper.SerializedCollections.Editor.Search
{
public class SearchQuery
{
public string SearchString
{
get => _text;
set
{
if (_text == value)
return;
_text = value;
foreach (var matcher in _matchers)
matcher.Prepare(_text);
}
}
private IEnumerable<Matcher> _matchers;
private string _text;
public SearchQuery(IEnumerable<Matcher> matchers)
{
_matchers = matchers;
}
public List<PropertySearchResult> ApplyToProperty(SerializedProperty property)
{
TryGetMatchingProperties(property.Copy(), out var properties);
return properties;
}
public IEnumerable<SearchResultEntry> ApplyToArrayProperty(SerializedProperty property)
{
int arrayCount = property.arraySize;
for (int i = 0; i < arrayCount; i++)
{
var prop = property.GetArrayElementAtIndex(i);
if (TryGetMatchingProperties(prop.Copy(), out var properties))
yield return new SearchResultEntry(i, prop, properties);
}
}
private bool TryGetMatchingProperties(SerializedProperty property, out List<PropertySearchResult> matchingProperties)
{
matchingProperties = null;
foreach (var child in SCEditorUtility.GetChildren(property, true))
{
foreach (var matcher in _matchers)
{
if (matcher.IsMatch(child))
{
if (matchingProperties == null)
matchingProperties = new();
matchingProperties.Add(new PropertySearchResult(child.Copy()));
}
}
}
return matchingProperties != null;
}
}
}
@@ -0,0 +1,18 @@
fileFormatVersion: 2
guid: c87dd0caf3c44ed4e82896aa40bf1b96
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
AssetOrigin:
serializedVersion: 1
productId: 243052
packageName: Serialized Dictionary
packageVersion: 1.0.13
assetPath: Assets/Plugins/SerializedCollections/Editor/Scripts/Search/SearchQuery.cs
uploadId: 632226
@@ -0,0 +1,31 @@
using System.Collections;
using System.Collections.Generic;
using System.Text;
using UnityEditor;
using UnityEngine;
namespace AYellowpaper.SerializedCollections.Editor.Search
{
public class SearchResultEntry
{
public readonly int Index;
public readonly SerializedProperty Property;
public readonly IEnumerable<PropertySearchResult> MatchingResults;
public SearchResultEntry(int index, SerializedProperty property, IEnumerable<PropertySearchResult> matchingResults)
{
Index = index;
Property = property;
MatchingResults = matchingResults;
}
public override string ToString()
{
StringBuilder sb = new StringBuilder();
sb.AppendLine($"{Index}: {Property.propertyPath}");
foreach (var matchingResult in MatchingResults)
sb.AppendLine(matchingResult.ToString());
return sb.ToString();
}
}
}
@@ -0,0 +1,18 @@
fileFormatVersion: 2
guid: d8455216ad2701d49b6dfec7f98ca88b
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
AssetOrigin:
serializedVersion: 1
productId: 243052
packageName: Serialized Dictionary
packageVersion: 1.0.13
assetPath: Assets/Plugins/SerializedCollections/Editor/Scripts/Search/SearchResultEntry.cs
uploadId: 632226
@@ -0,0 +1,65 @@
using AYellowpaper.SerializedCollections.Editor.Data;
using AYellowpaper.SerializedCollections.Editor.States;
using AYellowpaper.SerializedCollections.KeysGenerators;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using UnityEditor;
using UnityEditor.IMGUI.Controls;
using UnityEditorInternal;
using UnityEngine;
namespace AYellowpaper.SerializedCollections.Editor
{
#if ODIN_INSPECTOR
[Sirenix.OdinInspector.Editor.DrawerPriority(Sirenix.OdinInspector.Editor.DrawerPriorityLevel.SuperPriority)]
#endif
[CustomPropertyDrawer(typeof(SerializedDictionary<,>), true)]
public class SerializedDictionaryDrawer : PropertyDrawer
{
public const string KeyName = nameof(SerializedKeyValuePair<int, int>.Key);
public const string ValueName = nameof(SerializedKeyValuePair<int, int>.Value);
public const string SerializedListName = nameof(SerializedDictionary<int, int>._serializedList);
public const string LookupTableName = nameof(SerializedDictionary<int, int>.LookupTable);
public const int TopHeaderClipHeight = 20;
public const int TopHeaderHeight = 19;
public const int SearchHeaderHeight = 20;
public const int KeyValueHeaderHeight = 18;
public const bool KeyFlag = true;
public const bool ValueFlag = false;
public static readonly Color BorderColor = new Color(36 / 255f, 36 / 255f, 36 / 255f);
public static readonly List<int> NoEntriesList = new List<int>();
internal static GUIContent DisplayTypeToggleContent
{
get
{
if (_displayTypeToggleContent == null)
{
var texture = AssetDatabase.LoadAssetAtPath<Texture>("Assets/Plugins/SerializedCollections/Editor/Assets/BurgerMenu@2x.png");
_displayTypeToggleContent = new GUIContent(texture, "Toggle to either draw existing editor or draw properties manually.");
}
return _displayTypeToggleContent;
}
}
private static GUIContent _displayTypeToggleContent;
private Dictionary<string, SerializedDictionaryInstanceDrawer> _arrayData = new();
public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
{
if (!_arrayData.ContainsKey(property.propertyPath))
_arrayData.Add(property.propertyPath, new SerializedDictionaryInstanceDrawer(property, fieldInfo));
_arrayData[property.propertyPath].OnGUI(position, label);
}
public override float GetPropertyHeight(SerializedProperty property, GUIContent label)
{
if (!_arrayData.ContainsKey(property.propertyPath))
_arrayData.Add(property.propertyPath, new SerializedDictionaryInstanceDrawer(property, fieldInfo));
return _arrayData[property.propertyPath].GetPropertyHeight(label);
}
}
}
@@ -0,0 +1,18 @@
fileFormatVersion: 2
guid: 4ccfc6d910f95ca4f94b294a9a3a8872
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
AssetOrigin:
serializedVersion: 1
productId: 243052
packageName: Serialized Dictionary
packageVersion: 1.0.13
assetPath: Assets/Plugins/SerializedCollections/Editor/Scripts/SerializedDictionaryDrawer.cs
uploadId: 632226
@@ -0,0 +1,728 @@
using AYellowpaper.SerializedCollections.Editor.Data;
using AYellowpaper.SerializedCollections.Editor.States;
using AYellowpaper.SerializedCollections.KeysGenerators;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using UnityEditor;
using UnityEditor.IMGUI.Controls;
using UnityEditorInternal;
using UnityEngine;
namespace AYellowpaper.SerializedCollections.Editor
{
public class SerializedDictionaryInstanceDrawer
{
private const float MinKeyValueLabelWidth = 40f;
private FieldInfo _fieldInfo;
private ReorderableList _unexpandedList;
private SingleEditingData _singleEditingData;
private FieldInfo _keyFieldInfo;
private GUIContent _label;
private Rect _totalRect;
private GUIStyle _keyValueStyle;
private SerializedDictionaryAttribute _dictionaryAttribute;
private PropertyData _propertyData;
private bool _propertyListSettingsInitialized = false;
private List<int> _pagedIndices;
private PagingElement _pagingElement;
private int _lastListSize = -1;
private IReadOnlyList<KeyListGeneratorData> _keyGeneratorsWithoutWindow;
private IReadOnlyList<KeyListGeneratorData> _keyGeneratorsWithWindow;
private SearchField _searchField;
private GUIContent _shortDetailsContent;
private GUIContent _detailsContent;
private bool _showSearchBar = false;
private ListState _activeState;
internal ReorderableList ReorderableList { get; private set; }
internal SerializedProperty ListProperty { get; private set; }
internal string SearchText { get; private set; } = string.Empty;
internal SearchListState SearchState { get; private set; }
internal DefaultListState DefaultState { get; private set; }
private class SingleEditingData
{
public bool IsValid => LookupTable != null;
public IKeyable LookupTable;
public void Invalidate()
{
LookupTable = null;
}
}
public SerializedDictionaryInstanceDrawer(SerializedProperty property, FieldInfo fieldInfo)
{
_fieldInfo = fieldInfo;
ListProperty = property.FindPropertyRelative(SerializedDictionaryDrawer.SerializedListName);
_keyValueStyle = new GUIStyle(EditorStyles.toolbarButton);
_keyValueStyle.padding = new RectOffset(0, 0, 0, 0);
_keyValueStyle.border = new RectOffset(0, 0, 0, 0);
_keyValueStyle.alignment = TextAnchor.MiddleCenter;
DefaultState = new DefaultListState(this);
SearchState = new SearchListState(this);
_activeState = DefaultState;
_dictionaryAttribute = _fieldInfo.GetCustomAttribute<SerializedDictionaryAttribute>();
_propertyData = SCEditorUtility.GetPropertyData(ListProperty);
_propertyData.GetElementData(SCEditorUtility.KeyFlag).Settings.DisplayName = _dictionaryAttribute?.KeyName ?? "Key";
_propertyData.GetElementData(SCEditorUtility.ValueFlag).Settings.DisplayName = _dictionaryAttribute?.ValueName ?? "Value";
SavePropertyData();
_pagingElement = new PagingElement();
_pagedIndices = new List<int>();
UpdatePaging();
ReorderableList = MakeList();
_unexpandedList = MakeUnexpandedList();
_searchField = new SearchField();
var listField = _fieldInfo.FieldType.GetField(SerializedDictionaryDrawer.SerializedListName, BindingFlags.Instance | BindingFlags.NonPublic);
var entryType = listField.FieldType.GetGenericArguments()[0];
_keyFieldInfo = entryType.GetField(SerializedDictionaryDrawer.KeyName);
_singleEditingData = new SingleEditingData();
var keyGenerators = KeyListGeneratorCache.GetPopulatorsForType(_keyFieldInfo.FieldType);
_keyGeneratorsWithWindow = keyGenerators.Where(x => x.NeedsWindow).ToList();
_keyGeneratorsWithoutWindow = keyGenerators.Where(x => !x.NeedsWindow).ToList();
UpdateAfterInput();
}
public void OnGUI(Rect position, GUIContent label)
{
_totalRect = position;
_label = new GUIContent(label);
EditorGUI.BeginChangeCheck();
DoList(position);
if (EditorGUI.EndChangeCheck())
{
ListProperty.serializedObject.ApplyModifiedProperties();
}
}
public float GetPropertyHeight(GUIContent label)
{
if (!ListProperty.isExpanded)
return SerializedDictionaryDrawer.TopHeaderClipHeight;
return ReorderableList.GetHeight();
}
private void DoList(Rect position)
{
if (ListProperty.isExpanded)
ReorderableList.DoList(position);
else
{
using (new GUI.ClipScope(new Rect(0, position.y, position.width + position.x, SerializedDictionaryDrawer.TopHeaderClipHeight)))
{
_unexpandedList.DoList(position.WithY(0));
}
}
}
private void ProcessState()
{
var newState = _activeState.OnUpdate();
if (newState != null && newState != _activeState)
{
_activeState.OnExit();
_activeState = newState;
newState.OnEnter();
}
}
private SerializedProperty GetElementProperty(SerializedProperty property, bool fieldFlag)
{
return property.FindPropertyRelative(fieldFlag == SerializedDictionaryDrawer.KeyFlag ? SerializedDictionaryDrawer.KeyName : SerializedDictionaryDrawer.ValueName);
}
internal static float CalculateHeightOfElement(SerializedProperty property, bool drawKeyAsList, bool drawValueAsList)
{
SerializedProperty keyProperty = property.FindPropertyRelative(SerializedDictionaryDrawer.KeyName);
SerializedProperty valueProperty = property.FindPropertyRelative(SerializedDictionaryDrawer.ValueName);
return Mathf.Max(SCEditorUtility.CalculateHeight(keyProperty, drawKeyAsList), SCEditorUtility.CalculateHeight(valueProperty, drawValueAsList));
}
private void UpdateAfterInput()
{
InitializeSettingsIfNeeded();
ProcessState();
CheckIfNewDictionary();
CheckPaging();
var elementsPerPage = EditorUserSettings.Get().ElementsPerPage;
int pageCount = Mathf.Max(1, Mathf.CeilToInt((float)DefaultState.ListSize / elementsPerPage));
ToggleSearchBar(_propertyData.AlwaysShowSearch ? true : SCEditorUtility.ShouldShowSearch(pageCount));
}
// TODO: This works for now, but isn't perfect. This checks if the serialized dictionary was reassigned with new(), simply by comparing the count. Should be instead done by reference equality in the future
private void CheckIfNewDictionary()
{
if (_singleEditingData.IsValid && _singleEditingData.LookupTable.GetCount() != _activeState.ListSize)
{
var dictionary = SCEditorUtility.GetPropertyValue(ListProperty, ListProperty.serializedObject.targetObject);
_singleEditingData.LookupTable = GetLookupTable(dictionary);
_singleEditingData.LookupTable.RecalculateOccurences();
}
}
private void InitializeSettingsIfNeeded()
{
void InitializeSettings(bool fieldFlag)
{
var dictionaryType = FindGenericBaseType(typeof(SerializedDictionary<,>), _fieldInfo.FieldType);
var genericArgs = dictionaryType.GetGenericArguments();
var firstProperty = ListProperty.GetArrayElementAtIndex(0);
var keySettings = CreateDisplaySettings(GetElementProperty(firstProperty, fieldFlag), genericArgs[fieldFlag == SCEditorUtility.KeyFlag ? 0 : 1]);
var settings = _propertyData.GetElementData(fieldFlag).Settings;
settings.DisplayType = keySettings.displayType;
settings.HasListDrawerToggle = keySettings.canToggleListDrawer;
}
if (!_propertyListSettingsInitialized && ListProperty.minArraySize > 0)
{
_propertyListSettingsInitialized = true;
InitializeSettings(SCEditorUtility.KeyFlag);
InitializeSettings(SCEditorUtility.ValueFlag);
SavePropertyData();
}
}
private static Type FindGenericBaseType(Type generic, Type toCheck)
{
while (toCheck != null && toCheck != typeof(object))
{
var cur = toCheck.IsGenericType ? toCheck.GetGenericTypeDefinition() : toCheck;
if (generic == cur) {
return toCheck;
}
toCheck = toCheck.BaseType;
}
return null;
}
private void CheckPaging()
{
// TODO: Is there a better solution to check for Revert/delete/add?
if (_lastListSize != _activeState.ListSize)
{
_lastListSize = _activeState.ListSize;
UpdateSingleEditing();
UpdatePaging();
}
}
private void SavePropertyData()
{
SCEditorUtility.SavePropertyData(ListProperty, _propertyData);
}
private void UpdateSingleEditing()
{
if (ListProperty.serializedObject.isEditingMultipleObjects && _singleEditingData.IsValid)
_singleEditingData.Invalidate();
else if (!ListProperty.serializedObject.isEditingMultipleObjects && !_singleEditingData.IsValid)
{
var dictionary = SCEditorUtility.GetPropertyValue(ListProperty, ListProperty.serializedObject.targetObject);
_singleEditingData.LookupTable = GetLookupTable(dictionary);
}
}
private IKeyable GetLookupTable(object dictionary)
{
var propInfo = dictionary.GetType().GetProperty(SerializedDictionaryDrawer.LookupTableName, BindingFlags.Instance | BindingFlags.NonPublic);
return (IKeyable)propInfo.GetValue(dictionary);
}
private void UpdatePaging()
{
var elementsPerPage = EditorUserSettings.Get().ElementsPerPage;
_pagingElement.PageCount = Mathf.Max(1, Mathf.CeilToInt((float)_activeState.ListSize / elementsPerPage));
_pagedIndices.Clear();
_pagedIndices.Capacity = Mathf.Max(elementsPerPage, _pagedIndices.Capacity);
int startIndex = (_pagingElement.Page - 1) * elementsPerPage;
int endIndex = Mathf.Min(startIndex + elementsPerPage, _activeState.ListSize);
for (int i = startIndex; i < endIndex; i++)
_pagedIndices.Add(i);
string shortDetailsString = (_activeState.ListSize + " " + (_pagedIndices.Count == 1 ? "Element" : "Elements"));
string detailsString = _pagingElement.PageCount > 1
? $"{_pagedIndices[0] + 1}..{_pagedIndices.Last() + 1} / {_activeState.ListSize} Elements"
: shortDetailsString;
_detailsContent = new GUIContent(detailsString);
_shortDetailsContent = new GUIContent(shortDetailsString);
}
private ReorderableList MakeList()
{
var list = new ReorderableList(_pagedIndices, typeof(int), true, true, true, true);
list.onAddCallback += OnAdd;
list.onRemoveCallback += OnRemove;
list.onReorderCallbackWithDetails += OnReorder;
list.drawElementCallback += OnDrawElement;
list.elementHeightCallback += OnGetElementHeight;
list.drawHeaderCallback += OnDrawHeader;
list.drawNoneElementCallback += OnDrawNoneElement;
return list;
}
private ReorderableList MakeUnexpandedList()
{
var list = new ReorderableList(SerializedDictionaryDrawer.NoEntriesList, typeof(int));
list.drawHeaderCallback = OnDrawUnexpandedHeader;
return list;
}
private void ToggleSearchBar(bool flag)
{
_showSearchBar = flag;
ReorderableList.headerHeight = SerializedDictionaryDrawer.TopHeaderClipHeight + SerializedDictionaryDrawer.KeyValueHeaderHeight + (_showSearchBar ? SerializedDictionaryDrawer.SearchHeaderHeight : 0);
if (!_showSearchBar)
{
if (_searchField.HasFocus())
GUI.FocusControl(null);
SearchText = string.Empty;
}
}
private void OnDrawNoneElement(Rect rect)
{
EditorGUI.LabelField(rect, EditorGUIUtility.TrTextContent(_activeState.NoElementsText));
}
private (DisplayType displayType, bool canToggleListDrawer) CreateDisplaySettings(SerializedProperty property, Type type)
{
bool hasCustomEditor = SCEditorUtility.HasDrawerForProperty(property, type);
bool isGenericWithChildren = property.propertyType == SerializedPropertyType.Generic && property.hasVisibleChildren;
bool isArray = property.isArray && property.propertyType != SerializedPropertyType.String;
bool canToggleListDrawer = isArray || (isGenericWithChildren && hasCustomEditor);
DisplayType displayType = DisplayType.PropertyNoLabel;
if (canToggleListDrawer)
displayType = DisplayType.Property;
else if (!isArray && isGenericWithChildren && !hasCustomEditor)
displayType = DisplayType.List;
return (displayType, canToggleListDrawer);
}
private void DoPaging(Rect rect)
{
EditorGUI.BeginChangeCheck();
_pagingElement.OnGUI(rect);
if (EditorGUI.EndChangeCheck())
{
ReorderableList.ClearSelection();
UpdatePaging();
}
}
private void OnDrawHeader(Rect rect)
{
Rect topRect = rect.WithHeight(SerializedDictionaryDrawer.TopHeaderHeight);
Rect adjustedTopRect = topRect.WithXAndWidth(_totalRect.x + 1, _totalRect.width - 1);
DoMainHeader(adjustedTopRect.CutLeft(topRect.x - adjustedTopRect.x));
if (_showSearchBar)
{
adjustedTopRect = adjustedTopRect.AppendDown(SerializedDictionaryDrawer.SearchHeaderHeight);
DoSearch(adjustedTopRect);
}
DoKeyValueRect(adjustedTopRect.AppendDown(SerializedDictionaryDrawer.KeyValueHeaderHeight));
UpdateAfterInput();
}
private void OnDrawUnexpandedHeader(Rect rect)
{
EditorGUI.BeginProperty(rect, _label, ListProperty);
ListProperty.isExpanded = EditorGUI.Foldout(rect.WithX(rect.x - 5), ListProperty.isExpanded, _label, true);
var detailsStyle = EditorStyles.miniLabel;
var detailsRect = rect.AppendRight(0).AppendLeft(detailsStyle.CalcSize(_shortDetailsContent).x);
GUI.Label(detailsRect, _shortDetailsContent, detailsStyle);
EditorGUI.EndProperty();
UpdateAfterInput();
}
private void DoMainHeader(Rect rect)
{
Rect lastTopRect = rect.AppendRight(0).WithHeight(EditorGUIUtility.singleLineHeight);
lastTopRect = lastTopRect.AppendLeft(20);
DoOptionsButton(lastTopRect);
lastTopRect = lastTopRect.AppendLeft(5);
if (_pagingElement.PageCount > 1)
{
lastTopRect = lastTopRect.AppendLeft(_pagingElement.GetDesiredWidth());
DoPaging(lastTopRect);
}
var detailsStyle = EditorStyles.miniLabel;
lastTopRect = lastTopRect.AppendLeft(detailsStyle.CalcSize(_detailsContent).x, 5);
GUI.Label(lastTopRect, _detailsContent, detailsStyle);
if (!_singleEditingData.IsValid)
{
lastTopRect = lastTopRect.AppendLeft(lastTopRect.height + 5);
var guicontent = EditorGUIUtility.TrIconContent(EditorGUIUtility.Load("d_console.infoicon") as Texture, "Conflict checking, duplicate key removal and populators not supported in multi object editing mode.");
GUI.Label(lastTopRect, guicontent);
}
EditorGUI.BeginProperty(rect, _label, ListProperty);
ListProperty.isExpanded = EditorGUI.Foldout(rect.WithXAndWidth(rect.x - 5, lastTopRect.x - rect.x), ListProperty.isExpanded, _label, true);
EditorGUI.EndProperty();
}
private void DoOptionsButton(Rect rect)
{
var screenRect = GUIUtility.GUIToScreenRect(rect);
if (GUI.Button(rect, EditorGUIUtility.IconContent("pane options@2x"), EditorStyles.iconButton))
{
var gm = new GenericMenu();
SCEditorUtility.AddGenericMenuItem(gm, false, ListProperty.minArraySize > 0, new GUIContent("Clear"), () => QueueAction(ClearList));
SCEditorUtility.AddGenericMenuItem(gm, false, true, new GUIContent("Remove Conflicts"), () => QueueAction(RemoveConflicts));
SCEditorUtility.AddGenericMenuItem(gm, false, _keyGeneratorsWithWindow.Count > 0, new GUIContent("Bulk Edit..."), () => OpenKeysGeneratorSelectorWindow(screenRect));
if (_keyGeneratorsWithoutWindow.Count > 0)
{
gm.AddSeparator(string.Empty);
foreach (var generatorData in _keyGeneratorsWithoutWindow)
{
SCEditorUtility.AddGenericMenuItem(gm, false, true, new GUIContent(generatorData.Name), OnPopulatorDataSelected, generatorData);
}
}
gm.AddSeparator(string.Empty);
SCEditorUtility.AddGenericMenuItem(gm, _propertyData.AlwaysShowSearch, true, new GUIContent("Always Show Search"), ToggleAlwaysShowSearchPropertyData);
gm.AddItem(new GUIContent("Preferences..."), false, () => SettingsService.OpenUserPreferences(EditorUserSettingsProvider.PreferencesPath));
gm.DropDown(rect);
}
}
private void OnPopulatorDataSelected(object userData)
{
var data = (KeyListGeneratorData)userData;
var so = (KeyListGenerator)ScriptableObject.CreateInstance(data.GeneratorType);
so.hideFlags = HideFlags.DontSave;
ApplyPopulatorQueued(so, ModificationType.Add);
}
private void OpenKeysGeneratorSelectorWindow(Rect rect)
{
var window = ScriptableObject.CreateInstance<KeyListGeneratorSelectorWindow>();
window.Initialize(_keyGeneratorsWithWindow, _keyFieldInfo.FieldType);
window.ShowAsDropDown(rect, new Vector2(400, 200));
window.OnApply += ApplyPopulatorQueued;
}
private void ToggleAlwaysShowSearchPropertyData()
{
_propertyData.AlwaysShowSearch = !_propertyData.AlwaysShowSearch;
SavePropertyData();
}
private void DoKeyValueRect(Rect rect)
{
var width = GetDesiredKeyLabelWidth(rect.width, 22);
Rect leftRect = rect.WithWidth(width);
Rect rightRect = leftRect.AppendRight(rect.width - width);
if (_propertyData != null)
{
if (Event.current.type == EventType.Repaint)
{
_keyValueStyle.Draw(leftRect, EditorGUIUtility.TrTextContent(_propertyData.GetElementData(SerializedDictionaryDrawer.KeyFlag).Settings.DisplayName), false, false, false, false);
_keyValueStyle.Draw(rightRect, EditorGUIUtility.TrTextContent(_propertyData.GetElementData(SerializedDictionaryDrawer.ValueFlag).Settings.DisplayName), false, false, false, false);
}
var changeSizeRect = leftRect.AppendRight(5);
changeSizeRect.x -= 2;
EditorGUI.BeginChangeCheck();
float newWidth = SCEditorUtility.DoHorizontalScale(changeSizeRect, _propertyData.KeyLabelWidth > 0f ? _propertyData.KeyLabelWidth : width);
if (EditorGUI.EndChangeCheck())
{
_propertyData.KeyLabelWidth = Mathf.Max(newWidth, MinKeyValueLabelWidth);
SavePropertyData();
}
}
if (ListProperty.minArraySize > 0)
{
DoDisplayTypeToggle(leftRect, SerializedDictionaryDrawer.KeyFlag);
DoDisplayTypeToggle(rightRect, SerializedDictionaryDrawer.ValueFlag);
}
EditorGUI.DrawRect(rect.AppendDown(1, -1), SerializedDictionaryDrawer.BorderColor);
}
private float GetDesiredKeyLabelWidth(float maxWidth, float offset = 0f)
{
float desiredWidth = _propertyData is { KeyLabelWidth: > 0 }
? _propertyData.KeyLabelWidth
: EditorGUIUtility.labelWidth;
return Mathf.Clamp(desiredWidth + offset, MinKeyValueLabelWidth, maxWidth - MinKeyValueLabelWidth);
}
private void DoSearch(Rect rect)
{
EditorGUI.DrawRect(rect.AppendLeft(1), SerializedDictionaryDrawer.BorderColor);
EditorGUI.DrawRect(rect.AppendRight(1, -1), SerializedDictionaryDrawer.BorderColor);
EditorGUI.DrawRect(rect.AppendDown(1, -1), SerializedDictionaryDrawer.BorderColor);
SearchText = _searchField.OnToolbarGUI(rect.CutTop(2).CutHorizontal(6), SearchText);
}
private void ApplyPopulatorQueued(KeyListGenerator populator, ModificationType modificationType)
{
var array = populator.GetKeys(_keyFieldInfo.FieldType).OfType<object>().ToArray();
QueueAction(() => ApplyPopulator(array, modificationType));
}
private void QueueAction(EditorApplication.CallbackFunction action)
{
EditorApplication.delayCall += action;
}
private void ApplyPopulator(IEnumerable<object> elements, ModificationType modificationType)
{
foreach (var targetObject in ListProperty.serializedObject.targetObjects)
{
Undo.RecordObject(targetObject, "Populate");
var dictionary = SCEditorUtility.GetPropertyValue(ListProperty, targetObject);
var lookupTable = GetLookupTable(dictionary);
if (modificationType == ModificationType.Add)
AddElements(lookupTable, elements);
else if (modificationType == ModificationType.Remove)
RemoveElements(lookupTable, elements);
else if (modificationType == ModificationType.Confine)
ConfineElements(lookupTable, elements);
lookupTable.RecalculateOccurences();
PrefabUtility.RecordPrefabInstancePropertyModifications(targetObject);
}
ListProperty.serializedObject.Update();
ActiveEditorTracker.sharedTracker.ForceRebuild();
}
private static void AddElements(IKeyable lookupTable, IEnumerable<object> elements)
{
foreach (var key in elements)
{
var occurences = lookupTable.GetOccurences(key);
if (occurences.Count > 0)
continue;
lookupTable.AddKey(key);
}
}
private static void ConfineElements(IKeyable lookupTable, IEnumerable<object> elements)
{
var keysToRemove = lookupTable.Keys.OfType<object>().ToHashSet();
foreach (var key in elements)
keysToRemove.Remove(key);
RemoveElements(lookupTable, keysToRemove);
}
private static void RemoveElements(IKeyable lookupTable, IEnumerable<object> elements)
{
var indicesToRemove = elements.SelectMany(x => lookupTable.GetOccurences(x)).OrderByDescending(index => index);
foreach (var index in indicesToRemove)
{
lookupTable.RemoveAt(index);
}
}
private void ClearList()
{
ListProperty.ClearArray();
ListProperty.serializedObject.ApplyModifiedProperties();
}
private void RemoveConflicts()
{
foreach (var targetObject in ListProperty.serializedObject.targetObjects)
{
Undo.RecordObject(targetObject, "Remove Conflicts");
var dictionary = SCEditorUtility.GetPropertyValue(ListProperty, targetObject);
var lookupTable = GetLookupTable(dictionary);
List<int> duplicateIndices = new List<int>();
foreach (var key in lookupTable.Keys)
{
var occurences = lookupTable.GetOccurences(key);
for (int i = 1; i < occurences.Count; i++)
duplicateIndices.Add(occurences[i]);
}
foreach (var indexToRemove in duplicateIndices.OrderByDescending(x => x))
{
lookupTable.RemoveAt(indexToRemove);
}
lookupTable.RecalculateOccurences();
PrefabUtility.RecordPrefabInstancePropertyModifications(targetObject);
}
ListProperty.serializedObject.Update();
ActiveEditorTracker.sharedTracker.ForceRebuild();
}
private void DoDisplayTypeToggle(Rect contentRect, bool fieldFlag)
{
var displayData = _propertyData.GetElementData(fieldFlag);
if (displayData.Settings.HasListDrawerToggle)
{
Rect rightRectToggle = new Rect(contentRect);
rightRectToggle.x += rightRectToggle.width - 18;
rightRectToggle.width = 18;
EditorGUI.BeginChangeCheck();
bool newValue = GUI.Toggle(rightRectToggle, displayData.IsListToggleActive, SerializedDictionaryDrawer.DisplayTypeToggleContent, EditorStyles.toolbarButton);
if (EditorGUI.EndChangeCheck())
{
displayData.IsListToggleActive = newValue;
SavePropertyData();
}
}
}
private float OnGetElementHeight(int index)
{
int actualIndex = _pagedIndices[index];
var element = _activeState.GetPropertyAtIndex(actualIndex);
return CalculateHeightOfElement(element, _propertyData.GetElementData(SerializedDictionaryDrawer.KeyFlag).EffectiveDisplayType == DisplayType.List, _propertyData.GetElementData(SerializedDictionaryDrawer.ValueFlag).EffectiveDisplayType == DisplayType.List);
}
private void OnDrawElement(Rect rect, int index, bool isActive, bool isFocused)
{
const int lineLeftSpace = 2;
const int lineWidth = 1;
const int lineRightSpace = 12;
const int totalSpace = lineLeftSpace + lineWidth + lineRightSpace;
int actualIndex = _pagedIndices[index];
SerializedProperty kvp = _activeState.GetPropertyAtIndex(actualIndex);
Rect keyRect = rect.WithSize(GetDesiredKeyLabelWidth(rect.width) - lineLeftSpace, EditorGUIUtility.singleLineHeight);
Rect lineRect = keyRect.WithXAndWidth(keyRect.x + keyRect.width + lineLeftSpace, lineWidth).WithHeight(rect.height);
Rect valueRect = keyRect.AppendRight(rect.width - keyRect.width - totalSpace, totalSpace);
var keyProperty = kvp.FindPropertyRelative(SerializedDictionaryDrawer.KeyName);
var valueProperty = kvp.FindPropertyRelative(SerializedDictionaryDrawer.ValueName);
Color prevColor = GUI.color;
if (_singleEditingData.IsValid)
{
var keyObject = _keyFieldInfo.GetValue(_singleEditingData.LookupTable.GetKeyAt(actualIndex));
var occurences = _singleEditingData.LookupTable.GetOccurences(keyObject);
if (occurences.Count > 1)
{
GUI.color = occurences[0] == actualIndex ? Color.yellow : Color.red;
}
if (!SerializedCollectionsUtility.IsValidKey(keyObject))
{
GUI.color = Color.red;
}
}
var keyDisplayData = _propertyData.GetElementData(SerializedDictionaryDrawer.KeyFlag);
DrawGroupedElement(keyRect, 20, keyProperty, keyDisplayData.EffectiveDisplayType);
EditorGUI.DrawRect(lineRect, new Color(36 / 255f, 36 / 255f, 36 / 255f));
GUI.color = prevColor;
var valueDisplayData = _propertyData.GetElementData(SerializedDictionaryDrawer.ValueFlag);
DrawGroupedElement(valueRect, lineRightSpace, valueProperty, valueDisplayData.EffectiveDisplayType);
}
private void DrawGroupedElement(Rect rect, int spaceForProperty, SerializedProperty property, DisplayType displayType)
{
using (new LabelWidth(rect.width * 0.4f))
{
float height = SCEditorUtility.CalculateHeight(property.Copy(), displayType);
Rect groupRect = rect.CutLeft(-spaceForProperty).WithHeight(height);
GUI.BeginGroup(groupRect);
Rect elementRect = new Rect(spaceForProperty, 0, rect.width, height);
_activeState.DrawElement(elementRect, property, displayType);
DrawInvisibleProperty(rect.WithWidth(spaceForProperty), property);
GUI.EndGroup();
}
}
internal static void DrawInvisibleProperty(Rect rect, SerializedProperty property)
{
const int propertyOffset = 5;
GUI.BeginClip(rect.CutLeft(-propertyOffset));
EditorGUI.BeginProperty(rect, GUIContent.none, property);
EditorGUI.EndProperty();
GUI.EndClip();
}
internal static void DrawElement(Rect rect, SerializedProperty property, DisplayType displayType, Action<SerializedProperty> BeforeDrawingCallback = null, Action<SerializedProperty> AfterDrawingCallback = null)
{
switch (displayType)
{
case DisplayType.Property:
BeforeDrawingCallback?.Invoke(property);
EditorGUI.PropertyField(rect, property, true);
AfterDrawingCallback?.Invoke(property);
break;
case DisplayType.PropertyNoLabel:
BeforeDrawingCallback?.Invoke(property);
EditorGUI.PropertyField(rect, property, GUIContent.none, true);
AfterDrawingCallback?.Invoke(property);
break;
case DisplayType.List:
Rect childRect = rect.WithHeight(0);
foreach (SerializedProperty prop in SCEditorUtility.GetChildren(property.Copy()))
{
childRect = childRect.AppendDown(EditorGUI.GetPropertyHeight(prop, true));
BeforeDrawingCallback?.Invoke(prop);
EditorGUI.PropertyField(childRect, prop, true);
AfterDrawingCallback?.Invoke(prop);
}
break;
default:
break;
}
}
private void OnAdd(ReorderableList list)
{
int targetIndex = list.selectedIndices.Count > 0 && list.selectedIndices[0] >= 0 ? list.selectedIndices[0] : 0;
int actualTargetIndex = targetIndex < _pagedIndices.Count ? _pagedIndices[targetIndex] : 0;
_activeState.InserElementAt(actualTargetIndex);
}
private void OnReorder(ReorderableList list, int oldIndex, int newIndex)
{
UpdatePaging();
ListProperty.MoveArrayElement(_pagedIndices[oldIndex], _pagedIndices[newIndex]);
}
private void OnRemove(ReorderableList list)
{
_activeState.RemoveElementAt(_pagedIndices[list.index]);
UpdatePaging();
}
}
}
@@ -0,0 +1,18 @@
fileFormatVersion: 2
guid: 9c3b210db82056a4a93c337b45da413b
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
AssetOrigin:
serializedVersion: 1
productId: 243052
packageName: Serialized Dictionary
packageVersion: 1.0.13
assetPath: Assets/Plugins/SerializedCollections/Editor/Scripts/SerializedDictionaryInstanceDrawer.cs
uploadId: 632226
@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 7691132b92786be418f91bf39639db87
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,60 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;
using System.IO;
using System;
namespace AYellowpaper.SerializedCollections.Editor
{
public sealed class EditorUserSettings : ScriptableObject
{
[SerializeField]
private bool _alwaysShowSearch = false;
[SerializeField, Range(1, 10)]
private int _pageCountForSearch = 1;
[SerializeField, Min(1)]
private int _elementsPerPage = 10;
public bool AlwaysShowSearch => _alwaysShowSearch;
public int PageCountForSearch => _pageCountForSearch;
public int ElementsPerPage => _elementsPerPage;
private static EditorUserSettings _instance;
private const string _filePath = "UserSettings/SerializedCollectionsEditorSettings.asset";
public static EditorUserSettings Get()
{
if (_instance == null)
{
_instance = CreateInstance<EditorUserSettings>();
LoadInto(_instance);
}
return _instance;
}
private static void LoadInto(EditorUserSettings settings)
{
if (!File.Exists(_filePath)) return;
try
{
string json = File.ReadAllText(_filePath);
EditorJsonUtility.FromJsonOverwrite(json, settings);
return;
}
catch (Exception e)
{
Debug.LogError(e);
return;
}
}
internal static void Save()
{
string contents = EditorJsonUtility.ToJson(Get());
File.WriteAllText(_filePath, contents);
}
}
}
Loaded 100 of 239 files, more files were not shown because too many files have changed in this diff. Show more