You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
878 lines
24 KiB
878 lines
24 KiB
//-------------------------------------------------------------------------------------------------------------------------------- |
|
// Cartoon FX |
|
// (c) 2012-2020 Jean Moreno |
|
//-------------------------------------------------------------------------------------------------------------------------------- |
|
|
|
|
|
//-------------------------------------------------------------------------------------------------------------------------------- |
|
|
|
// Use the defines below to globally disable features: |
|
|
|
//#define DISABLE_CAMERA_SHAKE |
|
//#define DISABLE_LIGHTS |
|
//#define DISABLE_CLEAR_BEHAVIOR |
|
|
|
//-------------------------------------------------------------------------------------------------------------------------------- |
|
|
|
using UnityEngine; |
|
#if UNITY_EDITOR |
|
using UnityEditor; |
|
#endif |
|
|
|
namespace CartoonFX |
|
{ |
|
[RequireComponent(typeof(ParticleSystem))] |
|
[DisallowMultipleComponent] |
|
public partial class CFXR_Effect : MonoBehaviour |
|
{ |
|
// Change this value to easily tune the camera shake strength for all effects |
|
const float GLOBAL_CAMERA_SHAKE_MULTIPLIER = 1.0f; |
|
|
|
#if UNITY_EDITOR |
|
[InitializeOnLoadMethod] |
|
static void InitGlobalOptions() |
|
{ |
|
AnimatedLight.editorPreview = EditorPrefs.GetBool("CFXR Light EditorPreview", true); |
|
#if !DISABLE_CAMERA_SHAKE |
|
CameraShake.editorPreview = EditorPrefs.GetBool("CFXR CameraShake EditorPreview", true); |
|
#endif |
|
} |
|
#endif |
|
|
|
public enum ClearBehavior |
|
{ |
|
None, |
|
Disable, |
|
Destroy |
|
} |
|
|
|
[System.Serializable] |
|
public class AnimatedLight |
|
{ |
|
static public bool editorPreview = true; |
|
|
|
public Light light; |
|
|
|
public bool loop; |
|
|
|
public bool animateIntensity; |
|
public float intensityStart = 8f; |
|
public float intensityEnd = 0f; |
|
public float intensityDuration = 0.5f; |
|
public AnimationCurve intensityCurve = AnimationCurve.EaseInOut(0f, 1f, 1f, 0f); |
|
public bool perlinIntensity; |
|
public float perlinIntensitySpeed = 1f; |
|
public bool fadeIn; |
|
public float fadeInDuration = 0.5f; |
|
public bool fadeOut; |
|
public float fadeOutDuration = 0.5f; |
|
|
|
public bool animateRange; |
|
public float rangeStart = 8f; |
|
public float rangeEnd = 0f; |
|
public float rangeDuration = 0.5f; |
|
public AnimationCurve rangeCurve = AnimationCurve.EaseInOut(0f, 1f, 1f, 0f); |
|
public bool perlinRange; |
|
public float perlinRangeSpeed = 1f; |
|
|
|
public bool animateColor; |
|
public Gradient colorGradient; |
|
public float colorDuration = 0.5f; |
|
public AnimationCurve colorCurve = AnimationCurve.EaseInOut(0f, 1f, 1f, 0f); |
|
public bool perlinColor; |
|
public float perlinColorSpeed = 1f; |
|
|
|
public void animate(float time) |
|
{ |
|
#if UNITY_EDITOR |
|
if (!editorPreview && !EditorApplication.isPlaying) |
|
{ |
|
return; |
|
} |
|
#endif |
|
|
|
if (light != null) |
|
{ |
|
if (animateIntensity) |
|
{ |
|
float delta = loop ? Mathf.Clamp01((time % intensityDuration)/intensityDuration) : Mathf.Clamp01(time/intensityDuration); |
|
delta = perlinIntensity ? Mathf.PerlinNoise(Time.time * perlinIntensitySpeed, 0f) : intensityCurve.Evaluate(delta); |
|
light.intensity = Mathf.LerpUnclamped(intensityEnd, intensityStart, delta); |
|
|
|
if (fadeIn && time < fadeInDuration) |
|
{ |
|
light.intensity *= Mathf.Clamp01(time / fadeInDuration); |
|
} |
|
} |
|
|
|
if (animateRange) |
|
{ |
|
float delta = loop ? Mathf.Clamp01((time % rangeDuration)/rangeDuration) : Mathf.Clamp01(time/rangeDuration); |
|
delta = perlinRange ? Mathf.PerlinNoise(Time.time * perlinRangeSpeed, 10f) : rangeCurve.Evaluate(delta); |
|
light.range = Mathf.LerpUnclamped(rangeEnd, rangeStart, delta); |
|
} |
|
|
|
if (animateColor) |
|
{ |
|
float delta = loop ? Mathf.Clamp01((time % colorDuration)/colorDuration) : Mathf.Clamp01(time/colorDuration); |
|
delta = perlinColor ? Mathf.PerlinNoise(Time.time * perlinColorSpeed, 0f) : colorCurve.Evaluate(delta); |
|
light.color = colorGradient.Evaluate(delta); |
|
} |
|
} |
|
} |
|
|
|
public void animateFadeOut(float time) |
|
{ |
|
if (fadeOut && light != null) |
|
{ |
|
light.intensity *= 1.0f - Mathf.Clamp01(time / fadeOutDuration); |
|
} |
|
} |
|
|
|
public void reset() |
|
{ |
|
if (light != null) |
|
{ |
|
if (animateIntensity) |
|
{ |
|
light.intensity = (fadeIn || fadeOut) ? 0 : intensityEnd; |
|
} |
|
|
|
if (animateRange) |
|
{ |
|
light.range = rangeEnd; |
|
} |
|
|
|
if (animateColor) |
|
{ |
|
light.color = colorGradient.Evaluate(1f); |
|
} |
|
} |
|
} |
|
|
|
#region Animated Light Property Drawer |
|
#if UNITY_EDITOR |
|
[CustomPropertyDrawer(typeof(AnimatedLight))] |
|
public class AnimatedLightDrawer : PropertyDrawer |
|
{ |
|
SerializedProperty light; |
|
|
|
SerializedProperty loop; |
|
|
|
SerializedProperty animateIntensity; |
|
SerializedProperty intensityStart; |
|
SerializedProperty intensityEnd; |
|
SerializedProperty intensityDuration; |
|
SerializedProperty intensityCurve; |
|
SerializedProperty perlinIntensity; |
|
SerializedProperty perlinIntensitySpeed; |
|
SerializedProperty fadeIn; |
|
SerializedProperty fadeInDuration; |
|
SerializedProperty fadeOut; |
|
SerializedProperty fadeOutDuration; |
|
|
|
SerializedProperty animateRange; |
|
SerializedProperty rangeStart; |
|
SerializedProperty rangeEnd; |
|
SerializedProperty rangeDuration; |
|
SerializedProperty rangeCurve; |
|
SerializedProperty perlinRange; |
|
SerializedProperty perlinRangeSpeed; |
|
|
|
SerializedProperty animateColor; |
|
SerializedProperty colorGradient; |
|
SerializedProperty colorDuration; |
|
SerializedProperty colorCurve; |
|
SerializedProperty perlinColor; |
|
SerializedProperty perlinColorSpeed; |
|
|
|
void fetchProperties(SerializedProperty property) |
|
{ |
|
light = property.FindPropertyRelative("light"); |
|
|
|
loop = property.FindPropertyRelative("loop"); |
|
|
|
animateIntensity = property.FindPropertyRelative("animateIntensity"); |
|
intensityStart = property.FindPropertyRelative("intensityStart"); |
|
intensityEnd = property.FindPropertyRelative("intensityEnd"); |
|
intensityDuration = property.FindPropertyRelative("intensityDuration"); |
|
intensityCurve = property.FindPropertyRelative("intensityCurve"); |
|
perlinIntensity = property.FindPropertyRelative("perlinIntensity"); |
|
perlinIntensitySpeed = property.FindPropertyRelative("perlinIntensitySpeed"); |
|
fadeIn = property.FindPropertyRelative("fadeIn"); |
|
fadeInDuration = property.FindPropertyRelative("fadeInDuration"); |
|
fadeOut = property.FindPropertyRelative("fadeOut"); |
|
fadeOutDuration = property.FindPropertyRelative("fadeOutDuration"); |
|
|
|
animateRange = property.FindPropertyRelative("animateRange"); |
|
rangeStart = property.FindPropertyRelative("rangeStart"); |
|
rangeEnd = property.FindPropertyRelative("rangeEnd"); |
|
rangeDuration = property.FindPropertyRelative("rangeDuration"); |
|
rangeCurve = property.FindPropertyRelative("rangeCurve"); |
|
perlinRange = property.FindPropertyRelative("perlinRange"); |
|
perlinRangeSpeed = property.FindPropertyRelative("perlinRangeSpeed"); |
|
|
|
animateColor = property.FindPropertyRelative("animateColor"); |
|
colorGradient = property.FindPropertyRelative("colorGradient"); |
|
colorDuration = property.FindPropertyRelative("colorDuration"); |
|
colorCurve = property.FindPropertyRelative("colorCurve"); |
|
perlinColor = property.FindPropertyRelative("perlinColor"); |
|
perlinColorSpeed = property.FindPropertyRelative("perlinColorSpeed"); |
|
} |
|
|
|
static GUIContent[] ModePopupLabels = new GUIContent[] { new GUIContent("Curve"), new GUIContent("Perlin Noise") }; |
|
static GUIContent IntensityModeLabel = new GUIContent("Intensity Mode"); |
|
static GUIContent RangeModeLabel = new GUIContent("Range Mode"); |
|
static GUIContent ColorModeLabel = new GUIContent("Color Mode"); |
|
|
|
const float INDENT_WIDTH = 15f; |
|
const float PADDING = 4f; |
|
|
|
void startIndent(ref Rect rect) |
|
{ |
|
EditorGUIUtility.labelWidth -= INDENT_WIDTH; |
|
rect.xMin += INDENT_WIDTH; |
|
} |
|
|
|
void endIndent(ref Rect rect) |
|
{ |
|
EditorGUIUtility.labelWidth += INDENT_WIDTH; |
|
rect.xMin -= INDENT_WIDTH; |
|
} |
|
|
|
public override void OnGUI(Rect position, SerializedProperty property, GUIContent label) |
|
{ |
|
fetchProperties(property); |
|
|
|
Rect rect = EditorGUI.IndentedRect(position); |
|
|
|
//Rect lineRect = rect; |
|
//lineRect.height = 1; |
|
//lineRect.y -= 2; |
|
//EditorGUI.DrawRect(lineRect, Color.gray); |
|
|
|
if (Event.current.type == EventType.Repaint) |
|
{ |
|
EditorStyles.helpBox.Draw(rect, GUIContent.none, 0); |
|
} |
|
|
|
EditorGUIUtility.labelWidth -= INDENT_WIDTH; |
|
|
|
rect.height = EditorGUIUtility.singleLineHeight; |
|
rect.xMax -= PADDING; |
|
rect.y += PADDING; |
|
float propSpace = EditorGUIUtility.singleLineHeight + EditorGUIUtility.standardVerticalSpacing; |
|
|
|
EditorGUI.PropertyField(rect, light); rect.y += propSpace; |
|
EditorGUI.PropertyField(rect, loop); rect.y += propSpace; |
|
|
|
EditorGUI.PropertyField(rect, animateIntensity); rect.y += propSpace; |
|
if (animateIntensity.boolValue) |
|
{ |
|
startIndent(ref rect); |
|
{ |
|
|
|
EditorGUI.PropertyField(rect, intensityStart); rect.y += propSpace; |
|
EditorGUI.PropertyField(rect, intensityEnd); rect.y += propSpace; |
|
|
|
int val = EditorGUI.Popup(rect, IntensityModeLabel, perlinIntensity.boolValue ? 1 : 0, ModePopupLabels); rect.y += propSpace; |
|
if (val == 1 && !perlinIntensity.boolValue) |
|
{ |
|
perlinIntensity.boolValue = true; |
|
} |
|
else if (val == 0 && perlinIntensity.boolValue) |
|
{ |
|
perlinIntensity.boolValue = false; |
|
} |
|
|
|
startIndent(ref rect); |
|
{ |
|
if (perlinIntensity.boolValue) |
|
{ |
|
EditorGUI.PropertyField(rect, perlinIntensitySpeed); rect.y += propSpace; |
|
} |
|
else |
|
{ |
|
EditorGUI.PropertyField(rect, intensityDuration); rect.y += propSpace; |
|
EditorGUI.PropertyField(rect, intensityCurve); rect.y += propSpace; |
|
} |
|
} |
|
endIndent(ref rect); |
|
|
|
EditorGUI.PropertyField(rect, fadeIn); rect.y += propSpace; |
|
if (fadeIn.boolValue) |
|
{ |
|
startIndent(ref rect); |
|
EditorGUI.PropertyField(rect, fadeInDuration); rect.y += propSpace; |
|
endIndent(ref rect); |
|
} |
|
|
|
EditorGUI.PropertyField(rect, fadeOut); rect.y += propSpace; |
|
if (fadeOut.boolValue) |
|
{ |
|
startIndent(ref rect); |
|
EditorGUI.PropertyField(rect, fadeOutDuration); rect.y += propSpace; |
|
endIndent(ref rect); |
|
} |
|
|
|
} |
|
endIndent(ref rect); |
|
} |
|
|
|
EditorGUI.PropertyField(rect, animateRange); rect.y += propSpace; |
|
if (animateRange.boolValue) |
|
{ |
|
startIndent(ref rect); |
|
{ |
|
EditorGUI.PropertyField(rect, rangeStart); rect.y += propSpace; |
|
EditorGUI.PropertyField(rect, rangeEnd); rect.y += propSpace; |
|
|
|
int val = EditorGUI.Popup(rect, RangeModeLabel, perlinRange.boolValue ? 1 : 0, ModePopupLabels); rect.y += propSpace; |
|
if (val == 1 && !perlinRange.boolValue) |
|
{ |
|
perlinRange.boolValue = true; |
|
} |
|
else if (val == 0 && perlinRange.boolValue) |
|
{ |
|
perlinRange.boolValue = false; |
|
} |
|
|
|
startIndent(ref rect); |
|
{ |
|
if (perlinRange.boolValue) |
|
{ |
|
EditorGUI.PropertyField(rect, perlinRangeSpeed); rect.y += propSpace; |
|
} |
|
else |
|
{ |
|
EditorGUI.PropertyField(rect, rangeDuration); rect.y += propSpace; |
|
EditorGUI.PropertyField(rect, rangeCurve); rect.y += propSpace; |
|
} |
|
} |
|
endIndent(ref rect); |
|
} |
|
endIndent(ref rect); |
|
} |
|
|
|
EditorGUI.PropertyField(rect, animateColor); rect.y += propSpace; |
|
if (animateColor.boolValue) |
|
{ |
|
startIndent(ref rect); |
|
{ |
|
|
|
EditorGUI.PropertyField(rect, colorGradient); rect.y += propSpace; |
|
|
|
int val = EditorGUI.Popup(rect, ColorModeLabel, perlinColor.boolValue ? 1 : 0, ModePopupLabels); rect.y += propSpace; |
|
if (val == 1 && !perlinColor.boolValue) |
|
{ |
|
perlinColor.boolValue = true; |
|
} |
|
else if (val == 0 && perlinColor.boolValue) |
|
{ |
|
perlinColor.boolValue = false; |
|
} |
|
|
|
startIndent(ref rect); |
|
{ |
|
|
|
if (perlinColor.boolValue) |
|
{ |
|
EditorGUI.PropertyField(rect, perlinColorSpeed); rect.y += propSpace; |
|
} |
|
else |
|
{ |
|
EditorGUI.PropertyField(rect, colorDuration); rect.y += propSpace; |
|
EditorGUI.PropertyField(rect, colorCurve); rect.y += propSpace; |
|
} |
|
} |
|
endIndent(ref rect); |
|
} |
|
endIndent(ref rect); |
|
} |
|
|
|
EditorGUIUtility.labelWidth += INDENT_WIDTH; |
|
|
|
if (GUI.changed) |
|
{ |
|
property.serializedObject.ApplyModifiedProperties(); |
|
} |
|
} |
|
|
|
public override float GetPropertyHeight(SerializedProperty property, GUIContent label) |
|
{ |
|
fetchProperties(property); |
|
|
|
float propSpace = EditorGUIUtility.singleLineHeight + EditorGUIUtility.standardVerticalSpacing; |
|
int count = 5; |
|
|
|
if (animateIntensity.boolValue) |
|
{ |
|
count += 3; |
|
count += perlinIntensity.boolValue ? 1 : 2; |
|
count += 1; |
|
count += fadeIn.boolValue ? 1 : 0; |
|
count += 1; |
|
count += fadeOut.boolValue ? 1 : 0; |
|
} |
|
|
|
if (animateRange.boolValue) |
|
{ |
|
count += 3; |
|
count += perlinRange.boolValue ? 1 : 2; |
|
} |
|
|
|
if (animateColor.boolValue) |
|
{ |
|
count += 2; |
|
count += perlinColor.boolValue ? 1 : 2; |
|
} |
|
|
|
return count * propSpace + PADDING * 2; |
|
} |
|
} |
|
#endif |
|
#endregion |
|
|
|
} |
|
|
|
// ================================================================================================================================ |
|
|
|
// Globally disable features |
|
public static bool GlobalDisableCameraShake; |
|
public static bool GlobalDisableLights; |
|
|
|
// ================================================================================================================================ |
|
|
|
[Tooltip("Defines an action to execute when the Particle System has completely finished playing and emitting particles.")] |
|
public ClearBehavior clearBehavior = ClearBehavior.Destroy; |
|
[Space] |
|
public CameraShake cameraShake; |
|
[Space] |
|
public AnimatedLight[] animatedLights; |
|
[Tooltip("Defines which Particle System to track to trigger light fading out.\nLeave empty if not using fading out.")] |
|
public ParticleSystem fadeOutReference; |
|
|
|
float time; |
|
ParticleSystem rootParticleSystem; |
|
[System.NonSerialized] MaterialPropertyBlock materialPropertyBlock; |
|
[System.NonSerialized] Renderer particleRenderer; |
|
|
|
// ================================================================================================================================ |
|
|
|
public void ResetState() |
|
{ |
|
time = 0f; |
|
fadingOutStartTime = 0f; |
|
isFadingOut = false; |
|
|
|
#if !DISABLE_LIGHTS |
|
if (animatedLights != null) |
|
{ |
|
foreach (var animLight in animatedLights) |
|
{ |
|
animLight.reset(); |
|
} |
|
} |
|
#endif |
|
|
|
#if !DISABLE_CAMERA_SHAKE |
|
if (cameraShake != null && cameraShake.enabled) |
|
{ |
|
cameraShake.StopShake(); |
|
} |
|
#endif |
|
} |
|
|
|
#if !DISABLE_CAMERA_SHAKE || !DISABLE_CLEAR_BEHAVIOR |
|
void Awake() |
|
{ |
|
#if !DISABLE_CAMERA_SHAKE |
|
if (cameraShake != null && cameraShake.enabled) |
|
{ |
|
cameraShake.fetchCameras(); |
|
} |
|
#endif |
|
#if !DISABLE_CLEAR_BEHAVIOR |
|
startFrameOffset = GlobalStartFrameOffset++; |
|
#endif |
|
// Detect if world position needs to be passed to the shader |
|
particleRenderer = this.GetComponent<ParticleSystemRenderer>(); |
|
if (particleRenderer.sharedMaterial != null && particleRenderer.sharedMaterial.IsKeywordEnabled("_CFXR_LIGHTING_WPOS_OFFSET")) |
|
{ |
|
materialPropertyBlock = new MaterialPropertyBlock(); |
|
} |
|
} |
|
#endif |
|
|
|
void OnEnable() |
|
{ |
|
foreach (var animLight in animatedLights) |
|
{ |
|
if (animLight.light != null) |
|
{ |
|
#if !DISABLE_LIGHTS |
|
animLight.light.enabled = !GlobalDisableLights; |
|
#else |
|
animLight.light.enabled = false; |
|
#endif |
|
} |
|
} |
|
} |
|
|
|
void OnDisable() |
|
{ |
|
ResetState(); |
|
} |
|
|
|
#if !DISABLE_LIGHTS || !DISABLE_CAMERA_SHAKE || !DISABLE_CLEAR_BEHAVIOR |
|
const int CHECK_EVERY_N_FRAME = 20; |
|
static int GlobalStartFrameOffset = 0; |
|
int startFrameOffset; |
|
void Update() |
|
{ |
|
#if !DISABLE_LIGHTS || !DISABLE_CAMERA_SHAKE |
|
time += Time.deltaTime; |
|
|
|
Animate(time); |
|
|
|
if (fadeOutReference != null && !fadeOutReference.isEmitting && (fadeOutReference.isPlaying || isFadingOut)) |
|
{ |
|
FadeOut(time); |
|
} |
|
#endif |
|
#if !DISABLE_CLEAR_BEHAVIOR |
|
if (clearBehavior != ClearBehavior.None) |
|
{ |
|
if (rootParticleSystem == null) |
|
{ |
|
rootParticleSystem = this.GetComponent<ParticleSystem>(); |
|
} |
|
|
|
// Check isAlive every N frame, with an offset so that all active effects aren't checked at once |
|
if ((Time.renderedFrameCount + startFrameOffset) % CHECK_EVERY_N_FRAME == 0) |
|
{ |
|
if (!rootParticleSystem.IsAlive(true)) |
|
{ |
|
if (clearBehavior == ClearBehavior.Destroy) |
|
{ |
|
GameObject.Destroy(this.gameObject); |
|
} |
|
else |
|
{ |
|
this.gameObject.SetActive(false); |
|
} |
|
} |
|
} |
|
} |
|
#endif |
|
if (materialPropertyBlock != null) |
|
{ |
|
particleRenderer.GetPropertyBlock(materialPropertyBlock); |
|
materialPropertyBlock.SetVector("_GameObjectWorldPosition", this.transform.position); |
|
particleRenderer.SetPropertyBlock(materialPropertyBlock); |
|
} |
|
} |
|
#endif |
|
|
|
#if !DISABLE_LIGHTS || !DISABLE_CAMERA_SHAKE |
|
public void Animate(float time) |
|
{ |
|
#if !DISABLE_LIGHTS |
|
if (animatedLights != null && !GlobalDisableLights) |
|
{ |
|
foreach (var animLight in animatedLights) |
|
{ |
|
animLight.animate(time); |
|
} |
|
} |
|
#endif |
|
|
|
#if !DISABLE_CAMERA_SHAKE |
|
if (cameraShake != null && cameraShake.enabled && !GlobalDisableCameraShake) |
|
{ |
|
#if UNITY_EDITOR |
|
if (!cameraShake.isShaking) |
|
{ |
|
cameraShake.fetchCameras(); |
|
} |
|
#endif |
|
cameraShake.animate(time); |
|
} |
|
#endif |
|
} |
|
#endif |
|
|
|
#if !DISABLE_LIGHTS |
|
bool isFadingOut; |
|
float fadingOutStartTime; |
|
public void FadeOut(float time) |
|
{ |
|
if (animatedLights == null) |
|
{ |
|
return; |
|
} |
|
|
|
if (!isFadingOut) |
|
{ |
|
isFadingOut = true; |
|
fadingOutStartTime = time; |
|
} |
|
|
|
foreach (var animLight in animatedLights) |
|
{ |
|
animLight.animateFadeOut(time - fadingOutStartTime); |
|
} |
|
} |
|
#endif |
|
|
|
#if UNITY_EDITOR |
|
// Editor preview |
|
// Detect when the Particle System is previewing and trigger this animation too |
|
|
|
[System.NonSerialized] ParticleSystem _parentParticle; |
|
ParticleSystem parentParticle |
|
{ |
|
get |
|
{ |
|
if (_parentParticle == null) |
|
{ |
|
_parentParticle = this.GetComponent<ParticleSystem>(); |
|
} |
|
return _parentParticle; |
|
} |
|
} |
|
[System.NonSerialized] public bool editorUpdateRegistered; |
|
|
|
[System.NonSerialized] bool particleWasStopped; |
|
[System.NonSerialized] float particleTime; |
|
[System.NonSerialized] float particleTimeUnwrapped; |
|
|
|
void OnDestroy() |
|
{ |
|
UnregisterEditorUpdate(); |
|
} |
|
|
|
public void RegisterEditorUpdate() |
|
{ |
|
var type = PrefabUtility.GetPrefabAssetType(this.gameObject); |
|
var status = PrefabUtility.GetPrefabInstanceStatus(this.gameObject); |
|
|
|
// Prefab in Project window |
|
if ((type == PrefabAssetType.Regular || type == PrefabAssetType.Variant) && status == PrefabInstanceStatus.NotAPrefab) |
|
{ |
|
return; |
|
} |
|
|
|
if (!editorUpdateRegistered) |
|
{ |
|
EditorApplication.update += onEditorUpdate; |
|
editorUpdateRegistered = true; |
|
} |
|
} |
|
|
|
public void UnregisterEditorUpdate() |
|
{ |
|
if (editorUpdateRegistered) |
|
{ |
|
editorUpdateRegistered = false; |
|
EditorApplication.update -= onEditorUpdate; |
|
} |
|
ResetState(); |
|
} |
|
|
|
void onEditorUpdate() |
|
{ |
|
if (EditorApplication.isPlayingOrWillChangePlaymode) |
|
{ |
|
return; |
|
} |
|
|
|
if (this == null) |
|
{ |
|
return; |
|
} |
|
|
|
var renderer = this.GetComponent<ParticleSystemRenderer>(); |
|
if (renderer.sharedMaterial != null && renderer.sharedMaterial.IsKeywordEnabled("_CFXR_LIGHTING_WPOS_OFFSET")) |
|
{ |
|
if (materialPropertyBlock == null) |
|
{ |
|
materialPropertyBlock = new MaterialPropertyBlock(); |
|
} |
|
|
|
renderer.GetPropertyBlock(materialPropertyBlock); |
|
materialPropertyBlock.SetVector("_GameObjectWorldPosition", this.transform.position); |
|
renderer.SetPropertyBlock(materialPropertyBlock); |
|
} |
|
|
|
// Need to track unwrapped time when playing back from Editor |
|
// because the parentParticle.time will be reset at each loop |
|
float delta = parentParticle.time - particleTime; |
|
|
|
if (delta < 0 && parentParticle.isPlaying) |
|
{ |
|
delta = parentParticle.main.duration + delta; |
|
if (delta > 0.1 || delta < 0) |
|
{ |
|
// try to detect when "Restart" is pressed |
|
ResetState(); |
|
particleTimeUnwrapped = 0; |
|
delta = 0; |
|
} |
|
} |
|
particleTimeUnwrapped += delta; |
|
|
|
if (particleTime != parentParticle.time) |
|
{ |
|
#if !DISABLE_CAMERA_SHAKE |
|
if (cameraShake != null && cameraShake.enabled && parentParticle.time < particleTime && parentParticle.time < 0.05f) |
|
{ |
|
cameraShake.StartShake(); |
|
} |
|
#endif |
|
#if !DISABLE_LIGHTS || !DISABLE_CAMERA_SHAKES |
|
Animate(particleTimeUnwrapped); |
|
|
|
if (!parentParticle.isEmitting) |
|
{ |
|
FadeOut(particleTimeUnwrapped); |
|
} |
|
#endif |
|
} |
|
|
|
if (particleWasStopped != parentParticle.isStopped) |
|
{ |
|
if (parentParticle.isStopped) |
|
{ |
|
ResetState(); |
|
} |
|
particleTimeUnwrapped = 0; |
|
} |
|
|
|
particleWasStopped = parentParticle.isStopped; |
|
particleTime = parentParticle.time; |
|
} |
|
#endif |
|
} |
|
|
|
#if UNITY_EDITOR |
|
[CustomEditor(typeof(CFXR_Effect))] |
|
[CanEditMultipleObjects] |
|
public class CFXR_Effect_Editor : Editor |
|
{ |
|
bool? lightEditorPreview; |
|
bool? shakeEditorPreview; |
|
|
|
GUIStyle _PaddedRoundedRect; |
|
GUIStyle PaddedRoundedRect |
|
{ |
|
get |
|
{ |
|
if (_PaddedRoundedRect == null) |
|
{ |
|
_PaddedRoundedRect = new GUIStyle(EditorStyles.helpBox); |
|
_PaddedRoundedRect.padding = new RectOffset(4, 4, 4, 4); |
|
} |
|
return _PaddedRoundedRect; |
|
} |
|
} |
|
|
|
public override void OnInspectorGUI() |
|
{ |
|
GlobalOptionsGUI(); |
|
|
|
#if DISABLE_CAMERA_SHAKE |
|
EditorGUILayout.HelpBox("Camera Shake has been globally disabled in the code.\nThe properties remain to avoid data loss but the shaking won't be applied for any effect.", MessageType.Info); |
|
#endif |
|
|
|
base.OnInspectorGUI(); |
|
} |
|
|
|
void GlobalOptionsGUI() |
|
{ |
|
EditorGUILayout.BeginVertical(PaddedRoundedRect); |
|
{ |
|
GUILayout.Label("Editor Preview:", EditorStyles.boldLabel); |
|
|
|
if (lightEditorPreview == null) |
|
{ |
|
lightEditorPreview = EditorPrefs.GetBool("CFXR Light EditorPreview", true); |
|
} |
|
bool lightPreview = EditorGUILayout.Toggle("Light Animations", lightEditorPreview.Value); |
|
if (lightPreview != lightEditorPreview.Value) |
|
{ |
|
lightEditorPreview = lightPreview; |
|
EditorPrefs.SetBool("CFXR Light EditorPreview", lightPreview); |
|
CFXR_Effect.AnimatedLight.editorPreview = lightPreview; |
|
} |
|
|
|
#if !DISABLE_CAMERA_SHAKE |
|
if (shakeEditorPreview == null) |
|
{ |
|
shakeEditorPreview = EditorPrefs.GetBool("CFXR CameraShake EditorPreview", true); |
|
} |
|
bool shakePreview = EditorGUILayout.Toggle("Camera Shake", shakeEditorPreview.Value); |
|
if (shakePreview != shakeEditorPreview.Value) |
|
{ |
|
shakeEditorPreview = shakePreview; |
|
EditorPrefs.SetBool("CFXR CameraShake EditorPreview", shakePreview); |
|
CFXR_Effect.CameraShake.editorPreview = shakePreview; |
|
} |
|
#endif |
|
} |
|
EditorGUILayout.EndVertical(); |
|
} |
|
|
|
void OnEnable() |
|
{ |
|
if (this.targets == null) |
|
{ |
|
return; |
|
} |
|
|
|
foreach (var t in this.targets) |
|
{ |
|
var cfxr_effect = t as CFXR_Effect; |
|
if (cfxr_effect != null) |
|
{ |
|
if (isPrefabSource(cfxr_effect.gameObject)) |
|
{ |
|
return; |
|
} |
|
cfxr_effect.RegisterEditorUpdate(); |
|
} |
|
} |
|
} |
|
|
|
void OnDisable() |
|
{ |
|
if (this.targets == null) |
|
{ |
|
return; |
|
} |
|
|
|
foreach (var t in this.targets) |
|
{ |
|
// Can be null if GameObject has been destroyed |
|
var cfxr_effect = t as CFXR_Effect; |
|
if (cfxr_effect != null) |
|
{ |
|
if (isPrefabSource(cfxr_effect.gameObject)) |
|
{ |
|
return; |
|
} |
|
cfxr_effect.UnregisterEditorUpdate(); |
|
} |
|
} |
|
} |
|
|
|
static bool isPrefabSource(GameObject gameObject) |
|
{ |
|
var assetType = PrefabUtility.GetPrefabAssetType(gameObject); |
|
var prefabType = PrefabUtility.GetPrefabInstanceStatus(gameObject); |
|
return ((assetType == PrefabAssetType.Regular || assetType == PrefabAssetType.Variant) && prefabType == PrefabInstanceStatus.NotAPrefab); |
|
} |
|
} |
|
#endif |
|
} |
|
; |