c1_unity/Assets/Editor/InspectorTools/EffectHelperInspector.cs
2023-04-03 11:04:31 +08:00

298 lines
8.5 KiB
C#

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;
using UnityEditor.Experimental.SceneManagement;
using BF;
using UnityEditor.SceneManagement;
namespace BFEditor
{
[InitializeOnLoad]
[CustomEditor(typeof(EffectHelper))]
public class EffectHelperInspector : Editor
{
EffectHelper helper;
private bool playing;
private float runningTime;
private float speed = 1.0f;
private const float millisecond = 1 / 60f;
private float maxDuration = 30f;
private bool isPause = false;
private bool isStop = true;
private ParticleSystem rootParticle;
static EffectHelperInspector()
{
PrefabStage.prefabSaving += OnPrefabSaved;
}
private static void OnPrefabSaved(GameObject go)
{
var effectHelper = go.GetComponent<EffectHelper>();
if (effectHelper != null)
{
updateEffectHelper(go, effectHelper);
}
}
private static void updateEffectHelper(GameObject go, EffectHelper effectHelper)
{
Transform t = effectHelper.transform;
float dur = getParticleSystemLength(t);
bool drity = false;
if (effectHelper.EffectDuration != dur)
{
effectHelper.EffectDuration = dur;
EditorUtility.SetDirty(effectHelper);
drity = true;
}
var animators = t.GetComponentsInChildren<Animator>(true);
int animatorCount = animators.Length;
if (effectHelper.AnimatorCount != animatorCount)
{
effectHelper.AnimatorCount = animatorCount;
EditorUtility.SetDirty(effectHelper);
drity = true;
}
var trailRenderers = t.GetComponentsInChildren<TrailRenderer>(true);
int trailRendererCount = trailRenderers.Length;
if (effectHelper.TrailRendererCount != trailRendererCount)
{
effectHelper.TrailRendererCount = trailRendererCount;
EditorUtility.SetDirty(effectHelper);
drity = true;
}
ParticleSystem rootP = t.GetComponentInChildren<ParticleSystem>(true);
if (rootP != null && effectHelper.RootParticle != rootP)
{
effectHelper.RootParticle = rootP;
EditorUtility.SetDirty(effectHelper);
drity = true;
}
if (drity)
{
var prefabStage = PrefabStageUtility.GetPrefabStage(go);
if (prefabStage != null)
{
EditorSceneManager.MarkSceneDirty(prefabStage.scene);
}
AssetDatabase.SaveAssets();
AssetDatabase.Refresh();
}
}
void OnEnable()
{
EditorApplication.update += inspectorUpdate;
helper = target as EffectHelper;
}
void OnDisable()
{
EditorApplication.update -= inspectorUpdate;
}
public override void OnInspectorGUI()
{
updateEffectHelper(helper.gameObject, helper);
Transform t = helper.gameObject.transform;
ParticleSystem rootP = t.GetComponentInChildren<ParticleSystem>(true);
if (!ReferenceEquals(rootP, helper.RootParticle))
{
helper.RootParticle = rootP;
}
this.rootParticle = helper.RootParticle;
maxDuration = getParticleSystemLength(t);
EditorGUILayout.BeginHorizontal();
if (isStop)
{
if (GUILayout.Button("Play"))
{
play();
}
}
else
{
if (isPause)
{
if (GUILayout.Button("Continue"))
{
continuePlay();
}
}
else
{
if (GUILayout.Button("Pause"))
{
pause();
}
}
}
if (GUILayout.Button("Stop"))
{
stop();
}
EditorGUILayout.EndHorizontal();
speed = EditorGUILayout.Slider("Speed:", speed, 1f, 0f);
showParticleInfo();
manualUpdate();
}
private void showParticleInfo()
{
GUILayout.Space(10);
GUILayout.BeginHorizontal();
GUILayout.Label("主粒子:", EditorStyles.label);
EditorGUI.BeginDisabledGroup(true);
if(helper.RootParticle == null)
{
GameObject go = (GameObject)EditorGUILayout.ObjectField("", null,
typeof(GameObject), true, GUILayout.Width(140));
}
else
{
GameObject go = (GameObject)EditorGUILayout.ObjectField("", helper.RootParticle.gameObject,
typeof(GameObject), true, GUILayout.Width(140));
}
EditorGUI.EndDisabledGroup();
GUILayout.EndHorizontal();
GUILayout.BeginHorizontal();
GUILayout.Label("粒子总持续时间: " + System.Convert.ToString(helper.EffectDuration) + "s", EditorStyles.label);
GUILayout.EndHorizontal();
GUILayout.BeginHorizontal();
GUILayout.Label("Animator数量: " + System.Convert.ToString(helper.AnimatorCount), EditorStyles.label);
GUILayout.EndHorizontal();
GUILayout.BeginHorizontal();
GUILayout.Label("拖尾数量: " + System.Convert.ToString(helper.TrailRendererCount), EditorStyles.label);
GUILayout.EndHorizontal();
GUILayout.BeginHorizontal();
var toggleResult = EditorGUILayout.Toggle("使用角度来翻转特效: ", helper.EulerAnglesFlip);
if (toggleResult != helper.EulerAnglesFlip)
{
Undo.RecordObject(helper, helper.name + "Toggle EulerAnglesFlip");
helper.EulerAnglesFlip = toggleResult;
EditorUtility.SetDirty(helper);
}
GUILayout.EndHorizontal();
}
private void manualUpdate()
{
if (this.rootParticle && !playing)
{
this.rootParticle.Simulate(millisecond * speed, true, false);
SceneView.RepaintAll();
}
}
private void play()
{
if (Application.isPlaying || this.rootParticle == null)
{
return;
}
playing = true;
isPause = false;
isStop = false;
this.rootParticle.Simulate(0, true, true);
}
private void continuePlay()
{
if (Application.isPlaying || this.rootParticle == null)
{
return;
}
playing = true;
isPause = false;
isStop = false;
}
private void stop()
{
if (Application.isPlaying || this.rootParticle == null)
{
return;
}
playing = false;
isPause = false;
isStop = true;
runningTime = 0;
this.rootParticle.Stop(true, ParticleSystemStopBehavior.StopEmittingAndClear);
}
private void pause()
{
if (Application.isPlaying || this.rootParticle == null)
{
return;
}
playing = false;
isPause = true;
this.rootParticle.Stop(true);
}
private void inspectorUpdate()
{
if (!Application.isPlaying && playing)
{
runningTime = runningTime + millisecond * speed;
update();
}
}
private void update()
{
if (Application.isPlaying || this.rootParticle == null)
{
return;
}
if (maxDuration > 0 && runningTime >= maxDuration)
{
this.stop();
return;
}
this.rootParticle.Simulate(millisecond * speed, true, false, true);
SceneView.RepaintAll();
Repaint();
}
private static float getParticleSystemLength(Transform transform)
{
ParticleSystem[] particleSystems = transform.GetComponentsInChildren<ParticleSystem>(true);
float maxDuration = -1;
foreach (ParticleSystem ps in particleSystems)
{
if (ps.emission.enabled)
{
if (ps.main.loop)
{
continue;
}
float dunration = ps.main.duration;
if (ps.main.startDelay.mode == ParticleSystemCurveMode.TwoConstants)
{
dunration += ps.main.startDelay.constantMax;
}
else
{
dunration += ps.main.startDelay.constant;
}
if (dunration > maxDuration)
{
maxDuration = dunration;
}
}
}
return maxDuration;
}
}
}