chore: initial commit

This commit is contained in:
2026-05-08 11:04:00 +08:00
commit f55d2a57c3
6278 changed files with 866081 additions and 0 deletions

View File

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

View File

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

View File

@@ -0,0 +1,586 @@
using MoreMountains.FeedbacksForThirdParty;
using MoreMountains.Tools;
namespace MoreMountains.Feedbacks
{
/// <summary>
/// Add this class to an empty object in your scene and it will prevent any unchecked feedback in its inspector from playing
/// </summary>
public partial class MMFeedbacksAuthorizations : MMMonoBehaviour
{
[MMInspectorGroup("Animation", true, 16)] [MMInspectorButton("ToggleAnimation")]
public bool ToggleAnimationButton;
public bool AnimationParameter = true;
public bool AnimatorSpeed = true;
[MMInspectorGroup("Audio", true, 17)] [MMInspectorButton("ToggleAudio")]
public bool ToggleAudioButton;
public bool AudioFilterDistortion = true;
public bool AudioFilterEcho = true;
public bool AudioFilterHighPass = true;
public bool AudioFilterLowPass = true;
public bool AudioFilterReverb = true;
public bool AudioMixerSnapshotTransition = true;
public bool AudioSource = true;
public bool AudioSourcePitch = true;
public bool AudioSourceStereoPan = true;
public bool AudioSourceVolume = true;
public bool MMPlaylist = true;
public bool MMSoundManagerAllSoundsControl = true;
public bool MMSoundManagerSaveAndLoad = true;
public bool MMSoundManagerSound = true;
public bool MMSoundManagerSoundControl = true;
public bool MMSoundManagerSoundFade = true;
public bool MMSoundManagerTrackControl = true;
public bool MMSoundManagerTrackFade = true;
public bool Sound = true;
[MMInspectorGroup("Camera", true, 18)] [MMInspectorButton("ToggleCamera")]
public bool ToggleCameraButton;
public bool CameraShake = true;
public bool CameraZoom = true;
#if MM_CINEMACHINE || MM_CINEMACHINE3
public bool CinemachineImpulse = true;
public bool CinemachineImpulseClear = true;
public bool CinemachineImpulseSource = true;
public bool CinemachineTransition = true;
#endif
public bool ClippingPlanes = true;
public bool Fade = true;
public bool FieldOfView = true;
public bool Flash = true;
public bool OrthographicSize = true;
[MMInspectorGroup("Debug", true, 19)] [MMInspectorButton("ToggleDebug")]
public bool ToggleDebugButton;
public bool Comment = true;
public bool Log = true;
[MMInspectorGroup("Events", true, 20)] [MMInspectorButton("ToggleEvents")]
public bool ToggleEventsButton;
public bool MMGameEvent = true;
public bool UnityEvents = true;
[MMInspectorGroup("GameObject", true, 47)] [MMInspectorButton("ToggleGameObject")]
public bool ToggleGameObjectButton;
public bool Broadcast = true;
public bool Collider = true;
public bool Collider2D = true;
public bool DestroyTargetObject = true;
public bool EnableBehaviour = true;
public bool FloatController = true;
public bool InstantiateObject = true;
public bool MMRadioSignal = true;
public bool Rigidbody = true;
public bool Rigidbody2D = true;
public bool SetActive = true;
#if MOREMOUNTAINS_NICEVIBRATIONS_INSTALLED
[MMInspectorGroup("Haptics", true, 22)] [MMInspectorButton("ToggleHaptics")]
public bool ToggleHapticsButton;
public bool HapticClip = true;
public bool HapticContinuous = true;
public bool HapticControl = true;
public bool HapticEmphasis = true;
public bool HapticPreset = true;
#endif
[MMInspectorGroup("Light", true, 23)] [MMInspectorButton("ToggleLight")]
public bool ToggleLightButton;
public bool Light = true;
[MMInspectorGroup("Loop", true, 24)] [MMInspectorButton("ToggleLoop")]
public bool ToggleLoopButton;
public bool Looper = true;
public bool LooperStart = true;
[MMInspectorGroup("Particles", true, 25)] [MMInspectorButton("ToggleParticles")]
public bool ToggleParticlesButton;
public bool ParticlesInstantiation = true;
public bool ParticlesPlay = true;
[MMInspectorGroup("Pause", true, 26)] [MMInspectorButton("TogglePause")]
public bool TogglePauseButton;
public bool HoldingPause = true;
public bool Pause = true;
[MMInspectorGroup("Post Process", true, 27)] [MMInspectorButton("TogglePostProcess")]
public bool TogglePostProcessButton;
public bool Bloom = true;
public bool ChromaticAberration = true;
public bool ColorGrading = true;
public bool DepthOfField = true;
public bool GlobalPPVolumeAutoBlend = true;
public bool LensDistortion = true;
public bool PPMovingFilter = true;
public bool Vignette = true;
[MMInspectorGroup("Flicker", true, 28)] [MMInspectorButton("ToggleFlicker")]
public bool ToggleFlickerButton;
public bool Flicker = true;
public bool Fog = true;
public bool Material = true;
public bool MMBlink = true;
public bool ShaderGlobal = true;
public bool ShaderController = true;
public bool Skybox = true;
public bool SpriteRenderer = true;
public bool TextureOffset = true;
public bool TextureScale = true;
[MMInspectorGroup("Scene", true, 29)] [MMInspectorButton("ToggleScene")]
public bool ToggleSceneButton;
public bool LoadScene = true;
public bool UnloadScene = true;
[MMInspectorGroup("Time", true, 31)] [MMInspectorButton("ToggleTime")]
public bool ToggleTimeButton;
public bool FreezeFrame = true;
public bool TimescaleModifier = true;
[MMInspectorGroup("Transform", true, 32)] [MMInspectorButton("ToggleTransform")]
public bool ToggleTransformButton;
public bool Destination = true;
public bool Position = true;
public bool PositionShake = true;
public bool RotatePositionAround = true;
public bool Rotation = true;
public bool RotationShake = true;
public bool Scale = true;
public bool ScaleShake = true;
public bool SquashAndStretch = true;
public bool Wiggle = true;
[MMInspectorGroup("UI", true, 33)] [MMInspectorButton("ToggleUI")]
public bool ToggleUiButton;
public bool CanvasGroup = true;
public bool CanvasGroupBlocksRaycasts = true;
public bool FloatingText = true;
public bool Graphic = true;
public bool GraphicCrossFade = true;
public bool Image = true;
public bool ImageAlpha = true;
public bool ImageFill = true;
public bool ImageRaycastTarget = true;
public bool ImageTextureOffset = true;
public bool ImageTextureScale = true;
public bool RectTransformAnchor = true;
public bool RectTransformOffset = true;
public bool RectTransformPivot = true;
public bool RectTransformSizeDelta = true;
public bool Text = true;
public bool TextColor = true;
public bool TextFontSize = true;
public bool VideoPlayer = true;
[MMInspectorGroup("TextMesh Pro", true, 30)] [MMInspectorButton("ToggleTextMeshPro")]
public bool ToggleTextMeshProButton;
#if (MM_TEXTMESHPRO || MM_UGUI2)
public bool TMPAlpha = true;
public bool TMPCharacterSpacing = true;
public bool TMPColor = true;
public bool TMPCountTo = true;
public bool TMPDilate = true;
public bool TMPFontSize = true;
public bool TMPLineSpacing = true;
public bool TMPOutlineColor = true;
public bool TMPOutlineWidth = true;
public bool TMPParagraphSpacing = true;
public bool TMPSoftness = true;
public bool TMPText = true;
public bool TMPTextReveal = true;
public bool TMPWordSpacing = true;
#endif
#region ToggleMethods
private void ToggleAnimation()
{
AnimationParameter = !AnimationParameter;
AnimatorSpeed = !AnimatorSpeed;
}
private void ToggleAudio()
{
AudioFilterDistortion = !AudioFilterDistortion;
AudioFilterEcho = !AudioFilterEcho;
AudioFilterHighPass = !AudioFilterHighPass;
AudioFilterLowPass = !AudioFilterLowPass;
AudioFilterReverb = !AudioFilterReverb;
AudioMixerSnapshotTransition = !AudioMixerSnapshotTransition;
AudioSource = !AudioSource;
AudioSourcePitch = !AudioSourcePitch;
AudioSourceStereoPan = !AudioSourceStereoPan;
AudioSourceVolume = !AudioSourceVolume;
MMPlaylist = !MMPlaylist;
MMSoundManagerAllSoundsControl = !MMSoundManagerAllSoundsControl;
MMSoundManagerSaveAndLoad = !MMSoundManagerSaveAndLoad;
MMSoundManagerSound = !MMSoundManagerSound;
MMSoundManagerSoundControl = !MMSoundManagerSoundControl;
MMSoundManagerSoundFade = !MMSoundManagerSoundFade;
MMSoundManagerTrackControl = !MMSoundManagerTrackControl;
MMSoundManagerTrackFade = !MMSoundManagerTrackFade;
Sound = !Sound;
}
private void ToggleCamera()
{
CameraShake = !CameraShake;
CameraZoom = !CameraZoom;
#if MM_CINEMACHINE || MM_CINEMACHINE3
CinemachineImpulse = !CinemachineImpulse;
CinemachineImpulseClear = !CinemachineImpulseClear;
CinemachineImpulseSource = !CinemachineImpulseSource;
CinemachineTransition = !CinemachineTransition;
#endif
ClippingPlanes = !ClippingPlanes;
Fade = !Fade;
FieldOfView = !FieldOfView;
Flash = !Flash;
OrthographicSize = !OrthographicSize;
}
private void ToggleDebug()
{
Comment = !Comment;
Log = !Log;
}
private void ToggleEvents()
{
MMGameEvent = !MMGameEvent;
UnityEvents = !UnityEvents;
}
private void ToggleGameObject()
{
Broadcast = !Broadcast;
Collider = !Collider;
Collider2D = !Collider2D;
DestroyTargetObject = !DestroyTargetObject;
EnableBehaviour = !EnableBehaviour;
FloatController = !FloatController;
InstantiateObject = !InstantiateObject;
MMRadioSignal = !MMRadioSignal;
Rigidbody = !Rigidbody;
Rigidbody2D = !Rigidbody2D;
SetActive = !SetActive;
}
#if MOREMOUNTAINS_NICEVIBRATIONS_INSTALLED
private void ToggleHaptics()
{
HapticClip = !HapticClip;
HapticContinuous = !HapticContinuous;
HapticControl = !HapticControl;
HapticEmphasis = !HapticEmphasis;
HapticPreset = !HapticPreset;
}
#endif
private void ToggleLight()
{
Light = !Light;
}
private void ToggleLoop()
{
Looper = !Looper;
LooperStart = !LooperStart;
}
private void ToggleParticles()
{
ParticlesInstantiation = !ParticlesInstantiation;
ParticlesPlay = !ParticlesPlay;
}
private void TogglePause()
{
HoldingPause = !HoldingPause;
Pause = !Pause;
}
#if MM_POSTPROCESSING
private void TogglePostProcess()
{
Bloom = !Bloom;
ChromaticAberration = !ChromaticAberration;
ColorGrading = !ColorGrading;
DepthOfField = !DepthOfField;
GlobalPPVolumeAutoBlend = !GlobalPPVolumeAutoBlend;
LensDistortion = !LensDistortion;
PPMovingFilter = !PPMovingFilter;
Vignette = !Vignette;
}
#endif
private void ToggleFlicker()
{
Flicker = !Flicker;
Fog = !Fog;
Material = !Material;
MMBlink = !MMBlink;
ShaderGlobal = !ShaderGlobal;
ShaderController = !ShaderController;
Skybox = !Skybox;
SpriteRenderer = !SpriteRenderer;
TextureOffset = !TextureOffset;
TextureScale = !TextureScale;
}
private void ToggleScene()
{
LoadScene = !LoadScene;
UnloadScene = !UnloadScene;
}
private void ToggleTime()
{
FreezeFrame = !FreezeFrame;
TimescaleModifier = !TimescaleModifier;
}
private void ToggleTransform()
{
Destination = !Destination;
Position = !Position;
PositionShake = !PositionShake;
RotatePositionAround = !RotatePositionAround;
Rotation = !Rotation;
RotationShake = !RotationShake;
Scale = !Scale;
ScaleShake = !ScaleShake;
SquashAndStretch = !SquashAndStretch;
Wiggle = !Wiggle;
}
private void ToggleUI()
{
CanvasGroup = !CanvasGroup;
CanvasGroupBlocksRaycasts = !CanvasGroupBlocksRaycasts;
FloatingText = !FloatingText;
Graphic = !Graphic;
GraphicCrossFade = !GraphicCrossFade;
Image = !Image;
ImageAlpha = !ImageAlpha;
ImageFill = !ImageFill;
ImageRaycastTarget = !ImageRaycastTarget;
ImageTextureOffset = !ImageTextureOffset;
ImageTextureScale = !ImageTextureScale;
RectTransformAnchor = !RectTransformAnchor;
RectTransformOffset = !RectTransformOffset;
RectTransformPivot = !RectTransformPivot;
RectTransformSizeDelta = !RectTransformSizeDelta;
Text = !Text;
TextColor = !TextColor;
TextFontSize = !TextFontSize;
VideoPlayer = !VideoPlayer;
}
#if (MM_TEXTMESHPRO || MM_UGUI2)
private void ToggleTextMeshPro()
{
TMPAlpha = !TMPAlpha;
TMPCharacterSpacing = !TMPCharacterSpacing;
TMPColor = !TMPColor;
TMPCountTo = !TMPCountTo;
TMPDilate = !TMPDilate;
TMPFontSize = !TMPFontSize;
TMPLineSpacing = !TMPLineSpacing;
TMPOutlineColor = !TMPOutlineColor;
TMPOutlineWidth = !TMPOutlineWidth;
TMPParagraphSpacing = !TMPParagraphSpacing;
TMPSoftness = !TMPSoftness;
TMPText = !TMPText;
TMPTextReveal = !TMPTextReveal;
TMPWordSpacing = !TMPWordSpacing;
}
#endif
#endregion
private void Start()
{
MMF_Animation.FeedbackTypeAuthorized = AnimationParameter;
MMF_AnimatorSpeed.FeedbackTypeAuthorized = AnimatorSpeed;
MMF_AudioFilterDistortion.FeedbackTypeAuthorized = AudioFilterDistortion;
MMF_AudioFilterEcho.FeedbackTypeAuthorized = AudioFilterEcho;
MMF_AudioFilterHighPass.FeedbackTypeAuthorized = AudioFilterHighPass;
MMF_AudioFilterLowPass.FeedbackTypeAuthorized = AudioFilterLowPass;
MMF_AudioFilterReverb.FeedbackTypeAuthorized = AudioFilterReverb;
MMF_AudioMixerSnapshotTransition.FeedbackTypeAuthorized = AudioMixerSnapshotTransition;
MMF_AudioSource.FeedbackTypeAuthorized = AudioSource;
MMF_AudioSourcePitch.FeedbackTypeAuthorized = AudioSourcePitch;
MMF_AudioSourceStereoPan.FeedbackTypeAuthorized = AudioSourceStereoPan;
MMF_AudioSourceVolume.FeedbackTypeAuthorized = AudioSourceVolume;
MMF_Playlist.FeedbackTypeAuthorized = MMPlaylist;
MMF_MMSoundManagerAllSoundsControl.FeedbackTypeAuthorized = MMSoundManagerAllSoundsControl;
MMF_MMSoundManagerSaveLoad.FeedbackTypeAuthorized = MMSoundManagerSaveAndLoad;
MMF_MMSoundManagerSound.FeedbackTypeAuthorized = MMSoundManagerSound;
MMF_MMSoundManagerSoundControl.FeedbackTypeAuthorized = MMSoundManagerSoundControl;
MMF_MMSoundManagerSoundFade.FeedbackTypeAuthorized = MMSoundManagerSoundFade;
MMF_MMSoundManagerTrackControl.FeedbackTypeAuthorized = MMSoundManagerTrackControl;
MMF_MMSoundManagerTrackFade.FeedbackTypeAuthorized = MMSoundManagerTrackFade;
MMF_Sound.FeedbackTypeAuthorized = Sound;
MMF_CameraShake.FeedbackTypeAuthorized = CameraShake;
MMF_CameraZoom.FeedbackTypeAuthorized = CameraZoom;
#if MM_CINEMACHINE || MM_CINEMACHINE3
MMF_CinemachineImpulse.FeedbackTypeAuthorized = CinemachineImpulse;
MMF_CinemachineImpulseClear.FeedbackTypeAuthorized = CinemachineImpulseClear;
MMF_CinemachineImpulseSource.FeedbackTypeAuthorized = CinemachineImpulseSource;
MMF_CinemachineTransition.FeedbackTypeAuthorized = CinemachineTransition;
#endif
MMF_CameraClippingPlanes.FeedbackTypeAuthorized = ClippingPlanes;
MMF_CameraFieldOfView.FeedbackTypeAuthorized = FieldOfView;
MMF_CameraOrthographicSize.FeedbackTypeAuthorized = OrthographicSize;
MMF_DebugComment.FeedbackTypeAuthorized = Comment;
MMF_DebugLog.FeedbackTypeAuthorized = Log;
MMF_MMGameEvent.FeedbackTypeAuthorized = MMGameEvent;
MMF_Events.FeedbackTypeAuthorized = UnityEvents;
MMF_Broadcast.FeedbackTypeAuthorized = Broadcast;
MMF_Collider.FeedbackTypeAuthorized = Collider;
MMF_Collider2D.FeedbackTypeAuthorized = Collider2D;
MMF_Destroy.FeedbackTypeAuthorized = DestroyTargetObject;
MMF_Enable.FeedbackTypeAuthorized = EnableBehaviour;
MMF_FloatController.FeedbackTypeAuthorized = FloatController;
MMF_InstantiateObject.FeedbackTypeAuthorized = InstantiateObject;
MMF_RadioSignal.FeedbackTypeAuthorized = MMRadioSignal;
MMF_Rigidbody.FeedbackTypeAuthorized = Rigidbody;
MMF_Rigidbody2D.FeedbackTypeAuthorized = Rigidbody2D;
MMF_SetActive.FeedbackTypeAuthorized = SetActive;
#if MOREMOUNTAINS_NICEVIBRATIONS_INSTALLED
MMF_Haptics.FeedbackTypeAuthorized = HapticClip;
MMF_NVContinuous.FeedbackTypeAuthorized = HapticContinuous;
MMF_NVControl.FeedbackTypeAuthorized = HapticControl;
MMF_NVEmphasis.FeedbackTypeAuthorized = HapticEmphasis;
MMF_NVPreset.FeedbackTypeAuthorized = HapticPreset;
#endif
MMF_Light.FeedbackTypeAuthorized = Light;
MMF_Looper.FeedbackTypeAuthorized = Looper;
MMF_LooperStart.FeedbackTypeAuthorized = LooperStart;
MMF_ParticlesInstantiation.FeedbackTypeAuthorized = ParticlesInstantiation;
MMF_Particles.FeedbackTypeAuthorized = ParticlesPlay;
MMF_HoldingPause.FeedbackTypeAuthorized = HoldingPause;
MMF_Pause.FeedbackTypeAuthorized = Pause;
MMF_Flicker.FeedbackTypeAuthorized = Flicker;
MMF_Fog.FeedbackTypeAuthorized = Fog;
MMF_Material.FeedbackTypeAuthorized = Material;
MMF_Blink.FeedbackTypeAuthorized = MMBlink;
MMF_ShaderGlobal.FeedbackTypeAuthorized = ShaderGlobal;
MMF_Skybox.FeedbackTypeAuthorized = Skybox;
MMF_SpriteRenderer.FeedbackTypeAuthorized = SpriteRenderer;
MMF_TextureOffset.FeedbackTypeAuthorized = TextureOffset;
MMF_TextureScale.FeedbackTypeAuthorized = TextureScale;
MMF_LoadScene.FeedbackTypeAuthorized = LoadScene;
MMF_UnloadScene.FeedbackTypeAuthorized = UnloadScene;
MMF_FreezeFrame.FeedbackTypeAuthorized = FreezeFrame;
MMF_TimescaleModifier.FeedbackTypeAuthorized = TimescaleModifier;
MMF_DestinationTransform.FeedbackTypeAuthorized = Destination;
MMF_Position.FeedbackTypeAuthorized = Position;
MMF_PositionShake.FeedbackTypeAuthorized = PositionShake;
MMF_RotatePositionAround.FeedbackTypeAuthorized = RotatePositionAround;
MMF_Rotation.FeedbackTypeAuthorized = Rotation;
MMF_RotationShake.FeedbackTypeAuthorized = RotationShake;
MMF_Scale.FeedbackTypeAuthorized = Scale;
MMF_ScaleShake.FeedbackTypeAuthorized = ScaleShake;
MMF_SquashAndStretch.FeedbackTypeAuthorized = SquashAndStretch;
MMF_Wiggle.FeedbackTypeAuthorized = Wiggle;
MMF_CanvasGroup.FeedbackTypeAuthorized = CanvasGroup;
MMF_CanvasGroupBlocksRaycasts.FeedbackTypeAuthorized = CanvasGroupBlocksRaycasts;
MMF_FloatingText.FeedbackTypeAuthorized = FloatingText;
MMF_RectTransformAnchor.FeedbackTypeAuthorized = RectTransformAnchor;
MMF_RectTransformOffset.FeedbackTypeAuthorized = RectTransformOffset;
MMF_RectTransformPivot.FeedbackTypeAuthorized = RectTransformPivot;
MMF_RectTransformSizeDelta.FeedbackTypeAuthorized = RectTransformSizeDelta;
MMF_VideoPlayer.FeedbackTypeAuthorized = VideoPlayer;
#if MM_UI
MMF_ShaderController.FeedbackTypeAuthorized = ShaderController;
MMF_Graphic.FeedbackTypeAuthorized = Graphic;
MMF_GraphicCrossFade.FeedbackTypeAuthorized = GraphicCrossFade;
MMF_Image.FeedbackTypeAuthorized = Image;
MMF_ImageAlpha.FeedbackTypeAuthorized = ImageAlpha;
MMF_ImageFill.FeedbackTypeAuthorized = ImageFill;
MMF_ImageRaycastTarget.FeedbackTypeAuthorized = ImageRaycastTarget;
MMF_ImageTextureOffset.FeedbackTypeAuthorized = ImageTextureOffset;
MMF_ImageTextureScale.FeedbackTypeAuthorized = ImageTextureScale;
MMF_Text.FeedbackTypeAuthorized = Text;
MMF_TextColor.FeedbackTypeAuthorized = TextColor;
MMF_TextFontSize.FeedbackTypeAuthorized = TextFontSize;
MMF_Fade.FeedbackTypeAuthorized = Fade;
MMF_Flash.FeedbackTypeAuthorized = Flash;
#endif
#if MM_POSTPROCESSING
MMF_Bloom.FeedbackTypeAuthorized = Bloom;
MMF_ChromaticAberration.FeedbackTypeAuthorized = ChromaticAberration;
MMF_ColorGrading.FeedbackTypeAuthorized = ColorGrading;
MMF_DepthOfField.FeedbackTypeAuthorized = DepthOfField;
MMF_GlobalPPVolumeAutoBlend.FeedbackTypeAuthorized = GlobalPPVolumeAutoBlend;
MMF_LensDistortion.FeedbackTypeAuthorized = LensDistortion;
MMF_Vignette.FeedbackTypeAuthorized = Vignette;
MMF_PPMovingFilter.FeedbackTypeAuthorized = PPMovingFilter;
#endif
#if MM_HDRP
MMF_Bloom_HDRP.FeedbackTypeAuthorized = Bloom;
MMF_ChromaticAberration_HDRP.FeedbackTypeAuthorized = ChromaticAberration;
MMF_LensDistortion_HDRP.FeedbackTypeAuthorized = LensDistortion;
MMF_ColorAdjustments_HDRP.FeedbackTypeAuthorized = ColorGrading;
MMF_LensDistortion_HDRP.FeedbackTypeAuthorized = LensDistortion;
MMF_Vignette_HDRP.FeedbackTypeAuthorized = Vignette;
#endif
#if MM_URP
MMF_Bloom_URP.FeedbackTypeAuthorized = Bloom;
MMF_ChromaticAberration_URP.FeedbackTypeAuthorized = ChromaticAberration;
MMF_LensDistortion_URP.FeedbackTypeAuthorized = LensDistortion;
MMF_ColorAdjustments_URP.FeedbackTypeAuthorized = ColorGrading;
MMF_LensDistortion_URP.FeedbackTypeAuthorized = LensDistortion;
MMF_Vignette_URP.FeedbackTypeAuthorized = Vignette;
#endif
#if (MM_TEXTMESHPRO || MM_UGUI2)
MMF_TMPAlpha.FeedbackTypeAuthorized = TMPAlpha;
MMF_TMPCharacterSpacing.FeedbackTypeAuthorized = TMPCharacterSpacing;
MMF_TMPColor.FeedbackTypeAuthorized = TMPColor;
MMF_TMPCountTo.FeedbackTypeAuthorized = TMPCountTo;
MMF_TMPDilate.FeedbackTypeAuthorized = TMPDilate;
MMF_TMPFontSize.FeedbackTypeAuthorized = TMPFontSize;
MMF_TMPLineSpacing.FeedbackTypeAuthorized = TMPLineSpacing;
MMF_TMPOutlineColor.FeedbackTypeAuthorized = TMPOutlineColor;
MMF_TMPOutlineWidth.FeedbackTypeAuthorized = TMPOutlineWidth;
MMF_TMPParagraphSpacing.FeedbackTypeAuthorized = TMPParagraphSpacing;
MMF_TMPSoftness.FeedbackTypeAuthorized = TMPSoftness;
MMF_TMPText.FeedbackTypeAuthorized = TMPText;
MMF_TMPTextReveal.FeedbackTypeAuthorized = TMPTextReveal;
#endif
}
}
}

View File

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

View File

@@ -0,0 +1,3 @@
{
"reference": "GUID:4a1cb1490dc4df8409b2580d6b44e75e"
}

View File

@@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: 9a55bdc9c20a8d640a83b706174628dd
AssemblyDefinitionReferenceImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

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

View File

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

View File

@@ -0,0 +1,271 @@
using UnityEngine;
#if UNITY_EDITOR
using UnityEditor;
#endif
namespace MoreMountains.Feedbacks
{
[CustomPropertyDrawer(typeof(MMFEnumConditionAttribute))]
public class MMFEnumConditionAttributeDrawer : PropertyDrawer
{
public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
{
MMFEnumConditionAttribute enumConditionAttribute = (MMFEnumConditionAttribute)attribute;
bool enabled = GetConditionAttributeResult(enumConditionAttribute, property);
bool previouslyEnabled = GUI.enabled;
GUI.enabled = enabled;
if (!enumConditionAttribute.Hidden || enabled)
{
EditorGUI.PropertyField(position, property, label, true);
}
GUI.enabled = previouslyEnabled;
}
private bool GetConditionAttributeResult(MMFEnumConditionAttribute enumConditionAttribute, SerializedProperty property)
{
bool enabled = true;
string propertyPath = property.propertyPath;
string conditionPath = propertyPath.Replace(property.name, enumConditionAttribute.ConditionEnum);
SerializedProperty sourcePropertyValue = property.serializedObject.FindProperty(conditionPath);
if ((sourcePropertyValue != null) && (sourcePropertyValue.propertyType == SerializedPropertyType.Enum))
{
int currentEnum = sourcePropertyValue.enumValueIndex;
enabled = enumConditionAttribute.ContainsBitFlag(currentEnum);
}
else
{
Debug.LogWarning("No matching boolean found for ConditionAttribute in object: " + enumConditionAttribute.ConditionEnum);
}
return enabled;
}
public override float GetPropertyHeight(SerializedProperty property, GUIContent label)
{
MMFEnumConditionAttribute enumConditionAttribute = (MMFEnumConditionAttribute)attribute;
bool enabled = GetConditionAttributeResult(enumConditionAttribute, property);
if (!enumConditionAttribute.Hidden || enabled)
{
return EditorGUI.GetPropertyHeight(property, label);
}
else
{
/*int multiplier = 1; // this multiplier fixes issues in differing property spacing between MMFeedbacks and MMF_Player
if (property.depth > 0)
{
multiplier = property.depth;
}*/
return -EditorGUIUtility.standardVerticalSpacing /** multiplier*/;
}
}
}
// original implementation by http://www.brechtos.com/hiding-or-disabling-inspector-properties-using-propertydrawers-within-unity-5/
[CustomPropertyDrawer(typeof(MMFConditionAttribute))]
public class MMFConditionAttributeDrawer : PropertyDrawer
{
public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
{
MMFConditionAttribute conditionAttribute = (MMFConditionAttribute)attribute;
bool enabled = GetConditionAttributeResult(conditionAttribute, property);
bool previouslyEnabled = GUI.enabled;
GUI.enabled = conditionAttribute.Negative ? !enabled : enabled;
if (ShouldDisplay(conditionAttribute, enabled))
{
EditorGUI.PropertyField(position, property, label, true);
}
GUI.enabled = previouslyEnabled;
}
private bool GetConditionAttributeResult(MMFConditionAttribute conditionAttribute, SerializedProperty property)
{
bool enabled = true;
string propertyPath = property.propertyPath;
string conditionPath = propertyPath.Replace(property.name, conditionAttribute.ConditionBoolean);
SerializedProperty sourcePropertyValue = property.serializedObject.FindProperty(conditionPath);
if (sourcePropertyValue != null)
{
enabled = sourcePropertyValue.boolValue;
}
else
{
Debug.LogWarning("No matching boolean found for ConditionAttribute in object: " + conditionAttribute.ConditionBoolean);
}
return enabled;
}
private bool ShouldDisplay(MMFConditionAttribute conditionAttribute, bool result)
{
bool shouldDisplay = !conditionAttribute.Hidden || result;
if (conditionAttribute.Negative)
{
shouldDisplay = !shouldDisplay;
}
return shouldDisplay;
}
public override float GetPropertyHeight(SerializedProperty property, GUIContent label)
{
MMFConditionAttribute conditionAttribute = (MMFConditionAttribute)attribute;
bool enabled = GetConditionAttributeResult(conditionAttribute, property);
if (ShouldDisplay(conditionAttribute, enabled))
{
return EditorGUI.GetPropertyHeight(property, label);
}
else
{
/*int multiplier = 1; // this multiplier fixes issues in differing property spacing between MMFeedbacks and MMF_Player
if (property.depth > 0)
{
//multiplier = property.depth;
}*/
return -EditorGUIUtility.standardVerticalSpacing /** multiplier*/;
}
}
}
[CustomPropertyDrawer(typeof(MMFHiddenAttribute))]
public class MMFHiddenAttributeDrawer : PropertyDrawer
{
public override float GetPropertyHeight(SerializedProperty property, GUIContent label)
{
return 0f;
}
public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
{
}
}
[CustomPropertyDrawer(typeof(MMFInformationAttribute))]
/// <summary>
/// This class allows the display of a message box (warning, info, error...) next to a property (before or after)
/// </summary>
public class MMFInformationAttributeDrawer : PropertyDrawer
{
// determines the space after the help box, the space before the text box, and the width of the help box icon
const int spaceBeforeTheTextBox = 5;
const int spaceAfterTheTextBox = 10;
const int iconWidth = 55;
MMFInformationAttribute informationAttribute { get { return ((MMFInformationAttribute)attribute); } }
/// <summary>
/// OnGUI, displays the property and the textbox in the specified order
/// </summary>
/// <param name="rect">Rect.</param>
/// <param name="prop">Property.</param>
/// <param name="label">Label.</param>
public override void OnGUI(Rect rect, SerializedProperty prop, GUIContent label)
{
if (HelpEnabled())
{
EditorStyles.helpBox.richText = true;
Rect helpPosition = rect;
Rect textFieldPosition = rect;
if (!informationAttribute.MessageAfterProperty)
{
// we position the message before the property
helpPosition.height = DetermineTextboxHeight(informationAttribute.Message);
textFieldPosition.y += helpPosition.height + spaceBeforeTheTextBox;
textFieldPosition.height = GetPropertyHeight(prop, label);
}
else
{
// we position the property first, then the message
textFieldPosition.height = GetPropertyHeight(prop, label);
helpPosition.height = DetermineTextboxHeight(informationAttribute.Message);
// we add the complete property height (property + helpbox, as overridden in this very script), and substract both to get just the property
helpPosition.y += GetPropertyHeight(prop, label) - DetermineTextboxHeight(informationAttribute.Message) - spaceAfterTheTextBox;
}
EditorGUI.HelpBox(helpPosition, informationAttribute.Message, informationAttribute.Type);
EditorGUI.PropertyField(textFieldPosition, prop, label, true);
}
else
{
Rect textFieldPosition = rect;
textFieldPosition.height = GetPropertyHeight(prop, label);
EditorGUI.PropertyField(textFieldPosition, prop, label, true);
}
}
/// <summary>
/// Returns the complete height of the whole block (property + help text)
/// </summary>
/// <returns>The block height.</returns>
/// <param name="property">Property.</param>
/// <param name="label">Label.</param>
public override float GetPropertyHeight(SerializedProperty property, GUIContent label)
{
if (HelpEnabled())
{
return EditorGUI.GetPropertyHeight(property) + DetermineTextboxHeight(informationAttribute.Message) + spaceAfterTheTextBox + spaceBeforeTheTextBox;
}
else
{
return EditorGUI.GetPropertyHeight(property);
}
}
/// <summary>
/// Checks the editor prefs to see if help is enabled or not
/// </summary>
/// <returns><c>true</c>, if enabled was helped, <c>false</c> otherwise.</returns>
protected virtual bool HelpEnabled()
{
bool helpEnabled = false;
if (EditorPrefs.HasKey("MMShowHelpInInspectors"))
{
if (EditorPrefs.GetBool("MMShowHelpInInspectors"))
{
helpEnabled = true;
}
}
return helpEnabled;
}
/// <summary>
/// Determines the height of the textbox.
/// </summary>
/// <returns>The textbox height.</returns>
/// <param name="message">Message.</param>
protected virtual float DetermineTextboxHeight(string message)
{
GUIStyle style = new GUIStyle(EditorStyles.helpBox);
style.richText = true;
float newHeight = style.CalcHeight(new GUIContent(message), EditorGUIUtility.currentViewWidth - iconWidth);
return newHeight;
}
}
[CustomPropertyDrawer(typeof(MMFReadOnlyAttribute))]
public class MMFReadOnlyAttributeDrawer : PropertyDrawer
{
// Necessary since some properties tend to collapse smaller than their content
public override float GetPropertyHeight(SerializedProperty property, GUIContent label)
{
return EditorGUI.GetPropertyHeight(property, label, true);
}
// Draw a disabled property field
public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
{
GUI.enabled = false; // Disable fields
EditorGUI.PropertyField(position, property, label, true);
GUI.enabled = true; // Enable fields
}
}
}

View File

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

View File

@@ -0,0 +1,462 @@
using UnityEngine;
using UnityEditor;
using System;
using System.Reflection;
using System.Linq;
using System.Collections.Generic;
namespace MoreMountains.Feedbacks
{
public class MMFInspectorGroupData
{
public bool GroupIsOpen;
public MMFInspectorGroupAttribute GroupAttribute;
public List<SerializedProperty> PropertiesList = new List<SerializedProperty>();
public HashSet<string> GroupHashSet = new HashSet<string>();
public Color GroupColor;
public void ClearGroup()
{
GroupAttribute = null;
GroupHashSet.Clear();
PropertiesList.Clear();
}
}
public class MMF_FeedbackInspector
{
public bool DrawerInitialized;
public List<SerializedProperty> PropertiesList = new List<SerializedProperty>();
public Dictionary<string, MMFInspectorGroupData> GroupData = new Dictionary<string, MMFInspectorGroupData>();
private string[] _mmHiddenPropertiesToHide;
private bool _hasMMHiddenProperties = false;
protected bool _shouldDrawBase = true;
protected SerializedProperty _currentProperty;
protected MMF_Feedback _feedback;
protected bool _expandGroupInspectors;
private const string _channelFieldName = "Channel";
private const string _channelModeFieldName = "ChannelMode";
private const string _channelDefinitionFieldName = "MMChannelDefinition";
private const string _automatedTargetAcquisitionName = "AutomatedTargetAcquisition";
public virtual void OnEnable()
{
DrawerInitialized = false;
PropertiesList.Clear();
GroupData.Clear();
MMFHiddenPropertiesAttribute[] hiddenProperties = (MMFHiddenPropertiesAttribute[])_currentProperty.GetType().GetCustomAttributes(typeof(MMFHiddenPropertiesAttribute), false);
if (hiddenProperties != null && hiddenProperties.Length > 0 && hiddenProperties[0].PropertiesNames != null)
{
_mmHiddenPropertiesToHide = hiddenProperties[0].PropertiesNames;
_hasMMHiddenProperties = true;
}
}
public virtual void OnDisable()
{
foreach (KeyValuePair<string, MMFInspectorGroupData> groupData in GroupData)
{
if (groupData.Value != null)
{
EditorPrefs.SetBool(string.Format($"{groupData.Value.GroupAttribute.GroupName}{groupData.Value.PropertiesList[0].name}{_feedback.UniqueID}"), groupData.Value.GroupIsOpen);
groupData.Value.ClearGroup();
}
}
}
protected Dictionary<string,MMFConditionAttribute> _conditionDictionary = new Dictionary<string,MMFConditionAttribute>();
protected Dictionary<string,MMFEnumConditionAttribute> _enumConditionDictionary = new Dictionary<string,MMFEnumConditionAttribute>();
protected MMFConditionAttribute _conditionAttributeStore;
protected MMFEnumConditionAttribute _enumConditionAttributeStore;
public virtual void Initialization(SerializedProperty currentProperty, MMF_Feedback feedback, bool expandGroupInspectors)
{
if (DrawerInitialized)
{
return;
}
_expandGroupInspectors = expandGroupInspectors;
_currentProperty = currentProperty;
_feedback = feedback;
_conditionDictionary.Clear();
_enumConditionDictionary.Clear();
List<FieldInfo> fieldInfoList;
MMFInspectorGroupAttribute previousGroupAttribute = default;
int fieldInfoLength = MMF_FieldInfo.GetFieldInfo(feedback, out fieldInfoList);
for (int i = 0; i < fieldInfoLength; i++)
{
SearchForConditions(fieldInfoList[i]);
MMFInspectorGroupAttribute group = Attribute.GetCustomAttribute(fieldInfoList[i], typeof(MMFInspectorGroupAttribute)) as MMFInspectorGroupAttribute;
MMFInspectorGroupData groupData;
if (group == null)
{
if (previousGroupAttribute != null && previousGroupAttribute.GroupAllFieldsUntilNextGroupAttribute)
{
_shouldDrawBase = false;
if (!GroupData.TryGetValue(previousGroupAttribute.GroupName, out groupData))
{
if (!ShouldSkipGroup(previousGroupAttribute.GroupName))
{
GroupData.Add(previousGroupAttribute.GroupName, new MMFInspectorGroupData
{
GroupAttribute = previousGroupAttribute,
GroupHashSet = new HashSet<string> { fieldInfoList[i].Name },
GroupColor = MMFeedbacksColors.GetColorAt(previousGroupAttribute.GroupColorIndex)
});
}
}
else
{
groupData.GroupColor = MMFeedbacksColors.GetColorAt(previousGroupAttribute.GroupColorIndex);
groupData.GroupHashSet.Add(fieldInfoList[i].Name);
}
}
continue;
}
previousGroupAttribute = group;
if (!GroupData.TryGetValue(group.GroupName, out groupData))
{
bool fallbackOpenState = _expandGroupInspectors;
if (group.ClosedByDefault) { fallbackOpenState = false; }
bool groupIsOpen = EditorPrefs.GetBool(string.Format($"{group.GroupName}{fieldInfoList[i].Name}{feedback.UniqueID}"), fallbackOpenState);
if (!ShouldSkipGroup(previousGroupAttribute.GroupName))
{
GroupData.Add(group.GroupName, new MMFInspectorGroupData
{
GroupAttribute = group,
GroupColor = MMFeedbacksColors.GetColorAt(previousGroupAttribute.GroupColorIndex),
GroupHashSet = new HashSet<string> { fieldInfoList[i].Name }, GroupIsOpen = groupIsOpen
});
}
}
else
{
groupData.GroupHashSet.Add(fieldInfoList[i].Name);
groupData.GroupColor = MMFeedbacksColors.GetColorAt(previousGroupAttribute.GroupColorIndex);
}
}
if (currentProperty.NextVisible(true))
{
do
{
FillPropertiesList(currentProperty);
} while (currentProperty.NextVisible(false));
}
DrawerInitialized = true;
}
protected virtual bool ShouldSkipGroup(string groupName)
{
bool skip = false;
if (groupName == MMF_Feedback._randomnessGroupName && !_feedback.HasRandomness)
{
skip = true;
}
if (groupName == MMF_Feedback._rangeGroupName && !_feedback.HasRange)
{
skip = true;
}
if (groupName == MMF_Feedback._automaticSetupGroupName && !_feedback.HasAutomaticShakerSetup)
{
skip = true;
}
return skip;
}
protected virtual void SearchForConditions(FieldInfo fieldInfo)
{
_conditionAttributeStore = Attribute.GetCustomAttribute(fieldInfo, typeof(MMFConditionAttribute)) as MMFConditionAttribute;
if (_conditionAttributeStore != null)
{
_conditionDictionary.Add(fieldInfo.Name, _conditionAttributeStore);
}
_enumConditionAttributeStore = Attribute.GetCustomAttribute(fieldInfo, typeof(MMFEnumConditionAttribute)) as MMFEnumConditionAttribute;
if (_enumConditionAttributeStore != null)
{
_enumConditionDictionary.Add(fieldInfo.Name, _enumConditionAttributeStore);
}
}
public void FillPropertiesList(SerializedProperty serializedProperty)
{
bool shouldClose = false;
foreach (KeyValuePair<string, MMFInspectorGroupData> pair in GroupData)
{
if (pair.Value.GroupHashSet.Contains(serializedProperty.name))
{
SerializedProperty property = serializedProperty.Copy();
shouldClose = true;
pair.Value.PropertiesList.Add(property);
break;
}
}
if (!shouldClose)
{
SerializedProperty property = serializedProperty.Copy();
PropertiesList.Add(property);
}
}
public void DrawInspector(SerializedProperty currentProperty, MMF_Feedback feedback)
{
Initialization(currentProperty, feedback, _expandGroupInspectors);
if (!DrawBase(currentProperty, feedback))
{
DrawContainer(feedback);
DrawContents(feedback);
}
}
protected virtual bool DrawBase(SerializedProperty currentProperty, MMF_Feedback feedback)
{
if (_shouldDrawBase || !feedback.DrawGroupInspectors)
{
DrawNoGroupInspector(currentProperty, feedback);
return true;
}
else
{
return false;
}
}
protected virtual void DrawContainer(MMF_Feedback feedback)
{
if (PropertiesList.Count == 0)
{
return;
}
foreach (KeyValuePair<string, MMFInspectorGroupData> pair in GroupData)
{
DrawVerticalLayout(() => DrawGroup(pair.Value, feedback), MMF_FeedbackInspectorStyle.ContainerStyle);
EditorGUI.indentLevel = 0;
}
}
protected virtual void DrawContents(MMF_Feedback feedback)
{
if (PropertiesList.Count == 0)
{
return;
}
EditorGUILayout.Space();
for (int i = 1; i < PropertiesList.Count; i++)
{
if (_hasMMHiddenProperties && (!_mmHiddenPropertiesToHide.Contains(PropertiesList[i].name)))
{
if (!DrawCustomInspectors(PropertiesList[i], feedback))
{
EditorGUILayout.PropertyField(PropertiesList[i], true);
}
}
}
}
protected Rect _leftBorderRect = new Rect();
protected Rect _setupRect = new Rect();
protected Rect _verticalGroup = new Rect();
protected Rect _widthRect = new Rect();
protected GUIContent _groupTitle = new GUIContent();
protected virtual void DrawGroup(MMFInspectorGroupData groupData, MMF_Feedback feedback)
{
_verticalGroup = EditorGUILayout.BeginVertical();
// we draw a colored line on the left
_leftBorderRect.x = _verticalGroup.xMin + 5;
_leftBorderRect.y = _verticalGroup.yMin - 0;
_leftBorderRect.width = 3f;
_leftBorderRect.height = _verticalGroup.height + 0;
_leftBorderRect.xMin = 15f;
_leftBorderRect.xMax = 18f;
EditorGUI.DrawRect(_leftBorderRect, groupData.GroupColor);
if (groupData.GroupAttribute.RequiresSetup && feedback.RequiresSetup)
{
// we draw a warning sign if needed
_widthRect = EditorGUILayout.GetControlRect(false, 0);
float setupRectWidth = 20f;
_setupRect.x = _widthRect.xMax - setupRectWidth;
_setupRect.y = _verticalGroup.yMin;
_setupRect.width = setupRectWidth;
_setupRect.height = 17f;
EditorGUI.LabelField(_setupRect, MMF_PlayerStyling._setupRequiredIcon);
}
groupData.GroupIsOpen = EditorGUILayout.Foldout(groupData.GroupIsOpen, groupData.GroupAttribute.GroupName, true, MMF_FeedbackInspectorStyle.GroupStyle);
if (groupData.GroupIsOpen)
{
EditorGUI.indentLevel = 0;
for (int i = 0; i < groupData.PropertiesList.Count; i++)
{
DrawVerticalLayout(() => DrawChild(i, feedback), MMF_FeedbackInspectorStyle.BoxChildStyle);
}
}
EditorGUILayout.EndVertical();
void DrawChild(int i, MMF_Feedback feedbackDrawn)
{
if (i > groupData.PropertiesList.Count - 1)
{
return;
}
if ((_hasMMHiddenProperties) && (_mmHiddenPropertiesToHide.Contains(groupData.PropertiesList[i].name)))
{
return;
}
if (!feedback.HasChannel
&& (groupData.PropertiesList[i].name == _channelFieldName
|| groupData.PropertiesList[i].name == _channelModeFieldName
|| groupData.PropertiesList[i].name == _channelDefinitionFieldName))
{
return;
}
_groupTitle.text = ObjectNames.NicifyVariableName(groupData.PropertiesList[i].name);
_groupTitle.tooltip = groupData.PropertiesList[i].tooltip;
if (!DrawCustomInspectors(groupData.PropertiesList[i], feedback))
{
bool shouldDraw = !((groupData.PropertiesList[i].name == _automatedTargetAcquisitionName) &&
(!feedbackDrawn.HasAutomatedTargetAcquisition));
if (shouldDraw)
{
EditorGUILayout.PropertyField(groupData.PropertiesList[i], _groupTitle, true);
}
}
}
}
public static void DrawVerticalLayout(Action action, GUIStyle style)
{
EditorGUILayout.BeginVertical(style);
action();
EditorGUILayout.EndVertical();
}
public void DrawNoGroupInspector(SerializedProperty currentProperty, MMF_Feedback feedback)
{
SerializedProperty endProp = currentProperty.GetEndProperty();
while (currentProperty.NextVisible(true) && !EqualContents(endProp, currentProperty))
{
if (currentProperty.depth <= 2)
{
if (!DrawCustomInspectors(currentProperty, feedback))
{
EditorGUILayout.PropertyField(currentProperty, true);
}
}
}
}
protected GUIContent _tweenCurveGUIContent = new GUIContent("MM Tween Curve");
protected GUIContent _animationCurveGUIContent = new GUIContent("Animation Curve");
protected const string _customInspectorButtonPropertyName = "MMF_Button";
protected const string _customTweenTypePropertyName = "MMTweenType";
protected const string _findPropertyRelativeMMTweenDefinitionType = "MMTweenDefinitionType";
protected const string _mmTweenCurvePropertyName = "MMTweenCurve";
protected const string _curvePropertyName = "Curve";
protected SerializedProperty _mmTweenTypeProperty;
protected MMFConditionAttribute _conditionAttribute;
protected MMFEnumConditionAttribute _enumConditionAttribute;
private bool DrawCustomInspectors(SerializedProperty currentProperty, MMF_Feedback feedback)
{
if (feedback.HasCustomInspectors)
{
switch (currentProperty.type)
{
case _customInspectorButtonPropertyName:
MMF_Button myButton = (MMF_Button)(currentProperty.MMFGetObjectValue());
if (GUILayout.Button(myButton.ButtonText))
{
myButton.TargetMethod();
}
return true;
case _customTweenTypePropertyName:
// if we're displaying a tween type, we need to handle conditions manually
_animationCurveGUIContent.tooltip = currentProperty.tooltip;
_tweenCurveGUIContent.tooltip = currentProperty.tooltip;
_mmTweenTypeProperty = currentProperty.FindPropertyRelative(_findPropertyRelativeMMTweenDefinitionType);
if (_conditionDictionary.TryGetValue(currentProperty.name, out _conditionAttribute))
{
string propertyPath = currentProperty.propertyPath;
string conditionPath = propertyPath.Replace(currentProperty.name, _conditionAttribute.ConditionBoolean);
SerializedProperty sourcePropertyValue = currentProperty.serializedObject.FindProperty(conditionPath);
if (!_conditionAttribute.Negative && !sourcePropertyValue.boolValue)
{
return true;
}
if (_conditionAttribute.Negative && sourcePropertyValue.boolValue)
{
return true;
}
}
if (_enumConditionDictionary.TryGetValue(currentProperty.name, out _enumConditionAttribute))
{
string propertyPath = currentProperty.propertyPath;
string conditionPath = propertyPath.Replace(currentProperty.name, _enumConditionAttribute.ConditionEnum);
SerializedProperty sourcePropertyValue = currentProperty.serializedObject.FindProperty(conditionPath);
if ((sourcePropertyValue != null) && (sourcePropertyValue.propertyType == SerializedPropertyType.Enum))
{
int currentEnum = sourcePropertyValue.enumValueIndex;
if (!_enumConditionAttribute.ContainsBitFlag(currentEnum))
{
return true;
}
}
}
EditorGUILayout.PropertyField(_mmTweenTypeProperty, new GUIContent(currentProperty.displayName, currentProperty.tooltip));
if (_mmTweenTypeProperty.enumValueIndex == 0)
{
EditorGUILayout.PropertyField(currentProperty.FindPropertyRelative(_mmTweenCurvePropertyName), _tweenCurveGUIContent);
}
if (_mmTweenTypeProperty.enumValueIndex == 1)
{
EditorGUILayout.PropertyField(currentProperty.FindPropertyRelative(_curvePropertyName), _animationCurveGUIContent);
}
return true;
}
}
return false;
}
private bool EqualContents(SerializedProperty a, SerializedProperty b)
{
return SerializedProperty.EqualContents(a, b);
}
}
}

View File

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

View File

@@ -0,0 +1,75 @@
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEditor;
using UnityEngine;
namespace MoreMountains.Feedbacks
{
static class MMF_FeedbackInspectorStyle
{
public static GUIStyle ContainerStyle;
public static GUIStyle BoxChildStyle;
public static GUIStyle GroupStyle;
public static GUIStyle TextStyle;
public static bool IsProSkin = EditorGUIUtility.isProSkin;
public static Texture2D GroupClosedTriangle = Resources.Load<Texture2D>("IN foldout focus-6510");
public static Texture2D GroupOpenTriangle = Resources.Load<Texture2D>("IN foldout focus on-5718");
public static Texture2D NoTexture = new Texture2D(0, 0);
static MMF_FeedbackInspectorStyle()
{
// TEXT STYLE --------------------------------------------------------------------------------------------------------------
TextStyle = new GUIStyle(EditorStyles.largeLabel);
TextStyle.richText = true;
TextStyle.contentOffset = new Vector2(0, 25);
//TextStyle.font = Font.CreateDynamicFontFromOSFont(new[] { "Terminus (TTF) for Windows", "Calibri" }, 14);
// GROUP STYLE --------------------------------------------------------------------------------------------------------------
GroupStyle = new GUIStyle(EditorStyles.foldout);
GroupStyle.active.background = GroupClosedTriangle;
GroupStyle.focused.background = GroupClosedTriangle;
GroupStyle.hover.background = GroupClosedTriangle;
GroupStyle.onActive.background = GroupOpenTriangle;
GroupStyle.onFocused.background = GroupOpenTriangle;
GroupStyle.onHover.background = GroupOpenTriangle;
GroupStyle.fontStyle = FontStyle.Bold;
GroupStyle.overflow = new RectOffset(100, 0, 0, 0);
GroupStyle.padding = new RectOffset(20, 0, 0, 0);
// CONTAINER STYLE --------------------------------------------------------------------------------------------------------------
ContainerStyle = new GUIStyle(GUI.skin.box);
ContainerStyle.padding = new RectOffset(20, 0, 0, 0);
// BOX CHILD STYLE --------------------------------------------------------------------------------------------------------------
BoxChildStyle = new GUIStyle(GUI.skin.box);
BoxChildStyle.padding = new RectOffset(0, 0, 0, 0);
BoxChildStyle.margin = new RectOffset(0, 0, 0, 0);
BoxChildStyle.normal.background = NoTexture;
}
static Texture2D MakeTex(int width, int height, Color col)
{
Color[] pix = new Color[width * height];
for (int i = 0; i < pix.Length; ++i)
{
pix[i] = col;
}
Texture2D result = new Texture2D(width, height);
result.SetPixels(pix);
result.Apply();
return result;
}
}
}

View File

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

View File

@@ -0,0 +1,53 @@
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
namespace MoreMountains.Feedbacks
{
/// <summary>
/// An asset to store copy information, as well as global feedback settings.
/// It requires that one (and only one) MMFeedbacksConfiguration asset be created and stored in a Resources folder.
/// That's already done when installing MMFeedbacks.
/// </summary>
[CreateAssetMenu(menuName = "MoreMountains/MMFeedbacks/Configuration", fileName = "MMFeedbacksConfiguration")]
public class MMF_PlayerConfiguration : ScriptableObject
{
private static MMF_PlayerConfiguration _instance;
private static bool _instantiated;
/// <summary>
/// Singleton pattern
/// </summary>
public static MMF_PlayerConfiguration Instance
{
get
{
if (_instantiated)
{
return _instance;
}
string assetName = typeof(MMF_PlayerConfiguration).Name;
MMF_PlayerConfiguration loadedAsset = Resources.Load<MMF_PlayerConfiguration>("MMF_PlayerConfiguration");
_instance = loadedAsset;
_instantiated = true;
return _instance;
}
}
[Header("Help settings")]
/// if this is true, inspector tips will be shown for MMFeedbacks
public bool ShowInspectorTips = true;
/// if this is true, when exiting play mode when KeepPlaymodeChanges is active, it'll turn off automatically, otherwise it'll remain on
public bool AutoDisableKeepPlaymodeChanges = true;
/// if this is true, when exiting play mode when KeepPlaymodeChanges is active, it'll turn off automatically, otherwise it'll remain on
public bool InspectorGroupsExpandedByDefault = true;
private void OnDestroy(){ _instantiated = false; }
}
}

View File

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

View File

@@ -0,0 +1,144 @@
using System;
using System.Collections.Generic;
using UnityEditor;
using System.Linq;
using UnityEngine;
namespace MoreMountains.Feedbacks
{
/// <summary>
/// A helper class to copy and paste feedback properties
/// </summary>
static class MMF_PlayerCopy
{
static public System.Type Type { get; private set; }
public static readonly List<MMF_Feedback> CopiedFeedbacks = new List<MMF_Feedback>();
public static readonly Dictionary<MMF_Player, List<MMF_Feedback>> RuntimeChanges = new Dictionary<MMF_Player, List<MMF_Feedback>>();
static string[] IgnoreList = new string[]
{
"m_ObjectHideFlags",
"m_CorrespondingSourceObject",
"m_PrefabInstance",
"m_PrefabAsset",
"m_GameObject",
"m_Enabled",
"m_EditorHideFlags",
"m_Script",
"m_Name",
"m_EditorClassIdentifier"
};
static MMF_PlayerCopy()
{
EditorApplication.playModeStateChanged += ModeChanged;
}
private static void ModeChanged(PlayModeStateChange playModeState)
{
switch (playModeState)
{
case PlayModeStateChange.ExitingPlayMode:
StoreRuntimeChanges();
break;
case PlayModeStateChange.EnteredEditMode:
ApplyRuntimeChanges();
break;
}
}
private static void StoreRuntimeChanges()
{
foreach (MMF_Player player in MonoBehaviour.FindObjectsOfType<MMF_Player>(true).Where(p => p.KeepPlayModeChanges))
{
MMF_PlayerCopy.StoreRuntimeChanges(player);
}
}
private static void ApplyRuntimeChanges()
{
foreach (MMF_Player player in MonoBehaviour.FindObjectsOfType<MMF_Player>(true).Where(MMF_PlayerCopy.RuntimeChanges.ContainsKey))
{
MMF_PlayerCopy.ApplyRuntimeChanges(player);
}
}
static public bool HasCopy()
{
return CopiedFeedbacks != null && CopiedFeedbacks.Count == 1;
}
static public bool HasMultipleCopies()
{
return CopiedFeedbacks != null && CopiedFeedbacks.Count > 1;
}
static public void Copy(MMF_Feedback feedback)
{
Type feedbackType = feedback.GetType();
MMF_Feedback newFeedback = (MMF_Feedback)Activator.CreateInstance(feedbackType);
EditorUtility.CopySerializedManagedFieldsOnly(feedback, newFeedback);
CopiedFeedbacks.Clear();
CopiedFeedbacks.Add(newFeedback);
}
static public void CopyAll(MMF_Player sourceFeedbacks)
{
CopiedFeedbacks.Clear();
foreach (MMF_Feedback feedback in sourceFeedbacks.FeedbacksList)
{
Type feedbackType = feedback.GetType();
MMF_Feedback newFeedback = (MMF_Feedback)Activator.CreateInstance(feedbackType);
EditorUtility.CopySerializedManagedFieldsOnly(feedback, newFeedback);
CopiedFeedbacks.Add(newFeedback);
}
}
// Multiple Copy ----------------------------------------------------------
static public void PasteAll(MMF_PlayerEditor targetEditor)
{
foreach (MMF_Feedback feedback in MMF_PlayerCopy.CopiedFeedbacks)
{
targetEditor.TargetMmfPlayer.AddFeedback(feedback);
}
CopiedFeedbacks.Clear();
}
// Runtime Changes
static public void StoreRuntimeChanges(MMF_Player player)
{
RuntimeChanges[player] = new List<MMF_Feedback>();
foreach (MMF_Feedback feedback in player.FeedbacksList)
{
Type feedbackType = feedback.GetType();
MMF_Feedback newFeedback = (MMF_Feedback)Activator.CreateInstance(feedbackType);
EditorUtility.CopySerializedManagedFieldsOnly(feedback, newFeedback);
RuntimeChanges[player].Add(newFeedback);
}
}
static public void ApplyRuntimeChanges(MMF_Player player)
{
SerializedObject playerSerialized = new SerializedObject(player);
playerSerialized.Update();
Undo.RecordObject(player, "Replace all feedbacks");
player.FeedbacksList.Clear();
foreach (MMF_Feedback feedback in MMF_PlayerCopy.RuntimeChanges[player])
{
player.AddFeedback(feedback);
}
playerSerialized.ApplyModifiedProperties();
PrefabUtility.RecordPrefabInstancePropertyModifications(player);
if (MMF_PlayerConfiguration.Instance.AutoDisableKeepPlaymodeChanges)
{
playerSerialized.Update();
player.KeepPlayModeChanges = false;
playerSerialized.ApplyModifiedProperties();
}
player.RefreshCache();
}
}
}

View File

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

File diff suppressed because it is too large Load Diff

View File

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

View File

@@ -0,0 +1,444 @@
using UnityEngine;
using UnityEditor;
namespace MoreMountains.Feedbacks
{
/// <summary>
/// A class used to regroup most of the styling options for the MMFeedback editors
/// </summary>
public static class MMF_PlayerStyling
{
public static readonly GUIStyle SmallTickbox = new GUIStyle("ShurikenToggle");
static readonly Color _splitterdark = new Color(0.12f, 0.12f, 0.12f, 1.333f);
static readonly Color _splitterlight = new Color(0.6f, 0.6f, 0.6f, 1.333f);
public static Color Splitter { get { return EditorGUIUtility.isProSkin ? _splitterdark : _splitterlight; } }
static readonly Color _headerbackgrounddark = new Color(0.1f, 0.1f, 0.1f, 0.2f);
static readonly Color _headerbackgroundlight = new Color(1f, 1f, 1f, 0.4f);
public static Color HeaderBackground { get { return EditorGUIUtility.isProSkin ? _headerbackgrounddark : _headerbackgroundlight; } }
static readonly Color _reorderdark = new Color(1f, 1f, 1f, 0.2f);
static readonly Color _reorderlight = new Color(0.1f, 0.1f, 0.1f, 0.2f);
public static Color Reorder { get { return EditorGUIUtility.isProSkin ? _reorderdark : _reorderlight; } }
static readonly Color _timingDark = new Color(1f, 1f, 1f, 0.5f);
static readonly Color _timingLight = new Color(0f, 0f, 0f, 0.5f);
static readonly Color _targetLabelColor = new Color(1f, 1f, 1f, 0.4f);
static readonly Texture2D _paneoptionsicondark;
static readonly Texture2D _paneoptionsiconlight;
private static Rect _splitterRect;
public static Texture2D PaneOptionsIcon { get { return EditorGUIUtility.isProSkin ? _paneoptionsicondark : _paneoptionsiconlight; } }
static MMF_PlayerStyling()
{
_paneoptionsicondark = (Texture2D)EditorGUIUtility.Load("Builtin Skins/DarkSkin/Images/pane options.png");
_paneoptionsiconlight = (Texture2D)EditorGUIUtility.Load("Builtin Skins/LightSkin/Images/pane options.png");
}
private static GUIStyle _timingStyle = new GUIStyle();
private static Rect _backgroundRect;
private static Rect _progressRect;
private static Rect _timingRect;
private static Rect _reorderRect;
private static Rect _labelRect;
private static Rect _foldoutRect;
private static Rect _toggleRect;
private static Rect _directionRect;
private static Rect _setupRect;
private static Texture2D _menuIcon;
private static Rect _menuRect;
private static Rect _workRect;
private static Rect _colorRect;
private static Rect _genericMenuRect;
private static Color _headerBackgroundColor;
private static Color _barColor;
private static GUIContent _directionUpIcon;
private static GUIStyle _targetLabelStyle;
private static GUIContent _directionDownIcon;
public static GUIContent _setupRequiredIcon;
private static GenericMenu _genericMenu;
public static void CacheStyling()
{
_menuIcon = PaneOptionsIcon;
_menuRect = new Rect();
_colorRect = new Rect();
_directionRect = new Rect();
_setupRect = new Rect();
_timingRect = new Rect();
_directionUpIcon = new GUIContent(Resources.Load("FeelArrowUp") as Texture);
_directionDownIcon = new GUIContent(Resources.Load("FeelArrowDown") as Texture);
_setupRequiredIcon = new GUIContent(Resources.Load("FeelSetupRequired") as Texture);
_genericMenu = new GenericMenu();
_targetLabelStyle = new GUIStyle(GUI.skin.label);
_targetLabelStyle.alignment = TextAnchor.MiddleRight;
_targetLabelStyle.normal.textColor = _targetLabelColor;
}
/// <summary>
/// Simply drow a splitter line and a title bellow
/// </summary>
static public void DrawSection(string title)
{
EditorGUILayout.Space();
DrawSplitter();
EditorGUILayout.Space();
EditorGUILayout.Space();
EditorGUILayout.LabelField(title, EditorStyles.boldLabel);
}
/// <summary>
/// Draw a separator line
/// </summary>
static public void DrawSplitter()
{
// Helper to draw a separator line
_splitterRect = GUILayoutUtility.GetRect(1f, 1f);
_splitterRect.xMin = 0f;
_splitterRect.width += 4f;
if (Event.current.type != EventType.Repaint)
{
return;
}
EditorGUI.DrawRect(_splitterRect, Splitter);
}
/// <summary>
/// Draw a header similar to the one used for the post-process stack
/// </summary>
static public Rect DrawSimpleHeader(ref bool expanded, ref bool activeField, string title)
{
var e = Event.current;
// Initialize Rects
_backgroundRect = GUILayoutUtility.GetRect(1f, 17f);
_reorderRect = _backgroundRect;
_reorderRect.xMin -= 8f;
_reorderRect.y += 5f;
_reorderRect.width = 9f;
_reorderRect.height = 9f;
_labelRect = _backgroundRect;
_labelRect.xMin += 32f;
_labelRect.xMax -= 20f;
_foldoutRect = _backgroundRect;
_foldoutRect.y += 1f;
_foldoutRect.width = 13f;
_foldoutRect.height = 13f;
_toggleRect = _backgroundRect;
_toggleRect.x += 16f;
_toggleRect.y += 2f;
_toggleRect.width = 13f;
_toggleRect.height = 13f;
// Background rect should be full-width
_backgroundRect.xMin = 0f;
_backgroundRect.width += 4f;
// Background
EditorGUI.DrawRect(_backgroundRect, HeaderBackground);
// Foldout
expanded = GUI.Toggle(_foldoutRect, expanded, GUIContent.none, EditorStyles.foldout);
// Title
EditorGUI.LabelField(_labelRect, title, EditorStyles.boldLabel);
// Active checkbox
activeField = GUI.Toggle(_toggleRect, activeField, GUIContent.none, SmallTickbox);
// Handle events
if (e.type == EventType.MouseDown && _labelRect.Contains(e.mousePosition) && e.button == 0)
{
expanded = !expanded;
e.Use();
}
return _backgroundRect;
}
/// <summary>
/// Draw a header similar to the one used for the post-process stack
/// </summary>
static public Rect DrawHeader(ref bool expanded, ref bool activeField, string title, Color feedbackColor, System.Action<GenericMenu> fillGenericMenu,
float startedAt, float duration, float totalDuration, MMFeedbackTiming timing, bool pause, bool requiresSetup, string requiredTarget, Color displayColor,
bool displayFullHeaderColor, MMF_Player host)
{
float thisTime = timing.TimescaleMode == TimescaleModes.Scaled ? Time.time : Time.unscaledTime;
float thisDeltaTime = timing.TimescaleMode == TimescaleModes.Scaled ? Time.deltaTime : Time.unscaledDeltaTime;
if (host.ForceTimescaleMode)
{
thisTime = host.ForcedTimescaleMode == TimescaleModes.Scaled ? Time.time : Time.unscaledTime;
thisDeltaTime = host.ForcedTimescaleMode == TimescaleModes.Scaled ? Time.deltaTime : Time.unscaledDeltaTime;
}
var e = Event.current;
// Initialize Rects
_backgroundRect = GUILayoutUtility.GetRect(1f, 17f);
_progressRect = GUILayoutUtility.GetRect(1f, 2f);
var offset = 4f;
_reorderRect = _backgroundRect;
_reorderRect.xMin -= 8f;
_reorderRect.y += 5f;
_reorderRect.width = 9f;
_reorderRect.height = 9f;
_labelRect = _backgroundRect;
_labelRect.xMin += 32f + offset;
_labelRect.xMax -= 20f;
_foldoutRect = _backgroundRect;
_foldoutRect.y += 1f;
_foldoutRect.xMin += offset;
_foldoutRect.width = 13f;
_foldoutRect.height = 13f;
_toggleRect = _backgroundRect;
_toggleRect.x += 16f;
_toggleRect.xMin += offset;
_toggleRect.y += 2f;
_toggleRect.width = 13f;
_toggleRect.height = 13f;
_timingStyle.normal.textColor = EditorGUIUtility.isProSkin ? _timingDark : _timingLight;
_timingStyle.alignment = TextAnchor.MiddleRight;
_colorRect.x = _labelRect.xMin;
_colorRect.y = _labelRect.yMin;
_colorRect.width = 5f;
_colorRect.height = 17f;
_colorRect.xMin = 0f;
_colorRect.xMax = 5f;
EditorGUI.DrawRect(_colorRect, feedbackColor);
// Background rect should be full-width
_backgroundRect.xMin = 0f;
_backgroundRect.width += 4f;
_progressRect.xMin = 0f;
_progressRect.width += 4f;
_headerBackgroundColor = Color.white;
// Background - if color is white we draw the default color
if (!displayFullHeaderColor)
{
_headerBackgroundColor = HeaderBackground;
}
else
{
_headerBackgroundColor = feedbackColor;
}
if (displayColor != Color.black)
{
_headerBackgroundColor = displayColor;
}
EditorGUI.DrawRect(_backgroundRect, _headerBackgroundColor);
// Foldout
expanded = GUI.Toggle(_foldoutRect, expanded, GUIContent.none, EditorStyles.foldout);
// Title ----------------------------------------------------------------------------------------------------
using (new EditorGUI.DisabledScope(!activeField))
{
EditorGUI.LabelField(_labelRect, title, EditorStyles.boldLabel);
}
// Direction ----------------------------------------------------------------------------------------------
float directionRectWidth = 70f;
_directionRect.x = _labelRect.xMax - directionRectWidth;
_directionRect.y = _labelRect.yMin;
_directionRect.width = directionRectWidth;
_directionRect.height = 17f;
_directionRect.xMin = _labelRect.xMax - directionRectWidth;
_directionRect.xMax = _labelRect.xMax;
if (timing.MMFeedbacksDirectionCondition == MMFeedbackTiming.MMFeedbacksDirectionConditions.OnlyWhenBackwards)
{
EditorGUI.LabelField(_directionRect, _directionUpIcon);
}
if (timing.MMFeedbacksDirectionCondition == MMFeedbackTiming.MMFeedbacksDirectionConditions.OnlyWhenForwards)
{
EditorGUI.LabelField(_directionRect, _directionDownIcon);
}
if (!host.DisplayFullDurationDetails)
{
if (requiresSetup)
{
float setupRectWidth = 90f;
_setupRect.x = _labelRect.xMax - setupRectWidth;
_setupRect.y = _labelRect.yMin;
_setupRect.width = setupRectWidth;
_setupRect.height = 17f;
_setupRect.xMin = _labelRect.xMax - setupRectWidth;
_setupRect.xMax = _labelRect.xMax;
EditorGUI.LabelField(_setupRect, _setupRequiredIcon);
}
else
{
// otherwise we draw the name of our target
float setupRectWidth = _labelRect.width / 2f;
_setupRect.x = _labelRect.xMax - setupRectWidth - 73f;
_setupRect.y = _labelRect.yMin;
_setupRect.width = setupRectWidth;
_setupRect.height = 17f;
EditorGUI.LabelField(_setupRect, requiredTarget, _targetLabelStyle);
}
}
// Time -----------------------------------------------------------------------------------------------------
string timingInfo = "";
bool displayTotal = false;
if (host.DisplayFullDurationDetails)
{
if (timing.InitialDelay != 0)
{
timingInfo += host.ApplyTimeMultiplier(timing.InitialDelay).ToString() + "s + ";
displayTotal = true;
}
timingInfo += duration.ToString("F2") + "s";
if (timing.NumberOfRepeats != 0)
{
float delayBetweenRepeats = host.ApplyTimeMultiplier(timing.DelayBetweenRepeats);
timingInfo += " + "+ timing.NumberOfRepeats.ToString() + " x ";
timingInfo += host.ApplyTimeMultiplier(timing.DelayBetweenRepeats) + "s";
displayTotal = true;
}
if (displayTotal)
{
timingInfo += " = " + totalDuration.ToString("F2") + "s";
}
}
else
{
timingInfo = totalDuration.ToString("F2") + "s";
}
float timingRectWidth = 150f;
_timingRect.x = _labelRect.xMax - timingRectWidth;
_timingRect.y = _labelRect.yMin;
_timingRect.width = timingRectWidth;
_timingRect.height = 17f;
_timingRect.xMin = _labelRect.xMax - timingRectWidth;
_timingRect.xMax = _labelRect.xMax;
EditorGUI.LabelField(_timingRect, timingInfo, _timingStyle);
// Progress bar
if (totalDuration == 0f)
{
totalDuration = 0.1f;
}
if (startedAt == 0f)
{
startedAt = 0.001f;
}
if (host.IsPlaying && (startedAt > 0f) && (thisTime - startedAt < totalDuration + 0.05f))
{
float fullWidth = _progressRect.width;
if (totalDuration == 0f) { totalDuration = 0.1f; }
float percent = ((thisTime - startedAt) / totalDuration) * 100f;
_progressRect.width = percent * fullWidth / 100f;
_barColor = Color.white;
if (thisTime - startedAt > totalDuration)
{
_barColor = Color.yellow;
}
EditorGUI.DrawRect(_progressRect, _barColor);
}
else
{
EditorGUI.DrawRect(_progressRect, _headerBackgroundColor);
}
// Active checkbox
activeField = GUI.Toggle(_toggleRect, activeField, GUIContent.none, SmallTickbox);
_menuRect.x = _labelRect.xMax + 4f;
_menuRect.y = _labelRect.y + 4f;
_menuRect.width = _menuIcon.width;
_menuRect.height = _menuIcon.height;
// Dropdown menu icon
GUI.DrawTexture(_menuRect, _menuIcon);
for(int i = 0; i < 3; i++)
{
_workRect = _reorderRect;
_workRect.height = 1;
_workRect.y = _reorderRect.y + _reorderRect.height * (i / 3.0f);
EditorGUI.DrawRect(_workRect, Reorder);
}
// Handle events
if (e.type == EventType.MouseDown)
{
if (_menuRect.Contains(e.mousePosition))
{
fillGenericMenu(_genericMenu);
_genericMenuRect.x = _menuRect.x;
_genericMenuRect.y = _menuRect.yMax;
_genericMenuRect.width = 0f;
_genericMenuRect.height = 0f;
_genericMenu.DropDown(_genericMenuRect);
e.Use();
}
}
if (e.type == EventType.MouseDown && _labelRect.Contains(e.mousePosition) && e.button == 0)
{
expanded = !expanded;
e.Use();
}
return _backgroundRect;
}
public static void CreateColorTexture(this Texture2D texture2D, Color32 color)
{
Color32[] colorArray = texture2D.GetPixels32();
for (int i = 0; i < colorArray.Length; ++i)
{
colorArray[i] = color;
}
texture2D.SetPixels32(colorArray);
texture2D.Apply();
}
}
}

View File

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

View File

@@ -0,0 +1,351 @@
using UnityEngine;
using UnityEditor;
namespace MoreMountains.Feedbacks
{
/// <summary>
/// A class used to regroup most of the styling options for the MMFeedback editors
/// </summary>
public static class MMFeedbackStyling
{
public static readonly GUIStyle SmallTickbox = new GUIStyle("ShurikenToggle");
static readonly Color _splitterdark = new Color(0.12f, 0.12f, 0.12f, 1.333f);
static readonly Color _splitterlight = new Color(0.6f, 0.6f, 0.6f, 1.333f);
public static Color Splitter { get { return EditorGUIUtility.isProSkin ? _splitterdark : _splitterlight; } }
static readonly Color _headerbackgrounddark = new Color(0.1f, 0.1f, 0.1f, 0.2f);
static readonly Color _headerbackgroundlight = new Color(1f, 1f, 1f, 0.4f);
public static Color HeaderBackground { get { return EditorGUIUtility.isProSkin ? _headerbackgrounddark : _headerbackgroundlight; } }
static readonly Color _reorderdark = new Color(1f, 1f, 1f, 0.2f);
static readonly Color _reorderlight = new Color(0.1f, 0.1f, 0.1f, 0.2f);
public static Color Reorder { get { return EditorGUIUtility.isProSkin ? _reorderdark : _reorderlight; } }
static readonly Color _timingDark = new Color(1f, 1f, 1f, 0.5f);
static readonly Color _timingLight = new Color(0f, 0f, 0f, 0.5f);
static readonly Texture2D _paneoptionsicondark;
static readonly Texture2D _paneoptionsiconlight;
public static Texture2D PaneOptionsIcon { get { return EditorGUIUtility.isProSkin ? _paneoptionsicondark : _paneoptionsiconlight; } }
static MMFeedbackStyling()
{
_paneoptionsicondark = (Texture2D)EditorGUIUtility.Load("Builtin Skins/DarkSkin/Images/pane options.png");
_paneoptionsiconlight = (Texture2D)EditorGUIUtility.Load("Builtin Skins/LightSkin/Images/pane options.png");
}
private static GUIStyle _timingStyle = new GUIStyle();
/// <summary>
/// Simply drow a splitter line and a title bellow
/// </summary>
static public void DrawSection(string title)
{
EditorGUILayout.Space();
DrawSplitter();
EditorGUILayout.Space();
EditorGUILayout.Space();
EditorGUILayout.LabelField(title, EditorStyles.boldLabel);
}
/// <summary>
/// Draw a separator line
/// </summary>
static public void DrawSplitter()
{
// Helper to draw a separator line
var rect = GUILayoutUtility.GetRect(1f, 1f);
rect.xMin = 0f;
rect.width += 4f;
if (Event.current.type != EventType.Repaint)
return;
EditorGUI.DrawRect(rect, Splitter);
}
/// <summary>
/// Draw a header similar to the one used for the post-process stack
/// </summary>
static public Rect DrawSimpleHeader(ref bool expanded, ref bool activeField, string title)
{
var e = Event.current;
// Initialize Rects
var backgroundRect = GUILayoutUtility.GetRect(1f, 17f);
var reorderRect = backgroundRect;
reorderRect.xMin -= 8f;
reorderRect.y += 5f;
reorderRect.width = 9f;
reorderRect.height = 9f;
var labelRect = backgroundRect;
labelRect.xMin += 32f;
labelRect.xMax -= 20f;
var foldoutRect = backgroundRect;
foldoutRect.y += 1f;
foldoutRect.width = 13f;
foldoutRect.height = 13f;
var toggleRect = backgroundRect;
toggleRect.x += 16f;
toggleRect.y += 2f;
toggleRect.width = 13f;
toggleRect.height = 13f;
var menuIcon = PaneOptionsIcon;
var menuRect = new Rect(labelRect.xMax + 4f, labelRect.y + 4f, menuIcon.width, menuIcon.height);
// Background rect should be full-width
backgroundRect.xMin = 0f;
backgroundRect.width += 4f;
// Background
EditorGUI.DrawRect(backgroundRect, HeaderBackground);
// Foldout
expanded = GUI.Toggle(foldoutRect, expanded, GUIContent.none, EditorStyles.foldout);
// Title
EditorGUI.LabelField(labelRect, title, EditorStyles.boldLabel);
// Active checkbox
activeField = GUI.Toggle(toggleRect, activeField, GUIContent.none, SmallTickbox);
// Handle events
if (e.type == EventType.MouseDown && labelRect.Contains(e.mousePosition) && e.button == 0)
{
expanded = !expanded;
e.Use();
}
return backgroundRect;
}
/// <summary>
/// Draw a header similar to the one used for the post-process stack
/// </summary>
static public Rect DrawHeader(ref bool expanded, ref bool activeField, string title, Color feedbackColor, System.Action<GenericMenu> fillGenericMenu,
float startedAt, float duration, float totalDuration, MMFeedbackTiming timing, bool pause, MMFeedbacks host)
{
float thisTime = timing.TimescaleMode == TimescaleModes.Scaled ? Time.time : Time.unscaledTime;
float thisDeltaTime = timing.TimescaleMode == TimescaleModes.Scaled ? Time.deltaTime : Time.unscaledDeltaTime;
var e = Event.current;
// Initialize Rects
var backgroundRect = GUILayoutUtility.GetRect(1f, 17f);
var progressRect = GUILayoutUtility.GetRect(1f, 2f);
var offset = 4f;
var reorderRect = backgroundRect;
reorderRect.xMin -= 8f;
reorderRect.y += 5f;
reorderRect.width = 9f;
reorderRect.height = 9f;
var labelRect = backgroundRect;
labelRect.xMin += 32f + offset;
labelRect.xMax -= 20f;
var foldoutRect = backgroundRect;
foldoutRect.y += 1f;
foldoutRect.xMin += offset;
foldoutRect.width = 13f;
foldoutRect.height = 13f;
var toggleRect = backgroundRect;
toggleRect.x += 16f;
toggleRect.xMin += offset;
toggleRect.y += 2f;
toggleRect.width = 13f;
toggleRect.height = 13f;
var menuIcon = PaneOptionsIcon;
var menuRect = new Rect(labelRect.xMax + 4f, labelRect.y + 4f, menuIcon.width, menuIcon.height);
_timingStyle.normal.textColor = EditorGUIUtility.isProSkin ? _timingDark : _timingLight;
_timingStyle.alignment = TextAnchor.MiddleRight;
var colorRect = new Rect(labelRect.xMin, labelRect.yMin, 5f, 17f);
colorRect.xMin = 0f;
colorRect.xMax = 5f;
EditorGUI.DrawRect(colorRect, feedbackColor);
// Background rect should be full-width
backgroundRect.xMin = 0f;
backgroundRect.width += 4f;
progressRect.xMin = 0f;
progressRect.width += 4f;
Color headerBackgroundColor = Color.white;
// Background - if color is white we draw the default color
if (!pause)
{
headerBackgroundColor = HeaderBackground;
}
else
{
headerBackgroundColor = feedbackColor;
}
EditorGUI.DrawRect(backgroundRect, headerBackgroundColor);
// Foldout
expanded = GUI.Toggle(foldoutRect, expanded, GUIContent.none, EditorStyles.foldout);
// Title ----------------------------------------------------------------------------------------------------
using (new EditorGUI.DisabledScope(!activeField))
{
EditorGUI.LabelField(labelRect, title, EditorStyles.boldLabel);
}
// Direction ----------------------------------------------------------------------------------------------
float directionRectWidth = 70f;
var directionRect = new Rect(labelRect.xMax - directionRectWidth, labelRect.yMin, directionRectWidth, 17f);
directionRect.xMin = labelRect.xMax - directionRectWidth;
directionRect.xMax = labelRect.xMax;
if (timing.MMFeedbacksDirectionCondition == MMFeedbackTiming.MMFeedbacksDirectionConditions.OnlyWhenBackwards)
{
Texture arrowUpIcon = Resources.Load("FeelArrowUp") as Texture;
GUIContent directionIcon = new GUIContent(arrowUpIcon);
EditorGUI.LabelField(directionRect, directionIcon);
}
if (timing.MMFeedbacksDirectionCondition == MMFeedbackTiming.MMFeedbacksDirectionConditions.OnlyWhenForwards)
{
Texture arrowDownIcon = Resources.Load("FeelArrowDown") as Texture;
GUIContent directionIcon = new GUIContent(arrowDownIcon);
EditorGUI.LabelField(directionRect, directionIcon);
}
// Time -----------------------------------------------------------------------------------------------------
string timingInfo = "";
bool displayTotal = false;
if (host.DisplayFullDurationDetails)
{
if (timing.InitialDelay != 0)
{
timingInfo += host.ApplyTimeMultiplier(timing.InitialDelay).ToString() + "s + ";
displayTotal = true;
}
timingInfo += duration.ToString("F2") + "s";
if (timing.NumberOfRepeats != 0)
{
float delayBetweenRepeats = host.ApplyTimeMultiplier(timing.DelayBetweenRepeats);
timingInfo += " + "+ timing.NumberOfRepeats.ToString() + " x ";
if (timing.DelayBetweenRepeats > 0)
{
timingInfo += "(";
}
timingInfo += duration + "s";
if (timing.DelayBetweenRepeats > 0)
{
timingInfo += " + " + host.ApplyTimeMultiplier(timing.DelayBetweenRepeats) + "s )";
}
displayTotal = true;
}
if (displayTotal)
{
timingInfo += " = " + totalDuration.ToString("F2") + "s";
}
}
else
{
timingInfo = totalDuration.ToString("F2") + "s";
}
//"[ 2s + 3 x (4s + 1s) ]"
float timingRectWidth = 150f;
var timingRect = new Rect(labelRect.xMax - timingRectWidth, labelRect.yMin, timingRectWidth, 17f);
timingRect.xMin = labelRect.xMax - timingRectWidth;
timingRect.xMax = labelRect.xMax;
EditorGUI.LabelField(timingRect, timingInfo, _timingStyle);
// Progress bar
if (totalDuration == 0f)
{
totalDuration = 0.1f;
}
if (startedAt == 0f)
{
startedAt = 0.001f;
}
if ((startedAt > 0f) && (thisTime - startedAt < totalDuration + 0.05f))
{
float fullWidth = progressRect.width;
if (totalDuration == 0f) { totalDuration = 0.1f; }
float percent = ((thisTime - startedAt) / totalDuration) * 100f;
progressRect.width = percent * fullWidth / 100f;
Color barColor = Color.white;
if (thisTime - startedAt > totalDuration)
{
barColor = Color.yellow;
}
EditorGUI.DrawRect(progressRect, barColor);
}
else
{
EditorGUI.DrawRect(progressRect, headerBackgroundColor);
}
// Active checkbox
activeField = GUI.Toggle(toggleRect, activeField, GUIContent.none, SmallTickbox);
// Dropdown menu icon
GUI.DrawTexture(menuRect, menuIcon);
for(int i = 0; i < 3; i++)
{
Rect r = reorderRect;
r.height = 1;
r.y = reorderRect.y + reorderRect.height * (i / 3.0f);
EditorGUI.DrawRect(r, Reorder);
}
// Handle events
if (e.type == EventType.MouseDown)
{
if (menuRect.Contains(e.mousePosition))
{
var menu = new GenericMenu();
fillGenericMenu(menu);
menu.DropDown(new Rect(new Vector2(menuRect.x, menuRect.yMax), Vector2.zero));
e.Use();
}
}
if (e.type == EventType.MouseDown && labelRect.Contains(e.mousePosition) && e.button == 0)
{
expanded = !expanded;
e.Use();
}
return backgroundRect;
}
}
}

View File

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

View File

@@ -0,0 +1,396 @@
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
namespace MoreMountains.Feedbacks
{
/// <summary>
/// Color helpers
/// </summary>
public static class MMFeedbacksColors
{
// via https://gist.github.com/LotteMakesStuff/f7ce43f11e545a151b95b5e87f76304c
// NOTE: The follwing color names come from the CSS3 specification, Section 4.3 Extended Color Keywords
// http://www.w3.org/TR/css3-color/#svg-color
public static readonly Color AliceBlue = new Color32(240, 248, 255, 255);
public static readonly Color AntiqueWhite = new Color32(250, 235, 215, 255);
public static readonly Color Aqua = new Color32(0, 255, 255, 255);
public static readonly Color Aquamarine = new Color32(127, 255, 212, 255);
public static readonly Color Azure = new Color32(240, 255, 255, 255);
public static readonly Color Beige = new Color32(245, 245, 220, 255);
public static readonly Color Bisque = new Color32(255, 228, 196, 255);
public static readonly Color Black = new Color32(0, 0, 0, 255);
public static readonly Color BlanchedAlmond = new Color32(255, 235, 205, 255);
public static readonly Color Blue = new Color32(0, 0, 255, 255);
public static readonly Color BlueViolet = new Color32(138, 43, 226, 255);
public static readonly Color Brown = new Color32(165, 42, 42, 255);
public static readonly Color Burlywood = new Color32(222, 184, 135, 255);
public static readonly Color CadetBlue = new Color32(95, 158, 160, 255);
public static readonly Color Chartreuse = new Color32(127, 255, 0, 255);
public static readonly Color Chocolate = new Color32(210, 105, 30, 255);
public static readonly Color Coral = new Color32(255, 127, 80, 255);
public static readonly Color CornflowerBlue = new Color32(100, 149, 237, 255);
public static readonly Color Cornsilk = new Color32(255, 248, 220, 255);
public static readonly Color Crimson = new Color32(220, 20, 60, 255);
public static readonly Color Cyan = new Color32(0, 255, 255, 255);
public static readonly Color DarkBlue = new Color32(0, 0, 139, 255);
public static readonly Color DarkCyan = new Color32(0, 139, 139, 255);
public static readonly Color DarkGoldenrod = new Color32(184, 134, 11, 255);
public static readonly Color DarkGray = new Color32(169, 169, 169, 255);
public static readonly Color DarkGreen = new Color32(0, 100, 0, 255);
public static readonly Color DarkKhaki = new Color32(189, 183, 107, 255);
public static readonly Color DarkMagenta = new Color32(139, 0, 139, 255);
public static readonly Color DarkOliveGreen = new Color32(85, 107, 47, 255);
public static readonly Color DarkOrange = new Color32(255, 140, 0, 255);
public static readonly Color DarkOrchid = new Color32(153, 50, 204, 255);
public static readonly Color DarkRed = new Color32(139, 0, 0, 255);
public static readonly Color DarkSalmon = new Color32(233, 150, 122, 255);
public static readonly Color DarkSeaGreen = new Color32(143, 188, 143, 255);
public static readonly Color DarkSlateBlue = new Color32(72, 61, 139, 255);
public static readonly Color DarkSlateGray = new Color32(47, 79, 79, 255);
public static readonly Color DarkTurquoise = new Color32(0, 206, 209, 255);
public static readonly Color DarkViolet = new Color32(148, 0, 211, 255);
public static readonly Color DeepPink = new Color32(255, 20, 147, 255);
public static readonly Color DeepSkyBlue = new Color32(0, 191, 255, 255);
public static readonly Color DimGray = new Color32(105, 105, 105, 255);
public static readonly Color DodgerBlue = new Color32(30, 144, 255, 255);
public static readonly Color FireBrick = new Color32(178, 34, 34, 255);
public static readonly Color FloralWhite = new Color32(255, 250, 240, 255);
public static readonly Color ForestGreen = new Color32(34, 139, 34, 255);
public static readonly Color Fuchsia = new Color32(255, 0, 255, 255);
public static readonly Color Gainsboro = new Color32(220, 220, 220, 255);
public static readonly Color GhostWhite = new Color32(248, 248, 255, 255);
public static readonly Color Gold = new Color32(255, 215, 0, 255);
public static readonly Color Goldenrod = new Color32(218, 165, 32, 255);
public static readonly Color Gray = new Color32(128, 128, 128, 255);
public static readonly Color Green = new Color32(0, 128, 0, 255);
public static readonly Color GreenYellow = new Color32(173, 255, 47, 255);
public static readonly Color Honeydew = new Color32(240, 255, 240, 255);
public static readonly Color HotPink = new Color32(255, 105, 180, 255);
public static readonly Color IndianRed = new Color32(205, 92, 92, 255);
public static readonly Color Indigo = new Color32(75, 0, 130, 255);
public static readonly Color Ivory = new Color32(255, 255, 240, 255);
public static readonly Color Khaki = new Color32(240, 230, 140, 255);
public static readonly Color Lavender = new Color32(230, 230, 250, 255);
public static readonly Color Lavenderblush = new Color32(255, 240, 245, 255);
public static readonly Color LawnGreen = new Color32(124, 252, 0, 255);
public static readonly Color LemonChiffon = new Color32(255, 250, 205, 255);
public static readonly Color LightBlue = new Color32(173, 216, 230, 255);
public static readonly Color LightCoral = new Color32(240, 128, 128, 255);
public static readonly Color LightCyan = new Color32(224, 255, 255, 255);
public static readonly Color LightGoldenodYellow = new Color32(250, 250, 210, 255);
public static readonly Color LightGray = new Color32(211, 211, 211, 255);
public static readonly Color LightGreen = new Color32(144, 238, 144, 255);
public static readonly Color LightPink = new Color32(255, 182, 193, 255);
public static readonly Color LightSalmon = new Color32(255, 160, 122, 255);
public static readonly Color LightSeaGreen = new Color32(32, 178, 170, 255);
public static readonly Color LightSkyBlue = new Color32(135, 206, 250, 255);
public static readonly Color LightSlateGray = new Color32(119, 136, 153, 255);
public static readonly Color LightSteelBlue = new Color32(176, 196, 222, 255);
public static readonly Color LightYellow = new Color32(255, 255, 224, 255);
public static readonly Color Lime = new Color32(0, 255, 0, 255);
public static readonly Color LimeGreen = new Color32(50, 205, 50, 255);
public static readonly Color Linen = new Color32(250, 240, 230, 255);
public static readonly Color Magenta = new Color32(255, 0, 255, 255);
public static readonly Color Maroon = new Color32(128, 0, 0, 255);
public static readonly Color MediumAquamarine = new Color32(102, 205, 170, 255);
public static readonly Color MediumBlue = new Color32(0, 0, 205, 255);
public static readonly Color MediumOrchid = new Color32(186, 85, 211, 255);
public static readonly Color MediumPurple = new Color32(147, 112, 219, 255);
public static readonly Color MediumSeaGreen = new Color32(60, 179, 113, 255);
public static readonly Color MediumSlateBlue = new Color32(123, 104, 238, 255);
public static readonly Color MediumSpringGreen = new Color32(0, 250, 154, 255);
public static readonly Color MediumTurquoise = new Color32(72, 209, 204, 255);
public static readonly Color MediumVioletRed = new Color32(199, 21, 133, 255);
public static readonly Color MidnightBlue = new Color32(25, 25, 112, 255);
public static readonly Color Mintcream = new Color32(245, 255, 250, 255);
public static readonly Color MistyRose = new Color32(255, 228, 225, 255);
public static readonly Color Moccasin = new Color32(255, 228, 181, 255);
public static readonly Color NavajoWhite = new Color32(255, 222, 173, 255);
public static readonly Color Navy = new Color32(0, 0, 128, 255);
public static readonly Color OldLace = new Color32(253, 245, 230, 255);
public static readonly Color Olive = new Color32(128, 128, 0, 255);
public static readonly Color Olivedrab = new Color32(107, 142, 35, 255);
public static readonly Color Orange = new Color32(255, 165, 0, 255);
public static readonly Color Orangered = new Color32(255, 69, 0, 255);
public static readonly Color Orchid = new Color32(218, 112, 214, 255);
public static readonly Color PaleGoldenrod = new Color32(238, 232, 170, 255);
public static readonly Color PaleGreen = new Color32(152, 251, 152, 255);
public static readonly Color PaleTurquoise = new Color32(175, 238, 238, 255);
public static readonly Color PaleVioletred = new Color32(219, 112, 147, 255);
public static readonly Color PapayaWhip = new Color32(255, 239, 213, 255);
public static readonly Color PeachPuff = new Color32(255, 218, 185, 255);
public static readonly Color Peru = new Color32(205, 133, 63, 255);
public static readonly Color Pink = new Color32(255, 192, 203, 255);
public static readonly Color Plum = new Color32(221, 160, 221, 255);
public static readonly Color PowderBlue = new Color32(176, 224, 230, 255);
public static readonly Color Purple = new Color32(128, 0, 128, 255);
public static readonly Color Red = new Color32(255, 0, 0, 255);
public static readonly Color RosyBrown = new Color32(188, 143, 143, 255);
public static readonly Color RoyalBlue = new Color32(65, 105, 225, 255);
public static readonly Color SaddleBrown = new Color32(139, 69, 19, 255);
public static readonly Color Salmon = new Color32(250, 128, 114, 255);
public static readonly Color SandyBrown = new Color32(244, 164, 96, 255);
public static readonly Color SeaGreen = new Color32(46, 139, 87, 255);
public static readonly Color Seashell = new Color32(255, 245, 238, 255);
public static readonly Color Sienna = new Color32(160, 82, 45, 255);
public static readonly Color Silver = new Color32(192, 192, 192, 255);
public static readonly Color SkyBlue = new Color32(135, 206, 235, 255);
public static readonly Color SlateBlue = new Color32(106, 90, 205, 255);
public static readonly Color SlateGray = new Color32(112, 128, 144, 255);
public static readonly Color Snow = new Color32(255, 250, 250, 255);
public static readonly Color SpringGreen = new Color32(0, 255, 127, 255);
public static readonly Color SteelBlue = new Color32(70, 130, 180, 255);
public static readonly Color Tan = new Color32(210, 180, 140, 255);
public static readonly Color Teal = new Color32(0, 128, 128, 255);
public static readonly Color Thistle = new Color32(216, 191, 216, 255);
public static readonly Color Tomato = new Color32(255, 99, 71, 255);
public static readonly Color Turquoise = new Color32(64, 224, 208, 255);
public static readonly Color Violet = new Color32(238, 130, 238, 255);
public static readonly Color Wheat = new Color32(245, 222, 179, 255);
public static readonly Color White = new Color32(255, 255, 255, 255);
public static readonly Color WhiteSmoke = new Color32(245, 245, 245, 255);
public static readonly Color Yellow = new Color32(255, 255, 0, 255);
public static readonly Color YellowGreen = new Color32(154, 205, 50, 255);
public static readonly Color ReunoYellow = new Color32(255, 196, 0, 255);
public static readonly Color BestRed = new Color32(255, 24, 0, 255);
public static Dictionary<int, Color> ColorDictionary;
public static Color RandomColor()
{
int random = Random.Range(0, 140);
return GetColorAt(random);
}
public static Color GetColorAt(int index)
{
if (ColorDictionary == null)
{
InitializeDictionary();
}
if (index < ColorDictionary.Count)
{
return ColorDictionary[index];
}
else
{
return Color.white;
}
}
public static void InitializeDictionary()
{
ColorDictionary = new Dictionary<int, Color>
{
{ 0, AliceBlue },
{ 1, AntiqueWhite },
{ 2, Aqua },
{ 3, Aquamarine },
{ 4, Azure },
{ 5, Beige },
{ 6, Bisque },
{ 7, Black },
{ 8, BlanchedAlmond },
{ 9, Blue },
{ 10, BlueViolet },
{ 11, Brown },
{ 12, Burlywood },
{ 13, CadetBlue },
{ 14, Chartreuse },
{ 15, Chocolate },
{ 16, Coral },
{ 17, CornflowerBlue },
{ 18, Cornsilk },
{ 19, Crimson },
{ 20, Cyan },
{ 21, DarkBlue },
{ 22, DarkCyan },
{ 23, DarkGoldenrod },
{ 24, DarkGray },
{ 25, DarkGreen },
{ 26, DarkKhaki },
{ 27, DarkMagenta },
{ 28, DarkOliveGreen },
{ 29, DarkOrange },
{ 30, DarkOrchid },
{ 31, DarkRed },
{ 32, DarkSalmon },
{ 33, DarkSeaGreen },
{ 34, DarkSlateBlue },
{ 35, DarkSlateGray },
{ 36, DarkTurquoise },
{ 37, DarkViolet },
{ 38, DeepPink },
{ 39, DeepSkyBlue },
{ 40, DimGray },
{ 41, DodgerBlue },
{ 42, FireBrick },
{ 43, FloralWhite },
{ 44, ForestGreen },
{ 45, Fuchsia },
{ 46, Gainsboro },
{ 47, GhostWhite },
{ 48, Gold },
{ 49, Goldenrod },
{ 50, Gray },
{ 51, Green },
{ 52, GreenYellow },
{ 53, Honeydew },
{ 54, HotPink },
{ 55, IndianRed },
{ 56, Indigo },
{ 57, Ivory },
{ 58, Khaki },
{ 59, Lavender },
{ 60, Lavenderblush },
{ 61, LawnGreen },
{ 62, LemonChiffon },
{ 63, LightBlue },
{ 64, LightCoral },
{ 65, LightCyan },
{ 66, LightGoldenodYellow },
{ 67, LightGray },
{ 68, LightGreen },
{ 69, LightPink },
{ 70, LightSalmon },
{ 71, LightSeaGreen },
{ 72, LightSkyBlue },
{ 73, LightSlateGray },
{ 74, LightSteelBlue },
{ 75, LightYellow },
{ 76, Lime },
{ 77, LimeGreen },
{ 78, Linen },
{ 79, Magenta },
{ 80, Maroon },
{ 81, MediumAquamarine },
{ 82, MediumBlue },
{ 83, MediumOrchid },
{ 84, MediumPurple },
{ 85, MediumSeaGreen },
{ 86, MediumSlateBlue },
{ 87, MediumSpringGreen },
{ 88, MediumTurquoise },
{ 89, MediumVioletRed },
{ 90, MidnightBlue },
{ 91, Mintcream },
{ 92, MistyRose },
{ 93, Moccasin },
{ 94, NavajoWhite },
{ 95, Navy },
{ 96, OldLace },
{ 97, Olive },
{ 98, Olivedrab },
{ 99, Orange },
{ 100, Orangered },
{ 101, Orchid },
{ 102, PaleGoldenrod },
{ 103, PaleGreen },
{ 104, PaleTurquoise },
{ 105, PaleVioletred },
{ 106, PapayaWhip },
{ 107, PeachPuff },
{ 108, Peru },
{ 109, Pink },
{ 110, Plum },
{ 111, PowderBlue },
{ 112, Purple },
{ 113, Red },
{ 114, RosyBrown },
{ 115, RoyalBlue },
{ 116, SaddleBrown },
{ 117, Salmon },
{ 118, SandyBrown },
{ 119, SeaGreen },
{ 120, Seashell },
{ 121, Sienna },
{ 122, Silver },
{ 123, SkyBlue },
{ 124, SlateBlue },
{ 125, SlateGray },
{ 126, Snow },
{ 127, SpringGreen },
{ 128, SteelBlue },
{ 129, Tan },
{ 130, Teal },
{ 131, Thistle },
{ 132, Tomato },
{ 133, Turquoise },
{ 134, Violet },
{ 135, Wheat },
{ 136, White },
{ 137, WhiteSmoke },
{ 138, Yellow },
{ 139, YellowGreen },
{ 140, ReunoYellow },
{ 141, BestRed }
};
}
/// <summary>
/// Returns a random color between the two min/max specified
/// </summary>
/// <param name="color"></param>
/// <param name="min"></param>
/// <param name="max"></param>
/// <returns></returns>
public static Color MMRandomColor(this Color color, Color min, Color max)
{
Color c = new Color()
{
r = UnityEngine.Random.Range(min.r, max.r),
g = UnityEngine.Random.Range(min.g, max.g),
b = UnityEngine.Random.Range(min.b, max.b),
a = UnityEngine.Random.Range(min.a, max.a)
};
return c;
}
/// <summary>
/// Tint : Uses HSV color conversions, keeps the original values, multiplies alpha
/// Multiply : The whole color, including alpha, is multiplied over the original
/// Replace : completely replaces the original with the target color
/// ReplaceKeepAlpha : color is replaced but the original alpha channel is ignored
/// Add : target color gets added (including its alpha)
/// </summary>
public enum ColoringMode { Tint, Multiply, Replace, ReplaceKeepAlpha, Add }
public static Color MMColorize(this Color originalColor, Color targetColor, ColoringMode coloringMode, float lerpAmount = 1.0f)
{
Color resultColor = Color.white;
switch (coloringMode)
{
case ColoringMode.Tint:
{
float s_h, s_s, s_v, t_h, t_s, t_v;
Color.RGBToHSV(originalColor, out s_h, out s_s, out s_v);
Color.RGBToHSV(targetColor, out t_h, out t_s, out t_v);
resultColor = Color.HSVToRGB(t_h, t_s, s_v * t_v);
resultColor.a = originalColor.a * targetColor.a;
}
break;
case ColoringMode.Multiply:
resultColor = originalColor * targetColor;
break;
case ColoringMode.Replace:
resultColor = targetColor;
break;
case ColoringMode.ReplaceKeepAlpha:
resultColor = targetColor;
resultColor.a = originalColor.a;
break;
case ColoringMode.Add:
resultColor = originalColor + targetColor;
break;
default:
break;
}
return Color.Lerp(originalColor, resultColor, lerpAmount);
}
}
}

View File

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

View File

@@ -0,0 +1,51 @@
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
namespace MoreMountains.Feedbacks
{
/// <summary>
/// An asset to store copy information, as well as global feedback settings.
/// It requires that one (and only one) MMFeedbacksConfiguration asset be created and stored in a Resources folder.
/// That's already done when installing MMFeedbacks.
/// </summary>
[CreateAssetMenu(menuName = "MoreMountains/MMFeedbacks/Configuration", fileName = "MMFeedbacksConfiguration")]
public class MMFeedbacksConfiguration : ScriptableObject
{
private static MMFeedbacksConfiguration _instance;
private static bool _instantiated;
/// <summary>
/// Singleton pattern
/// </summary>
public static MMFeedbacksConfiguration Instance
{
get
{
if (_instantiated)
{
return _instance;
}
string assetName = typeof(MMFeedbacksConfiguration).Name;
MMFeedbacksConfiguration loadedAsset = Resources.Load<MMFeedbacksConfiguration>("MMFeedbacksConfiguration");
_instantiated = true;
_instance = loadedAsset;
return _instance;
}
}
[Header("Debug")]
/// storage for copy/paste
public MMFeedbacks _mmFeedbacks;
[Header("Help settings")]
/// if this is true, inspector tips will be shown for MMFeedbacks
public bool ShowInspectorTips = true;
private void OnDestroy(){ _instantiated = false; }
}
}

View File

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

View File

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

View File

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

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: dcef6f636a0aab845a6c8d9b97bb4b51
NativeFormatImporter:
externalObjects: {}
mainObjectFileID: 11400000
userData:
assetBundleName:
assetBundleVariant:

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 378d85c023238454db159ae565d259dd
NativeFormatImporter:
externalObjects: {}
mainObjectFileID: 11400000
userData:
assetBundleName:
assetBundleVariant:

View File

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

View File

@@ -0,0 +1,77 @@
using System.Collections;
using System.Collections.Generic;
using UnityEditor;
using UnityEditor.PackageManager.Requests;
using UnityEditor.PackageManager;
using UnityEngine;
using System.Threading.Tasks;
using System.Linq;
using System.Text;
using MoreMountains.Tools;
namespace MoreMountains.Feedbacks
{
/// <summary>
/// This class is used to automatically install optional dependencies used in MMFeedbacks
/// </summary>
public static class FeedbackListOutputer
{
/// <summary>
/// Outputs a list of all MMFeedbacks to the console (there's only one target user for this and it's me hello!)
/// </summary>
[MenuItem("Tools/More Mountains/MMFeedbacks/Output MMF_Feedbacks list", false, 705)]
public static void OutputIFeedbacksList()
{
// Retrieve available feedbacks
List<System.Type> types = (from domainAssembly in System.AppDomain.CurrentDomain.GetAssemblies()
from assemblyType in domainAssembly.GetTypes()
where assemblyType.IsSubclassOf(typeof(MMF_Feedback))
select assemblyType).ToList();
List<string> typeNames = new List<string>();
string previousType = "";
for (int i = 0; i < types.Count; i++)
{
MMFeedbacksEditor.FeedbackTypePair newType = new MMFeedbacksEditor.FeedbackTypePair();
newType.FeedbackType = types[i];
newType.FeedbackName = FeedbackPathAttribute.GetFeedbackDefaultPath(types[i]);
if (newType.FeedbackName == "MMF_FeedbackBase")
{
continue;
}
string newEntry = FeedbackPathAttribute.GetFeedbackDefaultPath(newType.FeedbackType);
typeNames.Add(newEntry);
}
typeNames.Sort();
StringBuilder builder = new StringBuilder();
int counter = 1;
foreach (string typeName in typeNames)
{
if (typeName == null)
{
continue;
}
string[] splitArray = typeName.Split(char.Parse("/"));
if ((previousType != splitArray[0]) && (counter > 1))
{
builder.Append("\n");
}
builder.Append("- [ ] ");
builder.Append(counter.ToString("000"));
builder.Append(" - ");
builder.Append(typeName);
builder.Append("\n");
previousType = splitArray[0];
counter++;
}
MMDebug.DebugLogInfo(builder.ToString());
}
}
}

View File

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

View File

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

File diff suppressed because it is too large Load Diff

View File

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

View File

@@ -0,0 +1,3 @@
{
"reference": "GUID:d9dbf313afb206f458581847ac758375"
}

View File

@@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: 9722df90d8b438e4b8b47fee471fbbee
AssemblyDefinitionReferenceImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

View File

@@ -0,0 +1,144 @@
fileFormatVersion: 2
guid: a29898adbcfeacb438ad390d9e925afe
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
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: 1
spriteExtrude: 1
spriteMeshType: 1
alignment: 0
spritePivot: {x: 0.5, y: 0.5}
spritePixelsToUnits: 100
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
spriteGenerateFallbackPhysicsShape: 1
alphaUsage: 1
alphaIsTransparency: 1
spriteTessellationDetail: -1
textureType: 8
textureShape: 1
singleChannelComponent: 0
flipbookRows: 1
flipbookColumns: 1
maxTextureSizeSet: 0
compressionQualitySet: 0
textureFormatSet: 0
ignorePngGamma: 0
applyGammaDecoding: 0
platformSettings:
- serializedVersion: 3
buildTarget: DefaultTexturePlatform
maxTextureSize: 2048
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: 2048
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: 2048
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: 2048
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: 2048
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: 5e97eb03825dee720800000000000000
internalID: 0
vertices: []
indices:
edges: []
weights: []
secondaryTextures: []
spritePackingTag:
pSDRemoveMatte: 0
pSDShowRemoveMatteOption: 0
userData:
assetBundleName:
assetBundleVariant:

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

View File

@@ -0,0 +1,144 @@
fileFormatVersion: 2
guid: 87529e0fd28c3774fa086315a42b1860
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
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: 1
spriteExtrude: 1
spriteMeshType: 1
alignment: 0
spritePivot: {x: 0.5, y: 0.5}
spritePixelsToUnits: 100
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
spriteGenerateFallbackPhysicsShape: 1
alphaUsage: 1
alphaIsTransparency: 1
spriteTessellationDetail: -1
textureType: 8
textureShape: 1
singleChannelComponent: 0
flipbookRows: 1
flipbookColumns: 1
maxTextureSizeSet: 0
compressionQualitySet: 0
textureFormatSet: 0
ignorePngGamma: 0
applyGammaDecoding: 0
platformSettings:
- serializedVersion: 3
buildTarget: DefaultTexturePlatform
maxTextureSize: 2048
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: 2048
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: 2048
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: 2048
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: 2048
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: 5e97eb03825dee720800000000000000
internalID: 0
vertices: []
indices:
edges: []
weights: []
secondaryTextures: []
spritePackingTag:
pSDRemoveMatte: 0
pSDShowRemoveMatteOption: 0
userData:
assetBundleName:
assetBundleVariant:

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

View File

@@ -0,0 +1,92 @@
fileFormatVersion: 2
guid: 1d575a145584c7549994d8a51c689ef8
TextureImporter:
internalIDToNameTable: []
externalObjects: {}
serializedVersion: 11
mipmaps:
mipMapMode: 0
enableMipMap: 1
sRGBTexture: 1
linearTexture: 0
fadeOut: 0
borderMipMap: 0
mipMapsPreserveCoverage: 0
alphaTestReferenceValue: 0.5
mipMapFadeDistanceStart: 1
mipMapFadeDistanceEnd: 3
bumpmap:
convertToNormalMap: 0
externalNormalMap: 0
heightScale: 0.25
normalMapFilter: 0
isReadable: 0
streamingMipmaps: 0
streamingMipmapsPriority: 0
grayScaleToAlpha: 0
generateCubemap: 6
cubemapConvolution: 0
seamlessCubemap: 0
textureFormat: 1
maxTextureSize: 2048
textureSettings:
serializedVersion: 2
filterMode: -1
aniso: -1
mipBias: -100
wrapU: -1
wrapV: -1
wrapW: -1
nPOTScale: 1
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: 0
spriteTessellationDetail: -1
textureType: 0
textureShape: 1
singleChannelComponent: 0
maxTextureSizeSet: 0
compressionQualitySet: 0
textureFormatSet: 0
applyGammaDecoding: 0
platformSettings:
- serializedVersion: 3
buildTarget: DefaultTexturePlatform
maxTextureSize: 2048
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: []
spritePackingTag:
pSDRemoveMatte: 0
pSDShowRemoveMatteOption: 0
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,17 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!114 &11400000
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 0}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 8bcf466015f0b254893ff0208fccf90f, type: 3}
m_Name: MMF_PlayerConfiguration
m_EditorClassIdentifier:
ShowInspectorTips: 1
AutoDisableKeepPlaymodeChanges: 1
InspectorGroupsExpandedByDefault: 1

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: c14ab46a507c8324c8b54e6a3fdc2b0e
NativeFormatImporter:
externalObjects: {}
mainObjectFileID: 11400000
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,16 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!114 &11400000
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 0}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 00bf1cad26d9e9342b90f463840caf08, type: 3}
m_Name: MMFeedbacksConfiguration
m_EditorClassIdentifier:
_mmFeedbacks: {fileID: 0}
ShowInspectorTips: 1

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 59a4add72d602ce4a9693b14a97d2a83
NativeFormatImporter:
externalObjects: {}
mainObjectFileID: 0
userData:
assetBundleName:
assetBundleVariant:

View File

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

View File

@@ -0,0 +1,189 @@
using System.Collections;
using System.Collections.Generic;
using UnityEditor;
using UnityEngine;
namespace MoreMountains.Feedbacks
{
/// <summary>
/// Custom editor for sequence recorder
/// </summary>
[CustomEditor(typeof(MMInputSequenceRecorder), true)]
[CanEditMultipleObjects]
public class MMInputSequenceRecorderEditor : Editor
{
protected SerializedProperty _Recording;
protected float _inspectorWidth;
protected int _externalMargin = 10;
protected Rect _rect;
protected Color _recordingColor = Color.red;
protected Color _recordingTextColor = Color.white;
protected Vector2 _boxPosition;
protected Vector2 _boxSize;
protected GUIStyle _recordingStyle;
protected MMInputSequenceRecorder _targetRecorder;
protected Event _currentEvent;
/// <summary>
/// Forces constant inspector repaints
/// </summary>
/// <returns></returns>
public override bool RequiresConstantRepaint()
{
return true;
}
/// <summary>
/// On enable we initialize our styles and listen for input in editor mode
/// </summary>
protected virtual void OnEnable()
{
_Recording = serializedObject.FindProperty("Recording");
_recordingStyle = new GUIStyle();
_recordingStyle.normal.textColor = Color.white;
_recordingStyle.fontSize = 30;
_recordingStyle.alignment = TextAnchor.MiddleCenter;
_targetRecorder = (MMInputSequenceRecorder)target;
System.Reflection.FieldInfo info = typeof(EditorApplication).GetField("globalEventHandler", System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.NonPublic);
EditorApplication.CallbackFunction value = (EditorApplication.CallbackFunction)info.GetValue(null);
value += EditorGlobalKeyPress;
info.SetValue(null, value);
}
/// <summary>
/// Looks for input
/// </summary>
protected virtual void EditorGlobalKeyPress()
{
if (Application.isPlaying)
{
return;
}
HandleUtility.AddDefaultControl(GUIUtility.GetControlID(FocusType.Passive));
_currentEvent = Event.current;
if (_currentEvent == null)
{
return;
}
DetectStartAndEnd();
EditorDetectRecording();
}
/// <summary>
/// Detects presses on the start or end keys
/// </summary>
protected virtual void DetectStartAndEnd()
{
if (_currentEvent.isKey)
{
if (!_targetRecorder.Recording)
{
if ((_currentEvent.keyCode == _targetRecorder.StartRecordingHotkey) && (_currentEvent.type == EventType.KeyDown))
{
_targetRecorder.StartRecording();
}
}
else
{
if ((_currentEvent.keyCode == _targetRecorder.StopRecordingHotkey) && (_currentEvent.type == EventType.KeyDown))
{
_targetRecorder.StopRecording();
}
}
}
}
/// <summary>
/// Looks for key presses on sequence key bindings
/// </summary>
protected virtual void EditorDetectRecording()
{
if (_targetRecorder.Recording && (_targetRecorder.SequenceScriptableObject != null))
{
if (_currentEvent.isKey)
{
foreach (MMSequenceTrack track in _targetRecorder.SequenceScriptableObject.SequenceTracks)
{
if (_currentEvent.keyCode == (track.Key))
{
if (track.State == MMSequenceTrackStates.Up)
{
track.State = MMSequenceTrackStates.Idle;
}
if (_currentEvent.type == EventType.KeyDown)
{
if (track.State != MMSequenceTrackStates.Down)
{
// key is down for the first time
_targetRecorder.AddNoteToTrack(track);
}
track.State = MMSequenceTrackStates.Down;
}
if (_currentEvent.type == EventType.KeyUp)
{
// key is up
track.State = MMSequenceTrackStates.Up;
}
}
}
}
}
}
/// <summary>
/// Draws the custom inspector
/// </summary>
public override void OnInspectorGUI()
{
serializedObject.Update();
Undo.RecordObject(target, "Modified Sequence Recorder");
_inspectorWidth = EditorGUIUtility.currentViewWidth - 24;
// display recording label
if (_Recording.boolValue)
{
GUILayout.Box("", GUILayout.Width(_inspectorWidth - _externalMargin), GUILayout.Height(50));
_boxPosition = GUILayoutUtility.GetLastRect().position;
_boxSize = GUILayoutUtility.GetLastRect().size;
_rect.x = _boxPosition.x;
_rect.y = _boxPosition.y;
_rect.width = _boxSize.x;
_rect.height = _boxSize.y;
EditorGUI.DrawRect(_rect, _recordingColor);
EditorGUI.LabelField(_rect, "RECORDING", _recordingStyle);
}
DrawDefaultInspector();
// separator
EditorGUILayout.Space();
EditorGUILayout.LabelField("Controls", EditorStyles.boldLabel);
if (!_Recording.boolValue)
{
// display start recording button
if (GUILayout.Button("Start Recording"))
{
_targetRecorder.StartRecording();
}
}
else
{
// display stop recording button
if (GUILayout.Button("Stop Recording"))
{
_targetRecorder.StopRecording();
}
}
serializedObject.ApplyModifiedProperties();
}
}
}

View File

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

View File

@@ -0,0 +1,418 @@
using System.Collections;
using System.Collections.Generic;
using UnityEditor;
using UnityEngine;
namespace MoreMountains.Feedbacks
{
/// <summary>
/// Custom editor for MMSequencer, handles recalibration and sequencer display
/// </summary>
[CustomEditor(typeof(MMSequencer), true)]
[CanEditMultipleObjects]
public class MMSequencerEditor : Editor
{
protected MMSequencer _targetSequencer;
protected float _inspectorWidth;
protected GUIStyle _buttonStyle;
protected GUIStyle _trackControlStyle;
protected GUIStyle _indexStyle;
protected Texture2D _buttonBackground;
protected Texture2D _dotBackground;
protected Color _buttonColor;
protected Color _trackControlColor;
protected Color _emptyButtonColor = new Color(0,0,0,0.5f);
protected Color _empty4ButtonColor = new Color(0, 0, 0, 0.75f);
protected const float _buttonWidth = 24;
protected const float _trackControlWidth = 11;
protected const float _distanceBetweenButtons = 6f;
protected int _boxesPerLine;
protected Color _originalBackgroundColor;
protected Color _controlColor;
protected List<float> _trackControlLastUseTimestamps;
/// <summary>
/// We want constant repaint on this inspector
/// </summary>
/// <returns></returns>
public override bool RequiresConstantRepaint()
{
return true;
}
/// <summary>
/// On enable we grab our textures and initialize our styles
/// </summary>
protected virtual void OnEnable()
{
_targetSequencer = (MMSequencer)target;
_buttonBackground = Resources.Load("SequencerButtonBackground") as Texture2D;
_dotBackground = Resources.Load("SequencerDotBackground") as Texture2D;
_originalBackgroundColor = GUI.backgroundColor;
_buttonStyle = new GUIStyle();
_buttonStyle.normal.background = _buttonBackground;
_buttonStyle.fixedWidth = _buttonWidth;
_buttonStyle.fixedHeight = _buttonWidth;
_trackControlStyle = new GUIStyle();
_trackControlStyle.normal.background = _dotBackground;
_trackControlStyle.normal.textColor = (Application.isPlaying) ? Color.black : Color.white;
_trackControlStyle.fixedWidth = _trackControlWidth;
_trackControlStyle.fixedHeight = _trackControlWidth;
_trackControlStyle.margin = new RectOffset(0, 0, 1, 0);
_trackControlStyle.alignment = TextAnchor.MiddleCenter;
_trackControlStyle.fontSize = 10;
_indexStyle = new GUIStyle();
_indexStyle.normal.background = _dotBackground;
_indexStyle.normal.textColor = Color.white;
_indexStyle.alignment = TextAnchor.MiddleCenter;
_indexStyle.fixedWidth = _trackControlWidth * 1.5f;
_indexStyle.fixedHeight = _trackControlWidth * 1.5f;
FillControlList();
}
protected virtual void FillControlList()
{
// fill the control timer list
if (_targetSequencer.Sequence != null)
{
_trackControlLastUseTimestamps = new List<float>();
foreach (MMSequenceTrack track in _targetSequencer.Sequence.SequenceTracks)
{
_trackControlLastUseTimestamps.Add(0f);
}
}
}
/// <summary>
/// Draws the default inspector and the sequencer
/// </summary>
public override void OnInspectorGUI()
{
serializedObject.Update();
Undo.RecordObject(target, "Modified Sequence Recorder");
DrawDefaultInspector();
if (_targetSequencer.Sequence == null)
{
_targetSequencer.LastSequence = null;
return;
}
// gets the width and computes how many boxes we can fit per line
_inspectorWidth = EditorGUIUtility.currentViewWidth - 24;
_boxesPerLine = (int)Mathf.Round(
(_inspectorWidth - ((_targetSequencer.Sequence.SequenceTracks.Count) * _distanceBetweenButtons) - _trackControlWidth - _distanceBetweenButtons)
/ (_buttonWidth + _distanceBetweenButtons)
) + 1;
LookForChanges();
// separator
EditorGUILayout.Space();
EditorGUILayout.LabelField("Sequencer", EditorStyles.boldLabel);
EditorGUILayout.BeginHorizontal();
if (GUILayout.Button("Destroy and rebuild sequence", EditorStyles.miniButtonLeft))
{
_targetSequencer.Sequence.QuantizedSequence = null;
_targetSequencer.LastTracksCount = -1;
_targetSequencer.ApplySequencerLengthToSequence();
EditorUtility.SetDirty(_targetSequencer.Sequence);
}
if (GUILayout.Button("Clear Sequence", EditorStyles.miniButtonMid))
{
_targetSequencer.ClearSequence();
EditorUtility.SetDirty(_targetSequencer.Sequence);
}
if (GUILayout.Button("[ - ] Length - 1", EditorStyles.miniButtonMid))
{
_targetSequencer.DecrementLength();
EditorUtility.SetDirty(_targetSequencer.Sequence);
}
if (GUILayout.Button("[ + ] Length + 1", EditorStyles.miniButtonRight))
{
_targetSequencer.IncrementLength();
EditorUtility.SetDirty(_targetSequencer.Sequence);
}
EditorGUILayout.EndHorizontal();
EditorGUILayout.Space();
EditorGUILayout.Space();
DrawSequenceIndexes();
for (int i = 0; i < _targetSequencer.Sequence.SequenceTracks.Count; i++)
{
DrawTrack(i);
}
DrawControlButtons();
serializedObject.ApplyModifiedProperties();
}
/// <summary>
/// Whenever we detect a change in the settings we recalibrate our sequence accordingly
/// </summary>
protected virtual void LookForChanges()
{
if (_targetSequencer.LastSequence != _targetSequencer.Sequence)
{
FillControlList();
if (_targetSequencer.Sequence.QuantizedSequence.Count > 0)
{
if (_targetSequencer.Sequence.QuantizedSequence[0].Line.Count != _targetSequencer.SequencerLength)
{
_targetSequencer.SequencerLength = _targetSequencer.Sequence.QuantizedSequence[0].Line.Count;
_targetSequencer.LastSequencerLength = _targetSequencer.SequencerLength;
_targetSequencer.LastSequence = _targetSequencer.Sequence;
_targetSequencer.LastTracksCount = _targetSequencer.Sequence.SequenceTracks.Count;
}
}
else
{
_targetSequencer.ApplySequencerLengthToSequence();
_targetSequencer.LastSequence = _targetSequencer.Sequence;
EditorUtility.SetDirty(_targetSequencer.Sequence);
}
}
if (_targetSequencer.LastSequence == _targetSequencer.Sequence)
{
if (_targetSequencer.LastTracksCount != _targetSequencer.Sequence.SequenceTracks.Count)
{
FillControlList();
_targetSequencer.ApplySequencerLengthToSequence();
EditorUtility.SetDirty(_targetSequencer.Sequence);
}
if (_targetSequencer.LastBPM != _targetSequencer.BPM)
{
_targetSequencer.UpdateTimestampsToMatchNewBPM();
EditorUtility.SetDirty(_targetSequencer.Sequence);
}
}
_targetSequencer.EditorMaintenance();
}
/// <summary>
/// Draws control buttons
/// </summary>
protected virtual void DrawControlButtons()
{
if (!Application.isPlaying)
{
return;
}
GUI.backgroundColor = _originalBackgroundColor;
EditorGUILayout.Space();
EditorGUILayout.LabelField("Controls", EditorStyles.boldLabel);
if (_targetSequencer.Playing)
{
if (GUILayout.Button("Stop Playing"))
{
_targetSequencer.StopSequence();
}
}
else
{
if (GUILayout.Button("Start Playing"))
{
_targetSequencer.PlaySequence();
}
}
if (GUILayout.Button("Play Next Beat"))
{
_targetSequencer.PlayBeat();
}
}
/// <summary>
/// Draws an index for each sequence item
/// </summary>
protected virtual void DrawSequenceIndexes()
{
GUILayout.BeginHorizontal();
GUI.backgroundColor = _emptyButtonColor;
GUILayout.Label("", GUILayout.Width(_trackControlWidth + _distanceBetweenButtons), GUILayout.Height(_trackControlWidth));
string label = "";
for (int i = 0; i < _targetSequencer.SequencerLength; i++)
{
label = i < 10 ? " " + i.ToString() : i.ToString();
_trackControlStyle.fontStyle = (i % 4 == 0) ? FontStyle.Bold : FontStyle.Normal;
//GUILayout.Label(label, _indexStyle, GUILayout.Width(_buttonWidth + _distanceBetweenButtons), GUILayout.Height(_trackControlWidth));
if (GUILayout.Button(label, _indexStyle, GUILayout.Width(_buttonWidth + _distanceBetweenButtons), GUILayout.Height(_trackControlWidth)))
{
_targetSequencer.ToggleStep(i);
EditorUtility.SetDirty(_targetSequencer.Sequence);
}
}
GUI.backgroundColor = _originalBackgroundColor;
GUILayout.EndHorizontal();
GUILayout.Space(_distanceBetweenButtons * 1.5f);
}
/// <summary>
/// Draws a line of the sequencer
/// </summary>
/// <param name="trackIndex"></param>
protected virtual void DrawTrack(int trackIndex)
{
int counter = 0;
if (_targetSequencer.Sequence.QuantizedSequence == null)
{
return;
}
if (_targetSequencer.Sequence.QuantizedSequence.Count != _targetSequencer.Sequence.SequenceTracks.Count)
{
return;
}
GUILayout.BeginHorizontal();
GUILayout.BeginVertical();
// draw active track control
if (_targetSequencer.Sequence.SequenceTracks[trackIndex].Active)
{
_trackControlColor = _targetSequencer.Sequence.SequenceTracks[trackIndex].TrackColor;
}
else
{
_trackControlColor = _emptyButtonColor;
}
GUI.backgroundColor = _trackControlColor;
if (GUILayout.Button("", _trackControlStyle, GUILayout.Width(_trackControlWidth), GUILayout.Height(_trackControlWidth)))
{
if (_targetSequencer.TrackEvents[trackIndex] != null)
{
_targetSequencer.ToggleActive(trackIndex);
EditorUtility.SetDirty(_targetSequencer.Sequence);
}
}
GUILayout.Space(_distanceBetweenButtons / 5);
// draw test track control
_trackControlColor = _targetSequencer.Sequence.SequenceTracks[trackIndex].TrackColor;
_controlColor = Application.isPlaying ? SequencerColor(_trackControlLastUseTimestamps[trackIndex], _trackControlColor) : Color.black;
GUI.backgroundColor = _controlColor;
if (GUILayout.Button(trackIndex.ToString(), _trackControlStyle, GUILayout.Width(_trackControlWidth), GUILayout.Height(_trackControlWidth)))
{
if (_targetSequencer.TrackEvents[trackIndex] != null)
{
_trackControlLastUseTimestamps[trackIndex] = Time.time;
_targetSequencer.PlayTrackEvent(trackIndex);
}
}
GUILayout.EndVertical();
GUILayout.Space(_distanceBetweenButtons);
for (int i = 0; i < _targetSequencer.Sequence.QuantizedSequence[trackIndex].Line.Count; i++)
{
// handle new lines
if (counter > _boxesPerLine )
{
GUILayout.EndHorizontal();
GUILayout.Space(_distanceBetweenButtons);
GUILayout.BeginHorizontal();
counter = 0;
}
if (_targetSequencer.Sequence.QuantizedSequence[trackIndex].Line[i].ID != -1)
{
_buttonColor = _targetSequencer.Sequence.SequenceTracks[trackIndex].TrackColor;
}
else
{
if (i % 4 == 0)
{
_buttonColor = _empty4ButtonColor;
}
else
{
_buttonColor = _emptyButtonColor;
}
}
// if the track is inactive, we reduce colors
if (!_targetSequencer.Sequence.SequenceTracks[trackIndex].Active)
{
_buttonColor = _buttonColor / 2f;
}
DrawSequenceButton(trackIndex, i, _buttonColor);
counter++;
}
GUILayout.FlexibleSpace();
GUILayout.EndHorizontal();
GUILayout.Space(_distanceBetweenButtons);
}
/// <summary>
/// Draws an interactive button for the sequencer
/// </summary>
/// <param name="trackIndex"></param>
/// <param name="sequenceIndex"></param>
/// <param name="buttonColor"></param>
protected virtual void DrawSequenceButton(int trackIndex, int sequenceIndex, Color buttonColor)
{
if (Application.isPlaying && _targetSequencer.PlayedOnce && (_targetSequencer.LastBeatIndex == sequenceIndex))
{
if (_targetSequencer.BeatThisFrame)
{
_buttonColor = Color.white;
}
else
{
_buttonColor = SequencerColor(_targetSequencer.LastBeatTimestamp, buttonColor);
}
}
else
{
_buttonColor = buttonColor;
}
GUI.backgroundColor = _buttonColor;
if (GUILayout.Button("", _buttonStyle, GUILayout.Width(_buttonWidth), GUILayout.Height(_buttonWidth)))
{
bool active = (_targetSequencer.Sequence.QuantizedSequence[trackIndex].Line[sequenceIndex].ID == _targetSequencer.Sequence.SequenceTracks[trackIndex].ID);
_targetSequencer.Sequence.QuantizedSequence[trackIndex].Line[sequenceIndex].ID = active ? -1 : _targetSequencer.Sequence.SequenceTracks[trackIndex].ID;
EditorUtility.SetDirty(_targetSequencer.Sequence);
}
GUILayout.Space(_distanceBetweenButtons);
}
/// <summary>
/// Color interpolation on hits
/// </summary>
/// <param name="lastBeatTimestamp"></param>
/// <param name="buttonColor"></param>
/// <returns></returns>
protected virtual Color SequencerColor(float lastBeatTimestamp, Color buttonColor)
{
float x = (Time.time - lastBeatTimestamp);
float A = 0f;
float B = (60f / _targetSequencer.BPM) / 4f;
float C = 0f;
float D = 1f;
float t = C + (x - A) / (B - A) * (D - C);
return Color.Lerp(Color.white, buttonColor, t);
}
}
}

View File

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

View File

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 958 B

View File

@@ -0,0 +1,139 @@
fileFormatVersion: 2
guid: e802b29e86b4ef74abe728250ecaf37c
TextureImporter:
internalIDToNameTable: []
externalObjects: {}
serializedVersion: 10
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
grayScaleToAlpha: 0
generateCubemap: 6
cubemapConvolution: 0
seamlessCubemap: 0
textureFormat: 1
maxTextureSize: 2048
textureSettings:
serializedVersion: 2
filterMode: 0
aniso: -1
mipBias: -100
wrapU: 1
wrapV: 1
wrapW: -1
nPOTScale: 0
lightmap: 0
compressionQuality: 50
spriteMode: 1
spriteExtrude: 1
spriteMeshType: 1
alignment: 0
spritePivot: {x: 0.5, y: 0.5}
spritePixelsToUnits: 100
spriteBorder: {x: 2, y: 2, z: 2, w: 2}
spriteGenerateFallbackPhysicsShape: 1
alphaUsage: 1
alphaIsTransparency: 1
spriteTessellationDetail: -1
textureType: 8
textureShape: 1
singleChannelComponent: 0
maxTextureSizeSet: 0
compressionQualitySet: 0
textureFormatSet: 0
platformSettings:
- serializedVersion: 3
buildTarget: DefaultTexturePlatform
maxTextureSize: 2048
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: 2048
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: 2048
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: 2048
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: 2048
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: 5e97eb03825dee720800000000000000
internalID: 0
vertices: []
indices:
edges: []
weights: []
secondaryTextures: []
spritePackingTag:
pSDRemoveMatte: 0
pSDShowRemoveMatteOption: 0
userData:
assetBundleName:
assetBundleVariant:

Binary file not shown.

After

Width:  |  Height:  |  Size: 935 B

View File

@@ -0,0 +1,139 @@
fileFormatVersion: 2
guid: 82c9d5c8726c57249b51c39e76eee072
TextureImporter:
internalIDToNameTable: []
externalObjects: {}
serializedVersion: 10
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
grayScaleToAlpha: 0
generateCubemap: 6
cubemapConvolution: 0
seamlessCubemap: 0
textureFormat: 1
maxTextureSize: 2048
textureSettings:
serializedVersion: 2
filterMode: 0
aniso: -1
mipBias: -100
wrapU: 1
wrapV: 1
wrapW: -1
nPOTScale: 0
lightmap: 0
compressionQuality: 50
spriteMode: 1
spriteExtrude: 1
spriteMeshType: 1
alignment: 0
spritePivot: {x: 0.5, y: 0.5}
spritePixelsToUnits: 100
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
spriteGenerateFallbackPhysicsShape: 1
alphaUsage: 1
alphaIsTransparency: 1
spriteTessellationDetail: -1
textureType: 8
textureShape: 1
singleChannelComponent: 0
maxTextureSizeSet: 0
compressionQualitySet: 0
textureFormatSet: 0
platformSettings:
- serializedVersion: 3
buildTarget: DefaultTexturePlatform
maxTextureSize: 2048
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: 2048
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: 2048
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: 2048
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: 2048
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: 5e97eb03825dee720800000000000000
internalID: 0
vertices: []
indices:
edges: []
weights: []
secondaryTextures: []
spritePackingTag:
pSDRemoveMatte: 0
pSDShowRemoveMatteOption: 0
userData:
assetBundleName:
assetBundleVariant:

View File

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

View File

@@ -0,0 +1,264 @@
using System.Collections;
using System.Collections.Generic;
using UnityEditor;
using UnityEngine;
namespace MoreMountains.Feedbacks
{
[CanEditMultipleObjects]
[CustomEditor(typeof(MMWiggle), true)]
public class MMWiggleEditor : Editor
{
public struct WiggleEditorProperties
{
public SerializedProperty WigglePermitted;
public SerializedProperty WiggleType;
public SerializedProperty UseUnscaledTime;
public SerializedProperty TimeMultiplier;
public SerializedProperty RelativeAmplitude;
public SerializedProperty UniformValues;
public SerializedProperty ForceVectorLength;
public SerializedProperty ForcedVectorLength;
public SerializedProperty StartWigglingAutomatically;
public SerializedProperty SmoothPingPong;
public SerializedProperty UseSpeedCurve;
public SerializedProperty SpeedCurve;
public SerializedProperty FrequencyMin;
public SerializedProperty FrequencyMax;
public SerializedProperty AmplitudeMin;
public SerializedProperty AmplitudeMax;
public SerializedProperty PauseMin;
public SerializedProperty PauseMax;
public SerializedProperty NoiseFrequencyMin;
public SerializedProperty NoiseFrequencyMax;
public SerializedProperty NoiseShiftMin;
public SerializedProperty NoiseShiftMax;
public SerializedProperty LimitedTime;
public SerializedProperty LimitedTimeTotal;
public SerializedProperty LimitedTimeLeft;
public SerializedProperty LimitedTimeFalloff;
public SerializedProperty LimitedTimeResetValue;
public SerializedProperty Curve;
public SerializedProperty RemapCurveZeroMin;
public SerializedProperty RemapCurveZeroMax;
public SerializedProperty RemapCurveOneMin;
public SerializedProperty RemapCurveOneMax;
public SerializedProperty RelativeCurveAmplitude;
public SerializedProperty CurvePingPong;
}
protected SerializedProperty _updateMode;
protected SerializedProperty _positionActive;
protected SerializedProperty _rotationActive;
protected SerializedProperty _scaleActive;
protected SerializedProperty _positionProperties;
protected SerializedProperty _rotationProperties;
protected SerializedProperty _scaleProperties;
protected WiggleEditorProperties _positionEditorProperties;
protected WiggleEditorProperties _rotationEditorProperties;
protected WiggleEditorProperties _scaleEditorProperties;
protected SerializedProperty _debugWiggleDuration;
protected MMWiggle _mmWiggle;
public bool StartWigglingAutomatically = true;
protected virtual void OnEnable()
{
_mmWiggle = (MMWiggle)target;
_updateMode = serializedObject.FindProperty("UpdateMode");
_positionProperties = serializedObject.FindProperty("PositionWiggleProperties");
_rotationProperties = serializedObject.FindProperty("RotationWiggleProperties");
_scaleProperties = serializedObject.FindProperty("ScaleWiggleProperties");
_positionActive = serializedObject.FindProperty("PositionActive");
_rotationActive = serializedObject.FindProperty("RotationActive");
_scaleActive = serializedObject.FindProperty("ScaleActive");
_debugWiggleDuration = serializedObject.FindProperty("DebugWiggleDuration");
InitializeProperties(_positionProperties, ref _positionEditorProperties);
InitializeProperties(_rotationProperties, ref _rotationEditorProperties);
InitializeProperties(_scaleProperties, ref _scaleEditorProperties);
}
protected virtual void InitializeProperties(SerializedProperty targetProperty, ref WiggleEditorProperties editorProperties)
{
editorProperties.WigglePermitted = targetProperty.FindPropertyRelative("WigglePermitted");
editorProperties.WiggleType = targetProperty.FindPropertyRelative("WiggleType");
editorProperties.UseUnscaledTime = targetProperty.FindPropertyRelative("UseUnscaledTime");
editorProperties.TimeMultiplier = targetProperty.FindPropertyRelative("TimeMultiplier");
editorProperties.RelativeAmplitude = targetProperty.FindPropertyRelative("RelativeAmplitude");
editorProperties.UniformValues = targetProperty.FindPropertyRelative("UniformValues");
editorProperties.ForceVectorLength = targetProperty.FindPropertyRelative("ForceVectorLength");
editorProperties.ForcedVectorLength = targetProperty.FindPropertyRelative("ForcedVectorLength");
editorProperties.StartWigglingAutomatically = targetProperty.FindPropertyRelative("StartWigglingAutomatically");
editorProperties.SmoothPingPong = targetProperty.FindPropertyRelative("SmoothPingPong");
editorProperties.UseSpeedCurve = targetProperty.FindPropertyRelative("UseSpeedCurve");
editorProperties.SpeedCurve = targetProperty.FindPropertyRelative("SpeedCurve");
editorProperties.FrequencyMin = targetProperty.FindPropertyRelative("FrequencyMin");
editorProperties.FrequencyMax = targetProperty.FindPropertyRelative("FrequencyMax");
editorProperties.AmplitudeMin = targetProperty.FindPropertyRelative("AmplitudeMin");
editorProperties.AmplitudeMax = targetProperty.FindPropertyRelative("AmplitudeMax");
editorProperties.PauseMin = targetProperty.FindPropertyRelative("PauseMin");
editorProperties.PauseMax = targetProperty.FindPropertyRelative("PauseMax");
editorProperties.NoiseFrequencyMin = targetProperty.FindPropertyRelative("NoiseFrequencyMin");
editorProperties.NoiseFrequencyMax = targetProperty.FindPropertyRelative("NoiseFrequencyMax");
editorProperties.NoiseShiftMin = targetProperty.FindPropertyRelative("NoiseShiftMin");
editorProperties.NoiseShiftMax = targetProperty.FindPropertyRelative("NoiseShiftMax");
editorProperties.LimitedTime = targetProperty.FindPropertyRelative("LimitedTime");
editorProperties.LimitedTimeTotal = targetProperty.FindPropertyRelative("LimitedTimeTotal");
editorProperties.LimitedTimeLeft = targetProperty.FindPropertyRelative("LimitedTimeLeft");
editorProperties.LimitedTimeFalloff = targetProperty.FindPropertyRelative("LimitedTimeFalloff");
editorProperties.LimitedTimeResetValue = targetProperty.FindPropertyRelative("LimitedTimeResetValue");
editorProperties.Curve = targetProperty.FindPropertyRelative("Curve");
editorProperties.RemapCurveZeroMin = targetProperty.FindPropertyRelative("RemapCurveZeroMin");
editorProperties.RemapCurveZeroMax = targetProperty.FindPropertyRelative("RemapCurveZeroMax");
editorProperties.RemapCurveOneMin = targetProperty.FindPropertyRelative("RemapCurveOneMin");
editorProperties.RemapCurveOneMax = targetProperty.FindPropertyRelative("RemapCurveOneMax");
editorProperties.RelativeCurveAmplitude = targetProperty.FindPropertyRelative("RelativeCurveAmplitude");
editorProperties.CurvePingPong = targetProperty.FindPropertyRelative("CurvePingPong");
}
public override void OnInspectorGUI()
{
serializedObject.Update();
Undo.RecordObject(target, "Modified MMWiggle");
EditorGUILayout.Space();
EditorGUILayout.PropertyField(_updateMode);
EditorGUILayout.Space();
MMFeedbackStyling.DrawSplitter();
DrawValueEditor("Position", _positionActive, _positionEditorProperties, _mmWiggle.PositionWiggleProperties.WiggleType);
DrawValueEditor("Rotation", _rotationActive, _rotationEditorProperties, _mmWiggle.RotationWiggleProperties.WiggleType);
DrawValueEditor("Scale", _scaleActive, _scaleEditorProperties, _mmWiggle.ScaleWiggleProperties.WiggleType);
EditorGUILayout.Space();
EditorGUILayout.LabelField("Debug", EditorStyles.boldLabel);
EditorGUILayout.PropertyField(_debugWiggleDuration);
EditorGUILayout.BeginHorizontal();
{
if (GUILayout.Button("Wiggle Position", EditorStyles.miniButtonLeft))
{
_mmWiggle.WigglePosition(_debugWiggleDuration.floatValue);
}
if (GUILayout.Button("Wiggle Rotation", EditorStyles.miniButtonMid))
{
_mmWiggle.WiggleRotation(_debugWiggleDuration.floatValue);
}
if (GUILayout.Button("Wiggle Scale", EditorStyles.miniButtonRight))
{
_mmWiggle.WiggleScale(_debugWiggleDuration.floatValue);
}
}
EditorGUILayout.EndHorizontal();
EditorGUILayout.Space();
serializedObject.ApplyModifiedProperties();
}
protected virtual void DrawValueEditor(string title, SerializedProperty propertyActive, WiggleEditorProperties editorProperties, WiggleTypes wiggleType)
{
bool propertyIsExpanded = propertyActive.isExpanded;
bool propertyIsActive = propertyActive.boolValue;
Rect headerRect = MMFeedbackStyling.DrawSimpleHeader(
ref propertyIsExpanded,
ref propertyIsActive,
title);
propertyActive.isExpanded = propertyIsExpanded;
propertyActive.boolValue = propertyIsActive;
if (propertyIsExpanded)
{
EditorGUI.BeginDisabledGroup(!propertyIsActive);
EditorGUILayout.PropertyField(editorProperties.WigglePermitted);
EditorGUILayout.PropertyField(editorProperties.WiggleType);
EditorGUILayout.PropertyField(editorProperties.UseUnscaledTime);
EditorGUILayout.PropertyField(editorProperties.TimeMultiplier);
if ((wiggleType == WiggleTypes.PingPong) || (wiggleType == WiggleTypes.Random))
{
if (wiggleType == WiggleTypes.PingPong)
{
EditorGUILayout.PropertyField(editorProperties.SmoothPingPong);
}
EditorGUILayout.PropertyField(editorProperties.UseSpeedCurve);
if (editorProperties.UseSpeedCurve.boolValue)
{
EditorGUILayout.PropertyField(editorProperties.SpeedCurve);
}
EditorGUILayout.PropertyField(editorProperties.AmplitudeMin);
EditorGUILayout.PropertyField(editorProperties.AmplitudeMax);
EditorGUILayout.PropertyField(editorProperties.RelativeAmplitude);
EditorGUILayout.PropertyField(editorProperties.UniformValues);
EditorGUILayout.PropertyField(editorProperties.ForceVectorLength);
EditorGUILayout.PropertyField(editorProperties.ForcedVectorLength);
EditorGUILayout.PropertyField(editorProperties.FrequencyMin);
EditorGUILayout.PropertyField(editorProperties.FrequencyMax);
EditorGUILayout.PropertyField(editorProperties.PauseMin);
EditorGUILayout.PropertyField(editorProperties.PauseMax);
}
if (wiggleType == WiggleTypes.Noise)
{
EditorGUILayout.PropertyField(editorProperties.AmplitudeMin);
EditorGUILayout.PropertyField(editorProperties.AmplitudeMax);
EditorGUILayout.PropertyField(editorProperties.RelativeAmplitude);
EditorGUILayout.PropertyField(editorProperties.UniformValues);
EditorGUILayout.PropertyField(editorProperties.ForceVectorLength);
EditorGUILayout.PropertyField(editorProperties.ForcedVectorLength);
EditorGUILayout.PropertyField(editorProperties.NoiseFrequencyMin);
EditorGUILayout.PropertyField(editorProperties.NoiseFrequencyMax);
EditorGUILayout.PropertyField(editorProperties.NoiseShiftMin);
EditorGUILayout.PropertyField(editorProperties.NoiseShiftMax);
}
if (wiggleType == WiggleTypes.Curve)
{
EditorGUILayout.PropertyField(editorProperties.Curve);
EditorGUILayout.PropertyField(editorProperties.RemapCurveZeroMin);
EditorGUILayout.PropertyField(editorProperties.RemapCurveZeroMax);
EditorGUILayout.PropertyField(editorProperties.RemapCurveOneMin);
EditorGUILayout.PropertyField(editorProperties.RemapCurveOneMax);
EditorGUILayout.PropertyField(editorProperties.RelativeCurveAmplitude);
EditorGUILayout.PropertyField(editorProperties.UniformValues);
EditorGUILayout.PropertyField(editorProperties.ForceVectorLength);
EditorGUILayout.PropertyField(editorProperties.ForcedVectorLength);
EditorGUILayout.PropertyField(editorProperties.CurvePingPong);
EditorGUILayout.PropertyField(editorProperties.FrequencyMin);
EditorGUILayout.PropertyField(editorProperties.FrequencyMax);
}
EditorGUILayout.PropertyField(editorProperties.LimitedTime);
if (editorProperties.LimitedTime.boolValue)
{
EditorGUILayout.PropertyField(editorProperties.LimitedTimeTotal);
EditorGUILayout.PropertyField(editorProperties.LimitedTimeLeft);
EditorGUILayout.PropertyField(editorProperties.LimitedTimeFalloff);
EditorGUILayout.PropertyField(editorProperties.LimitedTimeResetValue);
}
EditorGUI.EndDisabledGroup();
EditorGUILayout.Space();
}
MMFeedbackStyling.DrawSplitter();
}
}
}

View File

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

View File

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

View File

@@ -0,0 +1,28 @@
using MoreMountains.Tools;
using UnityEngine;
using UnityEditor;
using UnityEditor.UIElements;
using UnityEngine.UIElements;
namespace MoreMountains.Feedbacks
{
[CustomPropertyDrawer(typeof(MMSpringColor))]
class MMSpringColorPropertyDrawer : PropertyDrawer
{
protected float _lastTarget;
protected float _max;
public override VisualElement CreatePropertyGUI(SerializedProperty property)
{
var root = new VisualElement();
SerializedProperty _colorSpring = property.FindPropertyRelative("ColorSpring");
root.Add(new PropertyField(_colorSpring));
return root;
}
}
}

View File

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

View File

@@ -0,0 +1,71 @@
using MoreMountains.Tools;
using UnityEditor;
using UnityEngine;
namespace MoreMountains.Feedbacks
{
[CustomPropertyDrawer(typeof(MMSpringDebug))]
public class MMSpringDebugPropertyDrawer : PropertyDrawer
{
protected Color _backgroundBarColor = new Color(0f, 0f, 0f, 0.3f);
protected Color _frontBarColor = MMColors.Yellow;
protected SerializedProperty _currentValue;
protected SerializedProperty _targetValue;
protected Rect _rect;
protected float _lastTarget;
protected float _max;
public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
{
_currentValue = property.FindPropertyRelative("CurrentValue");
_targetValue = property.FindPropertyRelative("TargetValue");
EditorGUI.BeginProperty(position, label, property);
EditorGUI.BeginDisabledGroup(true);
position = EditorGUI.PrefixLabel(position, GUIUtility.GetControlID(FocusType.Passive), label);
var indent = EditorGUI.indentLevel;
EditorGUI.indentLevel = 0;
_rect.x = position.x;
_rect.y = position.y;
_rect.width = position.width;
_rect.height = position.height;
EditorGUI.DrawRect(_rect, _backgroundBarColor);
if (Application.isPlaying)
{
float current = _currentValue.floatValue;
float target = _targetValue.floatValue;
float normalizedValue = 0f;
float diff = target - current;
if (Mathf.Abs(diff) > Mathf.Abs(_max))
{
_max = diff;
}
if (_lastTarget != target)
{
_max = diff;
}
normalizedValue = MMMaths.Remap(diff, -_max, _max, -1f, 1f);
float newWidth = MMMaths.Remap(normalizedValue, -1f, 1f, -position.width/2f, position.width/2f);
_rect.x = position.x + (position.width/2f);
_rect.y = position.y;
_rect.width = newWidth;
_rect.height = position.height;
EditorGUI.DrawRect(_rect, _frontBarColor);
_lastTarget = target;
}
EditorGUI.indentLevel = indent;
EditorGUI.EndDisabledGroup();
EditorGUI.EndProperty();
}
}
}

View File

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

View File

@@ -0,0 +1,67 @@
using MoreMountains.Tools;
using UnityEngine;
using UnityEditor;
using UnityEditor.UIElements;
using UnityEngine.UIElements;
namespace MoreMountains.Feedbacks
{
[CustomPropertyDrawer(typeof(MMSpringFloat))]
class MMSpringFloatPropertyDrawer : PropertyDrawer
{
protected float _lastTarget;
protected float _max;
public override VisualElement CreatePropertyGUI(SerializedProperty property)
{
var root = new VisualElement();
root.style.backgroundColor = new StyleColor(new Color(255,255,255,0.03f));
root.style.marginTop = 5;
root.style.paddingRight = 5;
SerializedProperty _damping = property.FindPropertyRelative("Damping");
SerializedProperty _frequency = property.FindPropertyRelative("Frequency");
SerializedProperty _unifiedSpring = property.FindPropertyRelative("UnifiedSpring");
SerializedProperty _springDebug = property.FindPropertyRelative("SpringDebug");
root.Add(new PropertyField(_damping));
root.Add(new PropertyField(_frequency));
if (!_unifiedSpring.boolValue)
{
SerializedProperty _clampSettings = property.FindPropertyRelative("ClampSettings");
root.Add(new PropertyField(_clampSettings));
}
if (Application.isPlaying && !_unifiedSpring.boolValue)
{
VisualElement horizontalLayout = new VisualElement();
horizontalLayout.style.flexDirection = FlexDirection.Row;
root.Add(horizontalLayout);
FloatField currentValue = new FloatField("CurrentValue") { bindingPath = "CurrentValueDisplay", isReadOnly = true, style = { flexGrow = 1, paddingRight = 10 } };
currentValue.SetEnabled(false);
currentValue.AddToClassList("mm-fixed-width-floatfield");
horizontalLayout.Add(currentValue);
FloatField targetValue = new FloatField("TargetValue") { bindingPath = "TargetValueDisplay", isReadOnly = true, style = { flexGrow = 1} };
targetValue.SetEnabled(false);
targetValue.AddToClassList("mm-fixed-width-floatfield");
horizontalLayout.Add(targetValue);
FloatField velocity = new FloatField("Velocity") { bindingPath = "VelocityDisplay", isReadOnly = true, style = { flexGrow = 1, paddingLeft = 10} };
velocity.SetEnabled(false);
velocity.AddToClassList("mm-fixed-width-floatfield");
horizontalLayout.Add(velocity);
root.Add(new PropertyField(_springDebug));
}
return root;
}
}
}

View File

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

View File

@@ -0,0 +1,81 @@
using MoreMountains.Tools;
using UnityEngine;
using UnityEditor;
using UnityEditor.UIElements;
using UnityEngine.UIElements;
namespace MoreMountains.Feedbacks
{
[CustomPropertyDrawer(typeof(MMSpringVector2))]
class MMSpringVector2PropertyDrawer : PropertyDrawer
{
protected float _lastTarget;
protected float _max;
protected PropertyField _unifiedSpringField;
protected Label _springXLabel;
protected PropertyField _springXField;
protected Label _springYLabel;
protected PropertyField _springYField;
public override VisualElement CreatePropertyGUI(SerializedProperty property)
{
var root = new VisualElement();
SerializedProperty _separateAxis = property.FindPropertyRelative("SeparateAxis");
SerializedProperty _unifiedSpring = property.FindPropertyRelative("UnifiedSpring");
SerializedProperty _springX = property.FindPropertyRelative("SpringX");
SerializedProperty _springY = property.FindPropertyRelative("SpringY");
Toggle boolToggle = new Toggle("SeparateAxis") { value = property.FindPropertyRelative("SeparateAxis").boolValue };
boolToggle.RegisterValueChangedCallback(evt =>
{
property.FindPropertyRelative("SeparateAxis").boolValue = evt.newValue;
ToggleFields(evt.newValue);
_separateAxis.serializedObject.ApplyModifiedProperties();
});
root.Add(boolToggle);
_unifiedSpringField = new PropertyField(_unifiedSpring);
_springXLabel = new Label("Spring X");
_springXLabel.style.backgroundColor = new StyleColor(new Color(255,0,0,0.2f));
_springXLabel.style.marginLeft = -10;
_springXLabel.style.paddingLeft = 14;
_springXLabel.style.paddingBottom = 3;
_springXLabel.style.paddingTop = 3;
_springXField = new PropertyField(_springX);
_springYLabel = new Label("Spring Y");
_springYLabel.style.backgroundColor = new StyleColor(new Color(0,255,0,0.1f));
_springYLabel.style.marginLeft = -10;
_springYLabel.style.paddingLeft = 14;
_springYLabel.style.paddingBottom = 3;
_springYLabel.style.paddingTop = 3;
_springYField = new PropertyField(_springY);
root.Add(_unifiedSpringField);
root.Add(_springXLabel);
root.Add(_springXField);
root.Add(_springYLabel);
root.Add(_springYField);
ToggleFields(boolToggle.value);
return root;
}
private void ToggleFields(bool show)
{
_unifiedSpringField.style.display = show ? DisplayStyle.None : DisplayStyle.Flex;
_springXLabel.style.display = show ? DisplayStyle.Flex : DisplayStyle.None;
_springXField.style.display = show ? DisplayStyle.Flex : DisplayStyle.None;
_springYLabel.style.display = show ? DisplayStyle.Flex : DisplayStyle.None;
_springYField.style.display = show ? DisplayStyle.Flex : DisplayStyle.None;
}
}
}

View File

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

View File

@@ -0,0 +1,97 @@
using MoreMountains.Tools;
using UnityEngine;
using UnityEditor;
using UnityEditor.UIElements;
using UnityEngine.UIElements;
namespace MoreMountains.Feedbacks
{
[CustomPropertyDrawer(typeof(MMSpringVector3))]
class MMSpringVector3PropertyDrawer : PropertyDrawer
{
protected float _lastTarget;
protected float _max;
protected PropertyField _unifiedSpringField;
protected Label _springXLabel;
protected PropertyField _springXField;
protected Label _springYLabel;
protected PropertyField _springYField;
protected Label _springZLabel;
protected PropertyField _springZField;
public override VisualElement CreatePropertyGUI(SerializedProperty property)
{
var root = new VisualElement();
SerializedProperty _separateAxis = property.FindPropertyRelative("SeparateAxis");
SerializedProperty _unifiedSpring = property.FindPropertyRelative("UnifiedSpring");
SerializedProperty _springX = property.FindPropertyRelative("SpringX");
SerializedProperty _springY = property.FindPropertyRelative("SpringY");
SerializedProperty _springZ = property.FindPropertyRelative("SpringZ");
Toggle boolToggle = new Toggle("SeparateAxis") { value = property.FindPropertyRelative("SeparateAxis").boolValue };
boolToggle.RegisterValueChangedCallback(evt =>
{
property.FindPropertyRelative("SeparateAxis").boolValue = evt.newValue;
ToggleFields(evt.newValue);
_separateAxis.serializedObject.ApplyModifiedProperties();
});
root.Add(boolToggle);
_unifiedSpringField = new PropertyField(_unifiedSpring);
_springXLabel = new Label("Spring X");
_springXLabel.style.backgroundColor = new StyleColor(new Color(1f,0,0,0.2f));
_springXLabel.style.marginLeft = -10;
_springXLabel.style.paddingLeft = 14;
_springXLabel.style.paddingBottom = 3;
_springXLabel.style.paddingTop = 3;
_springXField = new PropertyField(_springX);
_springYLabel = new Label("Spring Y");
_springYLabel.style.backgroundColor = new StyleColor(new Color(0,1f,0,0.1f));
_springYLabel.style.marginLeft = -10;
_springYLabel.style.paddingLeft = 14;
_springYLabel.style.paddingBottom = 3;
_springYLabel.style.paddingTop = 3;
_springYField = new PropertyField(_springY);
_springZLabel = new Label("Spring Z");
_springZLabel.style.backgroundColor = new StyleColor(new Color(0,0.4f,0.9f,0.2f));
_springZLabel.style.marginLeft = -10;
_springZLabel.style.paddingLeft = 14;
_springZLabel.style.paddingBottom = 3;
_springZLabel.style.paddingTop = 3;
_springZField = new PropertyField(_springZ);
root.Add(_unifiedSpringField);
root.Add(_springXLabel);
root.Add(_springXField);
root.Add(_springYLabel);
root.Add(_springYField);
root.Add(_springZLabel);
root.Add(_springZField);
ToggleFields(boolToggle.value);
return root;
}
private void ToggleFields(bool show)
{
_unifiedSpringField.style.display = show ? DisplayStyle.None : DisplayStyle.Flex;
_springXLabel.style.display = show ? DisplayStyle.Flex : DisplayStyle.None;
_springXField.style.display = show ? DisplayStyle.Flex : DisplayStyle.None;
_springYLabel.style.display = show ? DisplayStyle.Flex : DisplayStyle.None;
_springYField.style.display = show ? DisplayStyle.Flex : DisplayStyle.None;
_springZLabel.style.display = show ? DisplayStyle.Flex : DisplayStyle.None;
_springZField.style.display = show ? DisplayStyle.Flex : DisplayStyle.None;
}
}
}

View File

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

View File

@@ -0,0 +1,110 @@
using MoreMountains.Tools;
using UnityEngine;
using UnityEditor;
using UnityEditor.UIElements;
using UnityEngine.UIElements;
namespace MoreMountains.Feedbacks
{
[CustomPropertyDrawer(typeof(MMSpringVector4))]
class MMSpringVector4PropertyDrawer : PropertyDrawer
{
protected float _lastTarget;
protected float _max;
protected PropertyField _unifiedSpringField;
protected Label _springXLabel;
protected PropertyField _springXField;
protected Label _springYLabel;
protected PropertyField _springYField;
protected Label _springZLabel;
protected PropertyField _springZField;
protected Label _springWLabel;
protected PropertyField _springWField;
public override VisualElement CreatePropertyGUI(SerializedProperty property)
{
var root = new VisualElement();
SerializedProperty _separateAxis = property.FindPropertyRelative("SeparateAxis");
SerializedProperty _unifiedSpring = property.FindPropertyRelative("UnifiedSpring");
SerializedProperty _springX = property.FindPropertyRelative("SpringX");
SerializedProperty _springY = property.FindPropertyRelative("SpringY");
SerializedProperty _springZ = property.FindPropertyRelative("SpringZ");
SerializedProperty _springW = property.FindPropertyRelative("SpringW");
Toggle boolToggle = new Toggle("SeparateAxis") { value = property.FindPropertyRelative("SeparateAxis").boolValue };
boolToggle.RegisterValueChangedCallback(evt =>
{
property.FindPropertyRelative("SeparateAxis").boolValue = evt.newValue;
ToggleFields(evt.newValue);
_separateAxis.serializedObject.ApplyModifiedProperties();
});
root.Add(boolToggle);
_unifiedSpringField = new PropertyField(_unifiedSpring);
_springXLabel = new Label("Spring X");
_springXLabel.style.backgroundColor = new StyleColor(new Color(1f,0,0,0.2f));
_springXLabel.style.marginLeft = -10;
_springXLabel.style.paddingLeft = 14;
_springXLabel.style.paddingBottom = 3;
_springXLabel.style.paddingTop = 3;
_springXField = new PropertyField(_springX);
_springYLabel = new Label("Spring Y");
_springYLabel.style.backgroundColor = new StyleColor(new Color(0,1f,0,0.1f));
_springYLabel.style.marginLeft = -10;
_springYLabel.style.paddingLeft = 14;
_springYLabel.style.paddingBottom = 3;
_springYLabel.style.paddingTop = 3;
_springYField = new PropertyField(_springY);
_springZLabel = new Label("Spring Z");
_springZLabel.style.backgroundColor = new StyleColor(new Color(0,0.4f,0.9f,0.2f));
_springZLabel.style.marginLeft = -10;
_springZLabel.style.paddingLeft = 14;
_springZLabel.style.paddingBottom = 3;
_springZLabel.style.paddingTop = 3;
_springZField = new PropertyField(_springZ);
_springWLabel = new Label("Spring W");
_springWLabel.style.backgroundColor = new StyleColor(new Color(0.7f,0f,0.7f,0.2f));
_springWLabel.style.marginLeft = -10;
_springWLabel.style.paddingLeft = 14;
_springWLabel.style.paddingBottom = 3;
_springWLabel.style.paddingTop = 3;
_springWField = new PropertyField(_springW);
root.Add(_unifiedSpringField);
root.Add(_springXLabel);
root.Add(_springXField);
root.Add(_springYLabel);
root.Add(_springYField);
root.Add(_springZLabel);
root.Add(_springZField);
root.Add(_springWLabel);
root.Add(_springWField);
ToggleFields(boolToggle.value);
return root;
}
private void ToggleFields(bool show)
{
_unifiedSpringField.style.display = show ? DisplayStyle.None : DisplayStyle.Flex;
_springXLabel.style.display = show ? DisplayStyle.Flex : DisplayStyle.None;
_springXField.style.display = show ? DisplayStyle.Flex : DisplayStyle.None;
_springYLabel.style.display = show ? DisplayStyle.Flex : DisplayStyle.None;
_springYField.style.display = show ? DisplayStyle.Flex : DisplayStyle.None;
_springZLabel.style.display = show ? DisplayStyle.Flex : DisplayStyle.None;
_springZField.style.display = show ? DisplayStyle.Flex : DisplayStyle.None;
_springWLabel.style.display = show ? DisplayStyle.Flex : DisplayStyle.None;
_springWField.style.display = show ? DisplayStyle.Flex : DisplayStyle.None;
}
}
}

View File

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

View File

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

View File

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

View File

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

View File

@@ -0,0 +1,598 @@
using System;
using System.Collections;
using System.Collections.Generic;
using MoreMountains.Tools;
using UnityEngine;
using Random = UnityEngine.Random;
namespace MoreMountains.Feedbacks
{
/// <summary>
/// A base class, meant to be extended, defining a Feedback. A Feedback is an action triggered by a MMFeedbacks, usually in reaction to the player's input or actions,
/// to help communicate both emotion and legibility, improving game feel.
/// To create a new feedback, extend this class and override its Custom methods, declared at the end of this class. You can look at the many examples for reference.
/// </summary>
[AddComponentMenu("")]
[System.Serializable]
[ExecuteAlways]
public abstract class MMFeedback : MonoBehaviour
{
/// whether or not this feedback is active
[Tooltip("whether or not this feedback is active")]
public bool Active = true;
/// the name of this feedback to display in the inspector
[Tooltip("the name of this feedback to display in the inspector")]
public string Label = "MMFeedback";
/// the chance of this feedback happening (in percent : 100 : happens all the time, 0 : never happens, 50 : happens once every two calls, etc)
[Tooltip("the chance of this feedback happening (in percent : 100 : happens all the time, 0 : never happens, 50 : happens once every two calls, etc)")]
[Range(0,100)]
public float Chance = 100f;
/// a number of timing-related values (delay, repeat, etc)
[Tooltip("a number of timing-related values (delay, repeat, etc)")]
public MMFeedbackTiming Timing;
/// the Owner of the feedback, as defined when calling the Initialization method
public GameObject Owner { get; set; }
[HideInInspector]
/// whether or not this feedback is in debug mode
public bool DebugActive = false;
/// set this to true if your feedback should pause the execution of the feedback sequence
public virtual IEnumerator Pause { get { return null; } }
/// if this is true, this feedback will wait until all previous feedbacks have run
public virtual bool HoldingPause { get { return false; } }
/// if this is true, this feedback will wait until all previous feedbacks have run, then run all previous feedbacks again
public virtual bool LooperPause { get { return false; } }
/// if this is true, this feedback will pause and wait until Resume() is called on its parent MMFeedbacks to resume execution
public virtual bool ScriptDrivenPause { get; set; }
/// if this is a positive value, the feedback will auto resume after that duration if it hasn't been resumed via script already
public virtual float ScriptDrivenPauseAutoResume { get; set; }
/// if this is true, this feedback will wait until all previous feedbacks have run, then run all previous feedbacks again
public virtual bool LooperStart { get { return false; } }
/// an overridable color for your feedback, that can be redefined per feedback. White is the only reserved color, and the feedback will revert to
/// normal (light or dark skin) when left to White
#if UNITY_EDITOR
public virtual Color FeedbackColor { get { return Color.white; } }
#endif
/// returns true if this feedback is in cooldown at this time (and thus can't play), false otherwise
public virtual bool InCooldown { get { return (Timing.CooldownDuration > 0f) && (FeedbackTime - _lastPlayTimestamp < Timing.CooldownDuration); } }
/// if this is true, this feedback is currently playing
public virtual bool IsPlaying { get; set; }
/// the time (or unscaled time) based on the selected Timing settings
public float FeedbackTime
{
get
{
if (Timing.TimescaleMode == TimescaleModes.Scaled)
{
return Time.time;
}
else
{
return Time.unscaledTime;
}
}
}
/// the delta time (or unscaled delta time) based on the selected Timing settings
public float FeedbackDeltaTime
{
get
{
if (Timing.TimescaleMode == TimescaleModes.Scaled)
{
return Time.deltaTime;
}
else
{
return Time.unscaledDeltaTime;
}
}
}
/// <summary>
/// The total duration of this feedback :
/// total = initial delay + duration * (number of repeats + delay between repeats)
/// </summary>
public float TotalDuration
{
get
{
if ((Timing != null) && (!Timing.ContributeToTotalDuration))
{
return 0f;
}
float totalTime = 0f;
if (Timing == null)
{
return 0f;
}
if (Timing.InitialDelay != 0)
{
totalTime += ApplyTimeMultiplier(Timing.InitialDelay);
}
totalTime += FeedbackDuration;
if (Timing.NumberOfRepeats > 0)
{
float delayBetweenRepeats = ApplyTimeMultiplier(Timing.DelayBetweenRepeats);
totalTime += (Timing.NumberOfRepeats * FeedbackDuration) + (Timing.NumberOfRepeats * delayBetweenRepeats);
}
return totalTime;
}
}
// the timestamp at which this feedback was last played
public virtual float FeedbackStartedAt { get { return _lastPlayTimestamp; } }
// the perceived duration of the feedback, to be used to display its progress bar, meant to be overridden with meaningful data by each feedback
public virtual float FeedbackDuration { get { return 0f; } set { } }
/// whether or not this feedback is playing right now
public virtual bool FeedbackPlaying { get { return ((FeedbackStartedAt > 0f) && (Time.time - FeedbackStartedAt < FeedbackDuration)); } }
public virtual MMChannelData ChannelData(int channel) => _channelData.Set(MMChannelModes.Int, channel, null);
protected float _lastPlayTimestamp = -1f;
protected int _playsLeft;
protected bool _initialized = false;
protected Coroutine _playCoroutine;
protected Coroutine _infinitePlayCoroutine;
protected Coroutine _sequenceCoroutine;
protected Coroutine _repeatedPlayCoroutine;
protected int _sequenceTrackID = 0;
protected MMFeedbacks _hostMMFeedbacks;
protected float _beatInterval;
protected bool BeatThisFrame = false;
protected int LastBeatIndex = 0;
protected int CurrentSequenceIndex = 0;
protected float LastBeatTimestamp = 0f;
protected bool _isHostMMFeedbacksNotNull;
protected MMChannelData _channelData;
protected virtual void OnEnable()
{
_hostMMFeedbacks = this.gameObject.GetComponent<MMFeedbacks>();
_isHostMMFeedbacksNotNull = _hostMMFeedbacks != null;
}
/// <summary>
/// Initializes the feedback and its timing related variables
/// </summary>
/// <param name="owner"></param>
public virtual void Initialization(GameObject owner)
{
_initialized = true;
Owner = owner;
_playsLeft = Timing.NumberOfRepeats + 1;
_hostMMFeedbacks = this.gameObject.GetComponent<MMFeedbacks>();
_channelData = new MMChannelData(MMChannelModes.Int, 0, null);
SetInitialDelay(Timing.InitialDelay);
SetDelayBetweenRepeats(Timing.DelayBetweenRepeats);
SetSequence(Timing.Sequence);
CustomInitialization(owner);
}
/// <summary>
/// Plays the feedback
/// </summary>
/// <param name="position"></param>
/// <param name="feedbacksIntensity"></param>
public virtual void Play(Vector3 position, float feedbacksIntensity = 1.0f)
{
if (!Active)
{
return;
}
if (!_initialized)
{
Debug.LogWarning("The " + this + " feedback is being played without having been initialized. Call Initialization() first.");
}
// we check the cooldown
if (InCooldown)
{
return;
}
if (Timing.InitialDelay > 0f)
{
_playCoroutine = StartCoroutine(PlayCoroutine(position, feedbacksIntensity));
}
else
{
_lastPlayTimestamp = FeedbackTime;
RegularPlay(position, feedbacksIntensity);
}
}
/// <summary>
/// An internal coroutine delaying the initial play of the feedback
/// </summary>
/// <param name="position"></param>
/// <param name="feedbacksIntensity"></param>
/// <returns></returns>
protected virtual IEnumerator PlayCoroutine(Vector3 position, float feedbacksIntensity = 1.0f)
{
if (Timing.TimescaleMode == TimescaleModes.Scaled)
{
yield return MMFeedbacksCoroutine.WaitFor(Timing.InitialDelay);
}
else
{
yield return MMFeedbacksCoroutine.WaitForUnscaled(Timing.InitialDelay);
}
_lastPlayTimestamp = FeedbackTime;
RegularPlay(position, feedbacksIntensity);
}
/// <summary>
/// Triggers delaying coroutines if needed
/// </summary>
/// <param name="position"></param>
/// <param name="feedbacksIntensity"></param>
protected virtual void RegularPlay(Vector3 position, float feedbacksIntensity = 1.0f)
{
if (Chance == 0f)
{
return;
}
if (Chance != 100f)
{
// determine the odds
float random = Random.Range(0f, 100f);
if (random > Chance)
{
return;
}
}
if (Timing.UseIntensityInterval)
{
if ((feedbacksIntensity < Timing.IntensityIntervalMin) || (feedbacksIntensity >= Timing.IntensityIntervalMax))
{
return;
}
}
if (Timing.RepeatForever)
{
_infinitePlayCoroutine = StartCoroutine(InfinitePlay(position, feedbacksIntensity));
return;
}
if (Timing.NumberOfRepeats > 0)
{
_repeatedPlayCoroutine = StartCoroutine(RepeatedPlay(position, feedbacksIntensity));
return;
}
if (Timing.Sequence == null)
{
CustomPlayFeedback(position, feedbacksIntensity);
}
else
{
_sequenceCoroutine = StartCoroutine(SequenceCoroutine(position, feedbacksIntensity));
}
}
/// <summary>
/// Internal coroutine used for repeated play without end
/// </summary>
/// <param name="position"></param>
/// <param name="feedbacksIntensity"></param>
/// <returns></returns>
protected virtual IEnumerator InfinitePlay(Vector3 position, float feedbacksIntensity = 1.0f)
{
while (true)
{
_lastPlayTimestamp = FeedbackTime;
if (Timing.Sequence == null)
{
CustomPlayFeedback(position, feedbacksIntensity);
if (Timing.TimescaleMode == TimescaleModes.Scaled)
{
yield return MMFeedbacksCoroutine.WaitFor(Timing.DelayBetweenRepeats);
}
else
{
yield return MMFeedbacksCoroutine.WaitForUnscaled(Timing.DelayBetweenRepeats);
}
}
else
{
_sequenceCoroutine = StartCoroutine(SequenceCoroutine(position, feedbacksIntensity));
float delay = ApplyTimeMultiplier(Timing.DelayBetweenRepeats) + Timing.Sequence.Length;
if (Timing.TimescaleMode == TimescaleModes.Scaled)
{
yield return MMFeedbacksCoroutine.WaitFor(delay);
}
else
{
yield return MMFeedbacksCoroutine.WaitForUnscaled(delay);
}
}
}
}
/// <summary>
/// Internal coroutine used for repeated play
/// </summary>
/// <param name="position"></param>
/// <param name="feedbacksIntensity"></param>
/// <returns></returns>
protected virtual IEnumerator RepeatedPlay(Vector3 position, float feedbacksIntensity = 1.0f)
{
while (_playsLeft > 0)
{
_lastPlayTimestamp = FeedbackTime;
_playsLeft--;
if (Timing.Sequence == null)
{
CustomPlayFeedback(position, feedbacksIntensity);
if (Timing.TimescaleMode == TimescaleModes.Scaled)
{
yield return MMFeedbacksCoroutine.WaitFor(Timing.DelayBetweenRepeats);
}
else
{
yield return MMFeedbacksCoroutine.WaitForUnscaled(Timing.DelayBetweenRepeats);
}
}
else
{
_sequenceCoroutine = StartCoroutine(SequenceCoroutine(position, feedbacksIntensity));
float delay = ApplyTimeMultiplier(Timing.DelayBetweenRepeats) + Timing.Sequence.Length;
if (Timing.TimescaleMode == TimescaleModes.Scaled)
{
yield return MMFeedbacksCoroutine.WaitFor(delay);
}
else
{
yield return MMFeedbacksCoroutine.WaitForUnscaled(delay);
}
}
}
_playsLeft = Timing.NumberOfRepeats + 1;
}
/// <summary>
/// A coroutine used to play this feedback on a sequence
/// </summary>
/// <param name="position"></param>
/// <param name="feedbacksIntensity"></param>
/// <returns></returns>
protected virtual IEnumerator SequenceCoroutine(Vector3 position, float feedbacksIntensity = 1.0f)
{
yield return null;
float timeStartedAt = FeedbackTime;
float lastFrame = FeedbackTime;
BeatThisFrame = false;
LastBeatIndex = 0;
CurrentSequenceIndex = 0;
LastBeatTimestamp = 0f;
if (Timing.Quantized)
{
while (CurrentSequenceIndex < Timing.Sequence.QuantizedSequence[0].Line.Count)
{
_beatInterval = 60f / Timing.TargetBPM;
if ((FeedbackTime - LastBeatTimestamp >= _beatInterval) || (LastBeatTimestamp == 0f))
{
BeatThisFrame = true;
LastBeatIndex = CurrentSequenceIndex;
LastBeatTimestamp = FeedbackTime;
for (int i = 0; i < Timing.Sequence.SequenceTracks.Count; i++)
{
if (Timing.Sequence.QuantizedSequence[i].Line[CurrentSequenceIndex].ID == Timing.TrackID)
{
CustomPlayFeedback(position, feedbacksIntensity);
}
}
CurrentSequenceIndex++;
}
yield return null;
}
}
else
{
while (FeedbackTime - timeStartedAt < Timing.Sequence.Length)
{
foreach (MMSequenceNote item in Timing.Sequence.OriginalSequence.Line)
{
if ((item.ID == Timing.TrackID) && (item.Timestamp >= lastFrame) && (item.Timestamp <= FeedbackTime - timeStartedAt))
{
CustomPlayFeedback(position, feedbacksIntensity);
}
}
lastFrame = FeedbackTime - timeStartedAt;
yield return null;
}
}
}
/// <summary>
/// Stops all feedbacks from playing. Will stop repeating feedbacks, and call custom stop implementations
/// </summary>
/// <param name="position"></param>
/// <param name="feedbacksIntensity"></param>
public virtual void Stop(Vector3 position, float feedbacksIntensity = 1.0f)
{
if (_playCoroutine != null) { StopCoroutine(_playCoroutine); }
if (_infinitePlayCoroutine != null) { StopCoroutine(_infinitePlayCoroutine); }
if (_repeatedPlayCoroutine != null) { StopCoroutine(_repeatedPlayCoroutine); }
if (_sequenceCoroutine != null) { StopCoroutine(_sequenceCoroutine); }
_lastPlayTimestamp = 0f;
_playsLeft = Timing.NumberOfRepeats + 1;
if (Timing.InterruptsOnStop)
{
CustomStopFeedback(position, feedbacksIntensity);
}
}
/// <summary>
/// Calls this feedback's custom reset
/// </summary>
public virtual void ResetFeedback()
{
_playsLeft = Timing.NumberOfRepeats + 1;
CustomReset();
}
/// <summary>
/// Use this method to change this feedback's sequence at runtime
/// </summary>
/// <param name="newSequence"></param>
public virtual void SetSequence(MMSequence newSequence)
{
Timing.Sequence = newSequence;
if (Timing.Sequence != null)
{
for (int i = 0; i < Timing.Sequence.SequenceTracks.Count; i++)
{
if (Timing.Sequence.SequenceTracks[i].ID == Timing.TrackID)
{
_sequenceTrackID = i;
}
}
}
}
/// <summary>
/// Use this method to specify a new delay between repeats at runtime
/// </summary>
/// <param name="delay"></param>
public virtual void SetDelayBetweenRepeats(float delay)
{
Timing.DelayBetweenRepeats = delay;
}
/// <summary>
/// Use this method to specify a new initial delay at runtime
/// </summary>
/// <param name="delay"></param>
public virtual void SetInitialDelay(float delay)
{
Timing.InitialDelay = delay;
}
/// <summary>
/// Returns a new value of the normalized time based on the current play direction of this feedback
/// </summary>
/// <param name="normalizedTime"></param>
/// <returns></returns>
protected virtual float ApplyDirection(float normalizedTime)
{
return NormalPlayDirection ? normalizedTime : 1 - normalizedTime;
}
/// <summary>
/// Returns true if this feedback should play normally, or false if it should play in rewind
/// </summary>
public virtual bool NormalPlayDirection
{
get
{
switch (Timing.PlayDirection)
{
case MMFeedbackTiming.PlayDirections.FollowMMFeedbacksDirection:
return (_hostMMFeedbacks.Direction == MMFeedbacks.Directions.TopToBottom);
case MMFeedbackTiming.PlayDirections.AlwaysNormal:
return true;
case MMFeedbackTiming.PlayDirections.AlwaysRewind:
return false;
case MMFeedbackTiming.PlayDirections.OppositeMMFeedbacksDirection:
return !(_hostMMFeedbacks.Direction == MMFeedbacks.Directions.TopToBottom);
}
return true;
}
}
/// <summary>
/// Returns true if this feedback should play in the current parent MMFeedbacks direction, according to its MMFeedbacksDirectionCondition setting
/// </summary>
public virtual bool ShouldPlayInThisSequenceDirection
{
get
{
switch (Timing.MMFeedbacksDirectionCondition)
{
case MMFeedbackTiming.MMFeedbacksDirectionConditions.Always:
return true;
case MMFeedbackTiming.MMFeedbacksDirectionConditions.OnlyWhenForwards:
return (_hostMMFeedbacks.Direction == MMFeedbacks.Directions.TopToBottom);
case MMFeedbackTiming.MMFeedbacksDirectionConditions.OnlyWhenBackwards:
return (_hostMMFeedbacks.Direction == MMFeedbacks.Directions.BottomToTop);
}
return true;
}
}
/// <summary>
/// Returns the t value at which to evaluate a curve at the end of this feedback's play time
/// </summary>
protected virtual float FinalNormalizedTime
{
get
{
return NormalPlayDirection ? 1f : 0f;
}
}
/// <summary>
/// Applies the host MMFeedbacks' time multiplier to this feedback
/// </summary>
/// <param name="duration"></param>
/// <returns></returns>
protected virtual float ApplyTimeMultiplier(float duration)
{
if (_isHostMMFeedbacksNotNull)
{
return _hostMMFeedbacks.ApplyTimeMultiplier(duration);
}
return duration;
}
/// <summary>
/// This method describes all custom initialization processes the feedback requires, in addition to the main Initialization method
/// </summary>
/// <param name="owner"></param>
protected virtual void CustomInitialization(GameObject owner) { }
/// <summary>
/// This method describes what happens when the feedback gets played
/// </summary>
/// <param name="position"></param>
/// <param name="feedbacksIntensity"></param>
protected abstract void CustomPlayFeedback(Vector3 position, float feedbacksIntensity = 1.0f);
/// <summary>
/// This method describes what happens when the feedback gets stopped
/// </summary>
/// <param name="position"></param>
/// <param name="feedbacksIntensity"></param>
protected virtual void CustomStopFeedback(Vector3 position, float feedbacksIntensity = 1.0f) { }
/// <summary>
/// This method describes what happens when the feedback gets reset
/// </summary>
protected virtual void CustomReset() { }
}
}

View File

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

View File

@@ -0,0 +1,924 @@
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using MoreMountains.Feedbacks;
using System.Linq;
using MoreMountains.Tools;
using UnityEditor.Experimental;
using UnityEngine.Events;
using Random = UnityEngine.Random;
#if UNITY_EDITOR
using UnityEditor;
#endif
namespace MoreMountains.Feedbacks
{
/// <summary>
/// A collection of MMFeedback, meant to be played altogether.
/// This class provides a custom inspector to add and customize feedbacks, and public methods to trigger them, stop them, etc.
/// You can either use it on its own, or bind it from another class and trigger it from there.
/// </summary>
[AddComponentMenu("")]
public class MMFeedbacks : MonoBehaviour
{
/// the possible directions MMFeedbacks can be played
public enum Directions { TopToBottom, BottomToTop }
/// the possible SafeModes (will perform checks to make sure no serialization error has damaged them)
/// - nope : no safety
/// - editor only : performs checks on enable
/// - runtime only : performs checks on Awake
/// - full : performs both editor and runtime checks, recommended setting
public enum SafeModes { Nope, EditorOnly, RuntimeOnly, Full }
/// a list of MMFeedback to trigger
public List<MMFeedback> Feedbacks = new List<MMFeedback>();
/// the possible initialization modes. If you use Script, you'll have to initialize manually by calling the Initialization method and passing it an owner
/// Otherwise, you can have this component initialize itself at Awake or Start, and in this case the owner will be the MMFeedbacks itself
public enum InitializationModes { Script, Awake, Start }
/// the chosen initialization mode
[Tooltip("the chosen initialization modes. If you use Script, you'll have to initialize manually by calling the " +
"Initialization method and passing it an owner. Otherwise, you can have this component initialize " +
"itself at Awake or Start, and in this case the owner will be the MMFeedbacks itself")]
public InitializationModes InitializationMode = InitializationModes.Start;
/// if you set this to true, the system will make changes to ensure that initialization always happens before play
[Tooltip("if you set this to true, the system will make changes to ensure that initialization always happens before play")]
public bool AutoInitialization = true;
/// the selected safe mode
[Tooltip("the selected safe mode")]
public SafeModes SafeMode = SafeModes.Full;
/// the selected direction
[Tooltip("the selected direction these feedbacks should play in")]
public Directions Direction = Directions.TopToBottom;
/// whether or not this MMFeedbacks should invert its direction when all feedbacks have played
[Tooltip("whether or not this MMFeedbacks should invert its direction when all feedbacks have played")]
public bool AutoChangeDirectionOnEnd = false;
/// whether or not to play this feedbacks automatically on Start
[Tooltip("whether or not to play this feedbacks automatically on Start")]
public bool AutoPlayOnStart = false;
/// whether or not to play this feedbacks automatically on Enable
[Tooltip("whether or not to play this feedbacks automatically on Enable")]
public bool AutoPlayOnEnable = false;
/// if this is true, all feedbacks within that player will work on the specified ForcedTimescaleMode, regardless of their individual settings
[Tooltip("if this is true, all feedbacks within that player will work on the specified ForcedTimescaleMode, regardless of their individual settings")]
public bool ForceTimescaleMode = false;
/// the time scale mode all feedbacks on this player should work on, if ForceTimescaleMode is true
[Tooltip("the time scale mode all feedbacks on this player should work on, if ForceTimescaleMode is true")]
[MMFCondition("ForceTimescaleMode", true)]
public TimescaleModes ForcedTimescaleMode = TimescaleModes.Unscaled;
/// a time multiplier that will be applied to all feedback durations (initial delay, duration, delay between repeats...)
[Tooltip("a time multiplier that will be applied to all feedback durations (initial delay, duration, delay between repeats...)")]
public float DurationMultiplier = 1f;
/// a multiplier to apply to all timescale operations (1: normal, less than 1: slower operations, higher than 1: faster operations)
[Tooltip("a multiplier to apply to all timescale operations (1: normal, less than 1: slower operations, higher than 1: faster operations)")]
public float TimescaleMultiplier = 1f;
/// if this is true, will expose a RandomDurationMultiplier. The final duration of each feedback will be : their base duration * DurationMultiplier * a random value between RandomDurationMultiplier.x and RandomDurationMultiplier.y
[Tooltip("if this is true, will expose a RandomDurationMultiplier. The final duration of each feedback will be : their base duration * DurationMultiplier * a random value between RandomDurationMultiplier.x and RandomDurationMultiplier.y")]
public bool RandomizeDuration = false;
/// if RandomizeDuration is true, the min (x) and max (y) values for the random duration multiplier
[Tooltip("if RandomizeDuration is true, the min (x) and max (y) values for the random duration multiplier")]
[MMCondition("RandomizeDuration", true)]
public Vector2 RandomDurationMultiplier = new Vector2(0.5f, 1.5f);
/// if this is true, more editor-only, detailed info will be displayed per feedback in the duration slot
[Tooltip("if this is true, more editor-only, detailed info will be displayed per feedback in the duration slot")]
public bool DisplayFullDurationDetails = false;
/// the timescale at which the player itself will operate. This notably impacts sequencing and pauses duration evaluation.
[Tooltip("the timescale at which the player itself will operate. This notably impacts sequencing and pauses duration evaluation.")]
public TimescaleModes PlayerTimescaleMode = TimescaleModes.Unscaled;
/// if this is true, this feedback will only play if its distance to RangeCenter is lower or equal to RangeDistance
[Tooltip("if this is true, this feedback will only play if its distance to RangeCenter is lower or equal to RangeDistance")]
public bool OnlyPlayIfWithinRange = false;
/// when in OnlyPlayIfWithinRange mode, the transform to consider as the center of the range
[Tooltip("when in OnlyPlayIfWithinRange mode, the transform to consider as the center of the range")]
public Transform RangeCenter;
/// when in OnlyPlayIfWithinRange mode, the distance to the center within which the feedback will play
[Tooltip("when in OnlyPlayIfWithinRange mode, the distance to the center within which the feedback will play")]
public float RangeDistance = 5f;
/// when in OnlyPlayIfWithinRange mode, whether or not to modify the intensity of feedbacks based on the RangeFallOff curve
[Tooltip("when in OnlyPlayIfWithinRange mode, whether or not to modify the intensity of feedbacks based on the RangeFallOff curve")]
public bool UseRangeFalloff = false;
/// the animation curve to use to define falloff (on the x 0 represents the range center, 1 represents the max distance to it)
[Tooltip("the animation curve to use to define falloff (on the x 0 represents the range center, 1 represents the max distance to it)")]
[MMFCondition("UseRangeFalloff", true)]
public AnimationCurve RangeFalloff = new AnimationCurve(new Keyframe(0f, 1f), new Keyframe(1f, 0f));
/// the values to remap the falloff curve's y axis' 0 and 1
[Tooltip("the values to remap the falloff curve's y axis' 0 and 1")]
[MMFVector("Zero","One")]
public Vector2 RemapRangeFalloff = new Vector2(0f, 1f);
/// whether or not to ignore MMSetFeedbackRangeCenterEvent, used to set the RangeCenter from anywhere
[Tooltip("whether or not to ignore MMSetFeedbackRangeCenterEvent, used to set the RangeCenter from anywhere")]
public bool IgnoreRangeEvents = false;
/// a duration, in seconds, during which triggering a new play of this MMFeedbacks after it's been played once will be impossible
[Tooltip("a duration, in seconds, during which triggering a new play of this MMFeedbacks after it's been played once will be impossible")]
public float CooldownDuration = 0f;
/// a duration, in seconds, to delay the start of this MMFeedbacks' contents play
[Tooltip("a duration, in seconds, to delay the start of this MMFeedbacks' contents play")]
public float InitialDelay = 0f;
/// whether this player can be played or not, useful to temporarily prevent play from another class, for example
[Tooltip("whether this player can be played or not, useful to temporarily prevent play from another class, for example")]
public bool CanPlay = true;
/// if this is true, you'll be able to trigger a new Play while this feedback is already playing, otherwise you won't be able to
[Tooltip("if this is true, you'll be able to trigger a new Play while this feedback is already playing, otherwise you won't be able to")]
public bool CanPlayWhileAlreadyPlaying = true;
/// the chance of this sequence happening (in percent : 100 : happens all the time, 0 : never happens, 50 : happens once every two calls, etc)
[Tooltip("the chance of this sequence happening (in percent : 100 : happens all the time, 0 : never happens, 50 : happens once every two calls, etc)")]
[Range(0,100)]
public float ChanceToPlay = 100f;
/// the intensity at which to play this feedback. That value will be used by most feedbacks to tune their amplitude. 1 is normal, 0.5 is half power, 0 is no effect.
/// Note that what this value controls depends from feedback to feedback, don't hesitate to check the code to see what it does exactly.
[Tooltip("the intensity at which to play this feedback. That value will be used by most feedbacks to tune their amplitude. 1 is normal, 0.5 is half power, 0 is no effect." +
"Note that what this value controls depends from feedback to feedback, don't hesitate to check the code to see what it does exactly.")]
public float FeedbacksIntensity = 1f;
/// a number of UnityEvents that can be triggered at the various stages of this MMFeedbacks
[Tooltip("a number of UnityEvents that can be triggered at the various stages of this MMFeedbacks")]
public MMFeedbacksEvents Events;
/// a global switch used to turn all feedbacks on or off globally
[Tooltip("a global switch used to turn all feedbacks on or off globally")]
public static bool GlobalMMFeedbacksActive = true;
[HideInInspector]
/// whether or not this MMFeedbacks is in debug mode
public bool DebugActive = false;
/// whether or not this MMFeedbacks is playing right now - meaning it hasn't been stopped yet.
/// if you don't stop your MMFeedbacks it'll remain true of course
public bool IsPlaying { get; protected set; }
/// if this MMFeedbacks is playing the time since it started playing
public virtual float ElapsedTime => IsPlaying ? GetTime() - _lastStartAt : 0f;
/// the amount of times this MMFeedbacks has been played
public int TimesPlayed { get; protected set; }
/// whether or not the execution of this MMFeedbacks' sequence is being prevented and waiting for a Resume() call
public bool InScriptDrivenPause { get; set; }
/// true if this MMFeedbacks contains at least one loop
public bool ContainsLoop { get; set; }
/// true if this feedback should change play direction next time it's played
public bool ShouldRevertOnNextPlay { get; set; }
/// true if this player is forcing unscaled mode
public bool ForcingUnscaledTimescaleMode { get { return (ForceTimescaleMode && ForcedTimescaleMode == TimescaleModes.Unscaled); } }
/// The total duration (in seconds) of all the active feedbacks in this MMFeedbacks
public virtual float TotalDuration
{
get
{
float total = 0f;
foreach (MMFeedback feedback in Feedbacks)
{
if ((feedback != null) && (feedback.Active))
{
if (total < feedback.TotalDuration)
{
total = feedback.TotalDuration;
}
}
}
return ComputedInitialDelay + total;
}
}
public virtual float GetTime() { return (PlayerTimescaleMode == TimescaleModes.Scaled) ? Time.time : Time.unscaledTime; }
public virtual float GetDeltaTime() { return (PlayerTimescaleMode == TimescaleModes.Scaled) ? Time.deltaTime : Time.unscaledDeltaTime; }
public virtual float ComputedInitialDelay => ApplyTimeMultiplier(InitialDelay);
protected float _startTime = 0f;
protected float _holdingMax = 0f;
protected float _lastStartAt = -float.MaxValue;
protected int _lastStartFrame = -1;
protected bool _pauseFound = false;
protected float _totalDuration = 0f;
protected bool _shouldStop = false;
protected const float _smallValue = 0.001f;
protected float _randomDurationMultiplier = 1f;
protected float _lastOnEnableFrame = -1;
#region INITIALIZATION
/// <summary>
/// On Awake we initialize our feedbacks if we're in auto mode
/// </summary>
protected virtual void Awake()
{
// if our MMFeedbacks is in AutoPlayOnEnable mode, we add a little helper to it that will re-enable it if needed if the parent game object gets turned off and on again
if (AutoPlayOnEnable)
{
MMFeedbacksEnabler enabler = GetComponent<MMFeedbacksEnabler>();
if (enabler == null)
{
enabler = this.gameObject.AddComponent<MMFeedbacksEnabler>();
}
enabler.TargetMMFeedbacks = this;
}
if ((InitializationMode == InitializationModes.Awake) && (Application.isPlaying))
{
Initialization(this.gameObject);
}
CheckForLoops();
}
/// <summary>
/// On Start we initialize our feedbacks if we're in auto mode
/// </summary>
protected virtual void Start()
{
if ((InitializationMode == InitializationModes.Start) && (Application.isPlaying))
{
Initialization(this.gameObject);
}
if (AutoPlayOnStart && Application.isPlaying)
{
PlayFeedbacks();
}
CheckForLoops();
}
/// <summary>
/// On Enable we initialize our feedbacks if we're in auto mode
/// </summary>
protected virtual void OnEnable()
{
if (AutoPlayOnEnable && Application.isPlaying)
{
PlayFeedbacks();
}
}
/// <summary>
/// Initializes the MMFeedbacks, setting this MMFeedbacks as the owner
/// </summary>
public virtual void Initialization(bool forceInitIfPlaying = false)
{
Initialization(this.gameObject);
}
/// <summary>
/// A public method to initialize the feedback, specifying an owner that will be used as the reference for position and hierarchy by feedbacks
/// </summary>
/// <param name="owner"></param>
/// <param name="feedbacksOwner"></param>
public virtual void Initialization(GameObject owner)
{
if ((SafeMode == MMFeedbacks.SafeModes.RuntimeOnly) || (SafeMode == MMFeedbacks.SafeModes.Full))
{
AutoRepair();
}
IsPlaying = false;
TimesPlayed = 0;
_lastStartAt = -float.MaxValue;
for (int i = 0; i < Feedbacks.Count; i++)
{
if (Feedbacks[i] != null)
{
Feedbacks[i].Initialization(owner);
}
}
}
#endregion
#region PLAY
/// <summary>
/// Plays all feedbacks using the MMFeedbacks' position as reference, and no attenuation
/// </summary>
public virtual void PlayFeedbacks()
{
PlayFeedbacksInternal(this.transform.position, FeedbacksIntensity);
}
/// <summary>
/// Plays all feedbacks and awaits until completion
/// </summary>
/// <param name="position"></param>
/// <param name="feedbacksIntensity"></param>
/// <param name="forceRevert"></param>
public virtual async System.Threading.Tasks.Task PlayFeedbacksTask(Vector3 position, float feedbacksIntensity = 1.0f, bool forceRevert = false)
{
PlayFeedbacks(position, feedbacksIntensity, forceRevert);
while (IsPlaying)
{
await System.Threading.Tasks.Task.Yield();
}
}
/// <summary>
/// Plays all feedbacks and awaits until completion
/// </summary>
public virtual async System.Threading.Tasks.Task PlayFeedbacksTask()
{
PlayFeedbacks();
while (IsPlaying)
{
await System.Threading.Tasks.Task.Yield();
}
}
/// <summary>
/// Plays all feedbacks, specifying a position and intensity. The position may be used by each Feedback and taken into account to spark a particle or play a sound for example.
/// The feedbacks intensity is a factor that can be used by each Feedback to lower its intensity, usually you'll want to define that attenuation based on time or distance (using a lower
/// intensity value for feedbacks happening further away from the Player).
/// Additionally you can force the feedback to play in reverse, ignoring its current condition
/// </summary>
/// <param name="position"></param>
/// <param name="feedbacksOwner"></param>
/// <param name="feedbacksIntensity"></param>
public virtual void PlayFeedbacks(Vector3 position, float feedbacksIntensity = 1.0f, bool forceRevert = false)
{
PlayFeedbacksInternal(position, feedbacksIntensity, forceRevert);
}
/// <summary>
/// Plays all feedbacks using the MMFeedbacks' position as reference, and no attenuation, and in reverse (from bottom to top)
/// </summary>
public virtual void PlayFeedbacksInReverse()
{
PlayFeedbacksInternal(this.transform.position, FeedbacksIntensity, true);
}
/// <summary>
/// Plays all feedbacks using the MMFeedbacks' position as reference, and no attenuation, and in reverse (from bottom to top)
/// </summary>
public virtual void PlayFeedbacksInReverse(Vector3 position, float feedbacksIntensity = 1.0f, bool forceRevert = false)
{
PlayFeedbacksInternal(position, feedbacksIntensity, forceRevert);
}
/// <summary>
/// Plays all feedbacks in the sequence, but only if this MMFeedbacks is playing in reverse order
/// </summary>
public virtual void PlayFeedbacksOnlyIfReversed()
{
if ( (Direction == Directions.BottomToTop && !ShouldRevertOnNextPlay)
|| ((Direction == Directions.TopToBottom) && ShouldRevertOnNextPlay) )
{
PlayFeedbacks();
}
}
/// <summary>
/// Plays all feedbacks in the sequence, but only if this MMFeedbacks is playing in reverse order
/// </summary>
public virtual void PlayFeedbacksOnlyIfReversed(Vector3 position, float feedbacksIntensity = 1.0f, bool forceRevert = false)
{
if ( (Direction == Directions.BottomToTop && !ShouldRevertOnNextPlay)
|| ((Direction == Directions.TopToBottom) && ShouldRevertOnNextPlay) )
{
PlayFeedbacks(position, feedbacksIntensity, forceRevert);
}
}
/// <summary>
/// Plays all feedbacks in the sequence, but only if this MMFeedbacks is playing in normal order
/// </summary>
public virtual void PlayFeedbacksOnlyIfNormalDirection()
{
if (Direction == Directions.TopToBottom)
{
PlayFeedbacks();
}
}
/// <summary>
/// Plays all feedbacks in the sequence, but only if this MMFeedbacks is playing in normal order
/// </summary>
public virtual void PlayFeedbacksOnlyIfNormalDirection(Vector3 position, float feedbacksIntensity = 1.0f, bool forceRevert = false)
{
if (Direction == Directions.TopToBottom)
{
PlayFeedbacks(position, feedbacksIntensity, forceRevert);
}
}
/// <summary>
/// A public coroutine you can call externally when you want to yield in a coroutine of yours until the MMFeedbacks has stopped playing
/// typically : yield return myFeedback.PlayFeedbacksCoroutine(this.transform.position, 1.0f, false);
/// </summary>
/// <param name="position">The position at which the MMFeedbacks should play</param>
/// <param name="feedbacksIntensity">The intensity of the feedback</param>
/// <param name="forceRevert">Whether or not the MMFeedbacks should play in reverse or not</param>
/// <returns></returns>
public virtual IEnumerator PlayFeedbacksCoroutine(Vector3 position, float feedbacksIntensity = 1.0f, bool forceRevert = false)
{
PlayFeedbacks(position, feedbacksIntensity, forceRevert);
while (IsPlaying)
{
yield return null;
}
}
#endregion
#region SEQUENCE
/// <summary>
/// An internal method used to play feedbacks, shouldn't be called externally
/// </summary>
/// <param name="position"></param>
/// <param name="feedbacksIntensity"></param>
protected virtual void PlayFeedbacksInternal(Vector3 position, float feedbacksIntensity, bool forceRevert = false)
{
if (!CanPlay)
{
return;
}
if (IsPlaying && !CanPlayWhileAlreadyPlaying)
{
return;
}
if (!EvaluateChance())
{
return;
}
// if we have a cooldown we prevent execution if needed
if (CooldownDuration > 0f)
{
if (GetTime() - _lastStartAt < CooldownDuration)
{
return;
}
}
// if all MMFeedbacks are disabled globally, we stop and don't play
if (!GlobalMMFeedbacksActive)
{
return;
}
if (!this.gameObject.activeInHierarchy)
{
return;
}
if (ShouldRevertOnNextPlay)
{
Revert();
ShouldRevertOnNextPlay = false;
}
if (forceRevert)
{
Direction = (Direction == Directions.BottomToTop) ? Directions.TopToBottom : Directions.BottomToTop;
}
ResetFeedbacks();
this.enabled = true;
TimesPlayed++;
IsPlaying = true;
_startTime = GetTime();
_lastStartAt = _startTime;
_totalDuration = TotalDuration;
CheckForPauses();
if (ComputedInitialDelay > 0f)
{
StartCoroutine(HandleInitialDelayCo(position, feedbacksIntensity, forceRevert));
}
else
{
PreparePlay(position, feedbacksIntensity, forceRevert);
}
}
protected virtual void PreparePlay(Vector3 position, float feedbacksIntensity, bool forceRevert = false)
{
Events.TriggerOnPlay(this);
_holdingMax = 0f;
CheckForPauses();
if (!_pauseFound)
{
PlayAllFeedbacks(position, feedbacksIntensity, forceRevert);
}
else
{
// if at least one pause was found
StartCoroutine(PausedFeedbacksCo(position, feedbacksIntensity));
}
}
protected virtual void CheckForPauses()
{
_pauseFound = false;
for (int i = 0; i < Feedbacks.Count; i++)
{
if (Feedbacks[i] != null)
{
if ((Feedbacks[i].Pause != null) && (Feedbacks[i].Active) && (Feedbacks[i].ShouldPlayInThisSequenceDirection))
{
_pauseFound = true;
}
if ((Feedbacks[i].HoldingPause == true) && (Feedbacks[i].Active) && (Feedbacks[i].ShouldPlayInThisSequenceDirection))
{
_pauseFound = true;
}
}
}
}
protected virtual void PlayAllFeedbacks(Vector3 position, float feedbacksIntensity, bool forceRevert = false)
{
// if no pause was found, we just play all feedbacks at once
for (int i = 0; i < Feedbacks.Count; i++)
{
if (FeedbackCanPlay(Feedbacks[i]))
{
Feedbacks[i].Play(position, feedbacksIntensity);
}
}
}
protected virtual IEnumerator HandleInitialDelayCo(Vector3 position, float feedbacksIntensity, bool forceRevert = false)
{
IsPlaying = true;
yield return MMFeedbacksCoroutine.WaitFor(ComputedInitialDelay);
PreparePlay(position, feedbacksIntensity, forceRevert);
}
protected virtual void Update()
{
if (_shouldStop)
{
if (HasFeedbackStillPlaying())
{
return;
}
IsPlaying = false;
Events.TriggerOnComplete(this);
ApplyAutoRevert();
this.enabled = false;
_shouldStop = false;
}
if (IsPlaying)
{
if (!_pauseFound)
{
if (GetTime() - _startTime > _totalDuration)
{
_shouldStop = true;
}
}
}
else
{
this.enabled = false;
}
}
/// <summary>
/// Returns true if feedbacks are still playing
/// </summary>
/// <returns></returns>
public virtual bool HasFeedbackStillPlaying()
{
int count = Feedbacks.Count;
for (int i = 0; i < count; i++)
{
if ((Feedbacks[i] != null) && (Feedbacks[i].IsPlaying))
{
return true;
}
}
return false;
}
/// <summary>
/// A coroutine used to handle the sequence of feedbacks if pauses are involved
/// </summary>
/// <param name="position"></param>
/// <param name="feedbacksIntensity"></param>
/// <returns></returns>
protected virtual IEnumerator PausedFeedbacksCo(Vector3 position, float feedbacksIntensity)
{
yield return null;
}
#endregion
#region STOP
/// <summary>
/// Stops all further feedbacks from playing, without stopping individual feedbacks
/// </summary>
public virtual void StopFeedbacks()
{
StopFeedbacks(true);
}
/// <summary>
/// Stops all feedbacks from playing, with an option to also stop individual feedbacks
/// </summary>
public virtual void StopFeedbacks(bool stopAllFeedbacks = true)
{
StopFeedbacks(this.transform.position, 1.0f, stopAllFeedbacks);
}
/// <summary>
/// Stops all feedbacks from playing, specifying a position and intensity that can be used by the Feedbacks
/// </summary>
/// <param name="position"></param>
/// <param name="feedbacksIntensity"></param>
public virtual void StopFeedbacks(Vector3 position, float feedbacksIntensity = 1.0f, bool stopAllFeedbacks = true)
{
if (stopAllFeedbacks)
{
for (int i = 0; i < Feedbacks.Count; i++)
{
if (Feedbacks[i] != null)
{
Feedbacks[i].Stop(position, feedbacksIntensity);
}
}
}
IsPlaying = false;
StopAllCoroutines();
}
#endregion
#region CONTROLS
/// <summary>
/// Calls each feedback's Reset method if they've defined one. An example of that can be resetting the initial color of a flickering renderer.
/// </summary>
public virtual void ResetFeedbacks()
{
for (int i = 0; i < Feedbacks.Count; i++)
{
if ((Feedbacks[i] != null) && (Feedbacks[i].Active))
{
Feedbacks[i].ResetFeedback();
}
}
IsPlaying = false;
}
/// <summary>
/// Changes the direction of this MMFeedbacks
/// </summary>
public virtual void Revert()
{
Events.TriggerOnRevert(this);
Direction = (Direction == Directions.BottomToTop) ? Directions.TopToBottom : Directions.BottomToTop;
}
/// <summary>
/// Use this method to authorize or prevent this player from being played
/// </summary>
/// <param name="newState"></param>
public virtual void SetCanPlay(bool newState)
{
CanPlay = newState;
}
/// <summary>
/// Pauses execution of a sequence, which can then be resumed by calling ResumeFeedbacks()
/// </summary>
public virtual void PauseFeedbacks()
{
Events.TriggerOnPause(this);
InScriptDrivenPause = true;
}
/// <summary>
/// Resumes execution of a sequence if a script driven pause is in progress
/// </summary>
public virtual void ResumeFeedbacks()
{
Events.TriggerOnResume(this);
InScriptDrivenPause = false;
}
#endregion
#region MODIFICATION
public virtual MMFeedback AddFeedback(System.Type feedbackType, bool add = true)
{
MMFeedback newFeedback;
#if UNITY_EDITOR
if (!Application.isPlaying)
{
newFeedback = Undo.AddComponent(this.gameObject, feedbackType) as MMFeedback;
}
else
{
newFeedback = this.gameObject.AddComponent(feedbackType) as MMFeedback;
}
#else
newFeedback = this.gameObject.AddComponent(feedbackType) as MMFeedback;
#endif
newFeedback.hideFlags = HideFlags.HideInInspector;
newFeedback.Label = FeedbackPathAttribute.GetFeedbackDefaultName(feedbackType);
AutoRepair();
return newFeedback;
}
public virtual void RemoveFeedback(int id)
{
#if UNITY_EDITOR
if (!Application.isPlaying)
{
Undo.DestroyObjectImmediate(Feedbacks[id]);
}
else
{
DestroyImmediate(Feedbacks[id]);
}
#else
DestroyImmediate(Feedbacks[id]);
#endif
Feedbacks.RemoveAt(id);
AutoRepair();
}
#endregion MODIFICATION
#region HELPERS
/// <summary>
/// Evaluates the chance of this feedback to play, and returns true if this feedback can play, false otherwise
/// </summary>
/// <returns></returns>
protected virtual bool EvaluateChance()
{
if (ChanceToPlay == 0f)
{
return false;
}
if (ChanceToPlay != 100f)
{
// determine the odds
float random = Random.Range(0f, 100f);
if (random > ChanceToPlay)
{
return false;
}
}
return true;
}
/// <summary>
/// Checks whether or not this MMFeedbacks contains one or more looper feedbacks
/// </summary>
protected virtual void CheckForLoops()
{
ContainsLoop = false;
for (int i = 0; i < Feedbacks.Count; i++)
{
if (Feedbacks[i] != null)
{
if (Feedbacks[i].LooperPause && Feedbacks[i].Active)
{
ContainsLoop = true;
return;
}
}
}
}
/// <summary>
/// This will return true if the conditions defined in the specified feedback's Timing section allow it to play in the current play direction of this MMFeedbacks
/// </summary>
/// <param name="feedback"></param>
/// <returns></returns>
protected bool FeedbackCanPlay(MMFeedback feedback)
{
if (feedback == null)
{
return false;
}
if (feedback.Timing == null)
{
return false;
}
if (feedback.Timing.MMFeedbacksDirectionCondition == MMFeedbackTiming.MMFeedbacksDirectionConditions.Always)
{
return true;
}
else if (((Direction == Directions.TopToBottom) && (feedback.Timing.MMFeedbacksDirectionCondition == MMFeedbackTiming.MMFeedbacksDirectionConditions.OnlyWhenForwards))
|| ((Direction == Directions.BottomToTop) && (feedback.Timing.MMFeedbacksDirectionCondition == MMFeedbackTiming.MMFeedbacksDirectionConditions.OnlyWhenBackwards)))
{
return true;
}
return false;
}
/// <summary>
/// Readies the MMFeedbacks to revert direction on the next play
/// </summary>
protected virtual void ApplyAutoRevert()
{
if (AutoChangeDirectionOnEnd)
{
ShouldRevertOnNextPlay = true;
}
}
/// <summary>
/// Applies this feedback's time multiplier to a duration (in seconds)
/// </summary>
/// <param name="duration"></param>
/// <returns></returns>
public virtual float ApplyTimeMultiplier(float duration)
{
return duration * Mathf.Clamp(DurationMultiplier, _smallValue, Single.MaxValue);
}
/// <summary>
/// Unity sometimes has serialization issues.
/// This method fixes that by fixing any bad sync that could happen.
/// </summary>
public virtual void AutoRepair()
{
List<Component> components = components = new List<Component>();
components = this.gameObject.GetComponents<Component>().ToList();
foreach (Component component in components)
{
if (component is MMFeedback)
{
bool found = false;
for (int i = 0; i < Feedbacks.Count; i++)
{
if (Feedbacks[i] == (MMFeedback)component)
{
found = true;
break;
}
}
if (!found)
{
Feedbacks.Add((MMFeedback)component);
}
}
}
}
#endregion
#region EVENTS
/// <summary>
/// On Disable we stop all feedbacks
/// </summary>
protected virtual void OnDisable()
{
/*if (IsPlaying)
{
StopFeedbacks();
StopAllCoroutines();
}*/
}
/// <summary>
/// On validate, we make sure our DurationMultiplier remains positive
/// </summary>
protected virtual void OnValidate()
{
DurationMultiplier = Mathf.Clamp(DurationMultiplier, _smallValue, Single.MaxValue);
}
/// <summary>
/// On Destroy, removes all feedbacks from this MMFeedbacks to avoid any leftovers
/// </summary>
protected virtual void OnDestroy()
{
IsPlaying = false;
#if UNITY_EDITOR
if (!Application.isPlaying)
{
// we remove all binders
foreach (MMFeedback feedback in Feedbacks)
{
EditorApplication.delayCall += () =>
{
DestroyImmediate(feedback);
};
}
}
#endif
}
#endregion EVENTS
}
}

View File

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

View File

@@ -0,0 +1,28 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
namespace MoreMountains.Feedbacks
{
/// <summary>
/// A helper class added automatically by MMFeedbacks if they're in AutoPlayOnEnable mode
/// This lets them play again should their parent game object be disabled/enabled
/// </summary>
[AddComponentMenu("")]
public class MMFeedbacksEnabler : MonoBehaviour
{
/// the MMFeedbacks to pilot
public MMFeedbacks TargetMMFeedbacks { get; set; }
/// <summary>
/// On enable, we re-enable (and thus play) our MMFeedbacks if needed
/// </summary>
protected virtual void OnEnable()
{
if ((TargetMMFeedbacks != null) && !TargetMMFeedbacks.enabled && TargetMMFeedbacks.AutoPlayOnEnable)
{
TargetMMFeedbacks.enabled = true;
}
}
}
}

View File

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

View File

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

View File

@@ -0,0 +1,14 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!114 &11400000
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 0}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 09e29c2242d13d64480d58af86fcb50f, type: 3}
m_Name: ChannelA
m_EditorClassIdentifier:

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 6ba165fd91edb434aa2f1cd6f6b05885
NativeFormatImporter:
externalObjects: {}
mainObjectFileID: 11400000
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,14 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!114 &11400000
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 0}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 09e29c2242d13d64480d58af86fcb50f, type: 3}
m_Name: ChannelB
m_EditorClassIdentifier:

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 7471a7ccb4c5bdb4e9c9d5b51f6db888
NativeFormatImporter:
externalObjects: {}
mainObjectFileID: 11400000
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,14 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!114 &11400000
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 0}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 09e29c2242d13d64480d58af86fcb50f, type: 3}
m_Name: ChannelC
m_EditorClassIdentifier:

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 277be439bdc9329468f9e6d0799d54be
NativeFormatImporter:
externalObjects: {}
mainObjectFileID: 11400000
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,92 @@
using System;
using UnityEngine;
namespace MoreMountains.Feedbacks
{
/// <summary>
/// The possible modes used to identify a channel, either via an int or a MMChannel scriptable object
/// </summary>
public enum MMChannelModes
{
Int,
MMChannel
}
/// <summary>
/// A data structure used to pass channel information
/// </summary>
[Serializable]
public class MMChannelData
{
public MMChannelModes MMChannelMode;
public int Channel;
public MMChannel MMChannelDefinition;
public MMChannelData(MMChannelModes mode, int channel, MMChannel channelDefinition)
{
MMChannelMode = mode;
Channel = channel;
MMChannelDefinition = channelDefinition;
}
}
/// <summary>
/// Extensions class for MMChannelData
/// </summary>
public static class MMChannelDataExtensions
{
public static MMChannelData Set(this MMChannelData data, MMChannelModes mode, int channel, MMChannel channelDefinition)
{
data.MMChannelMode = mode;
data.Channel = channel;
data.MMChannelDefinition = channelDefinition;
return data;
}
}
/// <summary>
/// A scriptable object you can create assets from, to identify Channels, used mostly (but not only) in feedbacks and shakers,
/// to determine a channel of communication, usually between emitters and receivers
/// </summary>
[CreateAssetMenu(menuName = "MoreMountains/MMChannel", fileName = "MMChannel")]
public class MMChannel : ScriptableObject
{
public static bool Match(MMChannelData dataA, MMChannelData dataB)
{
if (dataA.MMChannelMode != dataB.MMChannelMode)
{
return false;
}
if (dataA.MMChannelMode == MMChannelModes.Int)
{
return dataA.Channel == dataB.Channel;
}
else
{
return dataA.MMChannelDefinition == dataB.MMChannelDefinition;
}
}
public static bool Match(MMChannelData dataA, MMChannelModes modeB, int channelB, MMChannel channelDefinitionB)
{
if (dataA == null)
{
return true;
}
if (dataA.MMChannelMode != modeB)
{
return false;
}
if (dataA.MMChannelMode == MMChannelModes.Int)
{
return dataA.Channel == channelB;
}
else
{
return dataA.MMChannelDefinition == channelDefinitionB;
}
}
}
}

View File

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

View File

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

File diff suppressed because it is too large Load Diff

View File

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

Some files were not shown because too many files have changed in this diff Show More