|
|
using UnityEngine; |
|
|
using UnityEditor; |
|
|
using System.Collections.Generic; |
|
|
|
|
|
// Cartoon FX Easy Editor |
|
|
// (c) 2013-2020 - Jean Moreno |
|
|
|
|
|
public class CFXEasyEditor : EditorWindow |
|
|
{ |
|
|
static private CFXEasyEditor SingleWindow; |
|
|
|
|
|
[MenuItem("Tools/Cartoon FX Easy Editor")] |
|
|
static void ShowWindow() |
|
|
{ |
|
|
CFXEasyEditor window = EditorWindow.GetWindow<CFXEasyEditor>(EditorPrefs.GetBool("CFX_ShowAsToolbox", true), "Easy Editor", true); |
|
|
window.minSize = new Vector2(300, 8); |
|
|
window.maxSize = new Vector2(300, 8); |
|
|
} |
|
|
|
|
|
private int SelectedParticleSystemsCount; |
|
|
|
|
|
//Change Start Color |
|
|
private bool AffectAlpha = true; |
|
|
private Color ColorValue = Color.white; |
|
|
private Color ColorValue2 = Color.white; |
|
|
|
|
|
//Scale |
|
|
private float ScalingValue = 2.0f; |
|
|
private float LTScalingValue = 1.0f; |
|
|
|
|
|
//Delay |
|
|
private float DelayValue = 1.0f; |
|
|
|
|
|
//Duration |
|
|
private float DurationValue = 5.0f; |
|
|
|
|
|
//Tint |
|
|
private bool TintStartColor = true; |
|
|
private bool TintColorModule = true; |
|
|
private bool TintColorSpeedModule = true; |
|
|
private bool TintTrailsModule = true; |
|
|
private bool TintCustomData1 = true; |
|
|
private bool TintCustomData2 = true; |
|
|
private bool TintLights = true; |
|
|
private Color TintColorValue = Color.white; |
|
|
private float TintHueShiftValue = 0f; |
|
|
private float SatShiftValue = 0f; |
|
|
private float ValShiftValue = 0f; |
|
|
|
|
|
//Change Lightness |
|
|
private int LightnessStep = 10; |
|
|
|
|
|
//Module copying system |
|
|
private ParticleSystem copyModulesSourceParticleSystem; |
|
|
|
|
|
private class ParticleSystemModule |
|
|
{ |
|
|
public string name; |
|
|
//public bool selected; |
|
|
//public bool enabledInSource; |
|
|
public string serializedPropertyPath; |
|
|
|
|
|
public ParticleSystemModule(string name, string serializedPropertyPath) |
|
|
{ |
|
|
this.name = " " + name + " "; |
|
|
this.serializedPropertyPath = serializedPropertyPath; |
|
|
} |
|
|
|
|
|
public bool CheckIfEnabledInSource(SerializedObject serializedSource) |
|
|
{ |
|
|
bool enabled = true; |
|
|
var sp = serializedSource.FindProperty(this.serializedPropertyPath); |
|
|
if(sp != null) |
|
|
{ |
|
|
var enabledSp = sp.FindPropertyRelative("enabled"); |
|
|
if(enabledSp != null) |
|
|
{ |
|
|
enabled = enabledSp.boolValue; |
|
|
} |
|
|
} |
|
|
return enabled; |
|
|
} |
|
|
} |
|
|
|
|
|
private ParticleSystemModule[] modulesToCopy = null; |
|
|
private List<string> initialModuleExtraProperties = null; |
|
|
private GUIContent[] modulesLabels = null; |
|
|
|
|
|
private ParticleSystem selectedParticleSystem; |
|
|
private bool[] selectedModules; |
|
|
private bool[] enabledModules; |
|
|
/* |
|
|
private bool[] selectedModulesMutate; |
|
|
private bool[] enabledModulesMutate; |
|
|
|
|
|
private float mutatePercentage = 0.1f; |
|
|
*/ |
|
|
|
|
|
//Foldouts |
|
|
bool basicFoldout = false; |
|
|
bool colorFoldout = false; |
|
|
bool copyFoldout = false; |
|
|
//bool mutateFoldout = false; |
|
|
|
|
|
//Editor Prefs |
|
|
private bool pref_ShowAsToolbox; |
|
|
private bool pref_IncludeChildren; |
|
|
private bool pref_HideDisabledModulesCopy; |
|
|
|
|
|
void OnEnable() |
|
|
{ |
|
|
//Load Settings |
|
|
pref_ShowAsToolbox = EditorPrefs.GetBool("CFX_ShowAsToolbox", true); |
|
|
pref_IncludeChildren = EditorPrefs.GetBool("CFX_IncludeChildren", true); |
|
|
pref_HideDisabledModulesCopy = EditorPrefs.GetBool("CFX_HideDisabledModulesCopy", true); |
|
|
basicFoldout = EditorPrefs.GetBool("CFX_BasicFoldout", false); |
|
|
colorFoldout = EditorPrefs.GetBool("CFX_ColorFoldout", false); |
|
|
copyFoldout = EditorPrefs.GetBool("CFX_CopyFoldout", false); |
|
|
//mutateFoldout = EditorPrefs.GetBool("CFX_MutateFoldout", false); |
|
|
|
|
|
ParticleSystem ps = null; |
|
|
if (Selection.activeGameObject != null) |
|
|
{ |
|
|
ps = Selection.activeGameObject.GetComponent<ParticleSystem>(); |
|
|
} |
|
|
if (ps == null && copyModulesSourceParticleSystem != null) |
|
|
{ |
|
|
ps = copyModulesSourceParticleSystem.GetComponent<ParticleSystem>(); |
|
|
} |
|
|
FetchParticleSystemModules(ps); |
|
|
//RefreshCurrentlyEnabledModules(ps, ref enabledModulesMutate); |
|
|
|
|
|
OnSelectionChange(); |
|
|
} |
|
|
|
|
|
void OnSelectionChange() |
|
|
{ |
|
|
UpdateSelectionCount(); |
|
|
this.Repaint(); |
|
|
|
|
|
if (Selection.activeGameObject != null) |
|
|
{ |
|
|
selectedParticleSystem = Selection.activeGameObject.GetComponent<ParticleSystem>(); |
|
|
FetchParticleSystemModules(selectedParticleSystem); |
|
|
} |
|
|
} |
|
|
|
|
|
void FetchParticleSystemModules(ParticleSystem ps) |
|
|
{ |
|
|
// Fetch the modules list from a Particle System |
|
|
if (modulesToCopy == null && ps != null) |
|
|
{ |
|
|
initialModuleExtraProperties = new List<string>(); |
|
|
var modulesList = new List<ParticleSystemModule>(); |
|
|
var modulesLabelsList = new List<GUIContent>(); |
|
|
var so = new SerializedObject(ps); |
|
|
var sp = so.GetIterator(); |
|
|
sp.Next(true); |
|
|
while (sp.NextVisible(false)) |
|
|
{ |
|
|
if (sp.propertyPath.EndsWith("Module")) |
|
|
{ |
|
|
var module = new ParticleSystemModule(sp.propertyPath.Replace("Module", ""), sp.propertyPath); |
|
|
modulesList.Add(module); |
|
|
modulesLabelsList.Add(new GUIContent(sp.propertyPath.Replace("Module", ""))); |
|
|
} |
|
|
else |
|
|
{ |
|
|
initialModuleExtraProperties.Add(sp.propertyPath); |
|
|
} |
|
|
} |
|
|
modulesToCopy = modulesList.ToArray(); |
|
|
|
|
|
// add one entry for renderer (not a module but a component) |
|
|
modulesLabelsList.Add(new GUIContent("Renderer")); |
|
|
modulesLabels = modulesLabelsList.ToArray(); |
|
|
} |
|
|
} |
|
|
|
|
|
void OnDisable() |
|
|
{ |
|
|
//Save Settings |
|
|
EditorPrefs.SetBool("CFX_BasicFoldout", basicFoldout); |
|
|
EditorPrefs.SetBool("CFX_ColorFoldout", colorFoldout); |
|
|
EditorPrefs.SetBool("CFX_CopyFoldout", copyFoldout); |
|
|
//EditorPrefs.SetBool("CFX_MutateFoldout", mutateFoldout); |
|
|
} |
|
|
|
|
|
void UpdateSelectionCount() |
|
|
{ |
|
|
SelectedParticleSystemsCount = 0; |
|
|
foreach(var go in Selection.gameObjects) |
|
|
{ |
|
|
ParticleSystem[] systems; |
|
|
if(pref_IncludeChildren) |
|
|
systems = go.GetComponentsInChildren<ParticleSystem>(true); |
|
|
else |
|
|
systems = go.GetComponents<ParticleSystem>(); |
|
|
|
|
|
SelectedParticleSystemsCount += systems.Length; |
|
|
} |
|
|
} |
|
|
|
|
|
void OnGUI() |
|
|
{ |
|
|
GUILayout.Space(4); |
|
|
|
|
|
GUILayout.BeginHorizontal(); |
|
|
var rect = EditorGUILayout.GetControlRect(false, EditorGUIUtility.singleLineHeight, EditorStyles.label); |
|
|
GUI.Label(rect, "Cartoon FX Easy Editor", EditorStyles.boldLabel); |
|
|
var guiColor = GUI.color; |
|
|
GUI.color *= new Color(.8f,.8f,.8f,1f); |
|
|
pref_ShowAsToolbox = GUILayout.Toggle(pref_ShowAsToolbox, new GUIContent("Toolbox", "If enabled, the window will be displayed as an external toolbox.\nElse it will act as a dockable Unity window."), EditorStyles.miniButton, GUILayout.Width(65)); |
|
|
GUI.color = guiColor; |
|
|
if(GUI.changed) |
|
|
{ |
|
|
EditorPrefs.SetBool("CFX_ShowAsToolbox", pref_ShowAsToolbox); |
|
|
this.Close(); |
|
|
CFXEasyEditor.ShowWindow(); |
|
|
} |
|
|
GUILayout.EndHorizontal(); |
|
|
GUILayout.Label("Easily change properties of any Particle System!", EditorStyles.miniLabel); |
|
|
|
|
|
//---------------------------------------------------------------- |
|
|
|
|
|
pref_IncludeChildren = GUILayout.Toggle(pref_IncludeChildren, new GUIContent("Include Children", "If checked, changes will affect every Particle Systems from each child of the selected GameObject(s)")); |
|
|
if(GUI.changed) |
|
|
{ |
|
|
EditorPrefs.SetBool("CFX_IncludeChildren", pref_IncludeChildren); |
|
|
UpdateSelectionCount(); |
|
|
} |
|
|
|
|
|
GUILayout.Label(string.Format("{0} selected Particle System{1}", SelectedParticleSystemsCount, SelectedParticleSystemsCount > 1 ? "s" : ""), EditorStyles.helpBox); |
|
|
|
|
|
EditorGUILayout.BeginHorizontal(); |
|
|
|
|
|
GUILayout.Label("Test effect(s):"); |
|
|
using(new EditorGUI.DisabledScope(SelectedParticleSystemsCount <= 0)) |
|
|
{ |
|
|
|
|
|
if(GUILayout.Button("Play", EditorStyles.miniButtonLeft, GUILayout.Width(50f))) |
|
|
{ |
|
|
foreach(GameObject go in Selection.gameObjects) |
|
|
{ |
|
|
ParticleSystem[] systems = go.GetComponents<ParticleSystem>(); |
|
|
if(systems.Length == 0) continue; |
|
|
foreach(ParticleSystem system in systems) |
|
|
system.Play(pref_IncludeChildren); |
|
|
} |
|
|
} |
|
|
if(GUILayout.Button("Pause", EditorStyles.miniButtonMid, GUILayout.Width(50f))) |
|
|
{ |
|
|
foreach(GameObject go in Selection.gameObjects) |
|
|
{ |
|
|
ParticleSystem[] systems = go.GetComponents<ParticleSystem>(); |
|
|
if(systems.Length == 0) continue; |
|
|
foreach(ParticleSystem system in systems) |
|
|
system.Pause(pref_IncludeChildren); |
|
|
} |
|
|
} |
|
|
if(GUILayout.Button("Stop", EditorStyles.miniButtonMid, GUILayout.Width(50f))) |
|
|
{ |
|
|
foreach(GameObject go in Selection.gameObjects) |
|
|
{ |
|
|
ParticleSystem[] systems = go.GetComponents<ParticleSystem>(); |
|
|
if(systems.Length == 0) continue; |
|
|
foreach(ParticleSystem system in systems) |
|
|
system.Stop(pref_IncludeChildren); |
|
|
} |
|
|
} |
|
|
if(GUILayout.Button("Clear", EditorStyles.miniButtonRight, GUILayout.Width(50f))) |
|
|
{ |
|
|
foreach(GameObject go in Selection.gameObjects) |
|
|
{ |
|
|
ParticleSystem[] systems = go.GetComponents<ParticleSystem>(); |
|
|
if(systems.Length == 0) continue; |
|
|
foreach(ParticleSystem system in systems) |
|
|
{ |
|
|
system.Stop(pref_IncludeChildren); |
|
|
system.Clear(pref_IncludeChildren); |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
GUILayout.FlexibleSpace(); |
|
|
EditorGUILayout.EndHorizontal(); |
|
|
|
|
|
//---------------------------------------------------------------- |
|
|
|
|
|
//Separator |
|
|
GUISeparator(); |
|
|
//GUILayout.Box("",GUILayout.Width(this.position.width - 12), GUILayout.Height(3)); |
|
|
|
|
|
basicFoldout = EditorGUILayout.Foldout(basicFoldout, "QUICK EDIT", true); |
|
|
if(basicFoldout) |
|
|
{ |
|
|
GUILayout.Space(4); |
|
|
|
|
|
//---------------------------------------------------------------- |
|
|
|
|
|
GUILayout.BeginHorizontal(); |
|
|
if(GUILayout.Button(new GUIContent("Scale Size", "Changes the size of the Particle System(s) and other values accordingly (speed, gravity, etc.)"), GUILayout.Width(120))) |
|
|
{ |
|
|
applyScale(); |
|
|
} |
|
|
GUILayout.Label("Multiplier:",GUILayout.Width(110)); |
|
|
ScalingValue = EditorGUILayout.FloatField(ScalingValue,GUILayout.Width(50)); |
|
|
if(ScalingValue <= 0) ScalingValue = 0.1f; |
|
|
GUILayout.EndHorizontal(); |
|
|
|
|
|
//---------------------------------------------------------------- |
|
|
|
|
|
GUILayout.BeginHorizontal(); |
|
|
if(GUILayout.Button(new GUIContent("Set Speed", "Changes the simulation speed of the Particle System(s)\n1 = default speed"), GUILayout.Width(120))) |
|
|
{ |
|
|
applySpeed(); |
|
|
} |
|
|
GUILayout.Label("Speed:",GUILayout.Width(110)); |
|
|
LTScalingValue = EditorGUILayout.FloatField(LTScalingValue,GUILayout.Width(50)); |
|
|
if(LTScalingValue < 0.0f) LTScalingValue = 0.0f; |
|
|
else if(LTScalingValue > 9999) LTScalingValue = 9999; |
|
|
GUILayout.EndHorizontal(); |
|
|
|
|
|
//---------------------------------------------------------------- |
|
|
|
|
|
GUILayout.BeginHorizontal(); |
|
|
if(GUILayout.Button(new GUIContent("Set Duration", "Changes the duration of the Particle System(s)"), GUILayout.Width(120))) |
|
|
{ |
|
|
applyDuration(); |
|
|
} |
|
|
GUILayout.Label("Duration (sec):",GUILayout.Width(110)); |
|
|
DurationValue = EditorGUILayout.FloatField(DurationValue,GUILayout.Width(50)); |
|
|
if(DurationValue < 0.1f) DurationValue = 0.1f; |
|
|
else if(DurationValue > 9999) DurationValue = 9999; |
|
|
GUILayout.EndHorizontal(); |
|
|
|
|
|
//---------------------------------------------------------------- |
|
|
|
|
|
GUILayout.BeginHorizontal(); |
|
|
if(GUILayout.Button(new GUIContent("Set Delay", "Changes the delay of the Particle System(s)"), GUILayout.Width(120))) |
|
|
{ |
|
|
applyDelay(); |
|
|
} |
|
|
GUILayout.Label("Delay :",GUILayout.Width(110)); |
|
|
DelayValue = EditorGUILayout.FloatField(DelayValue,GUILayout.Width(50)); |
|
|
if(DelayValue < 0.0f) DelayValue = 0.0f; |
|
|
else if(DelayValue > 9999f) DelayValue = 9999f; |
|
|
GUILayout.EndHorizontal(); |
|
|
|
|
|
//---------------------------------------------------------------- |
|
|
|
|
|
GUILayout.Space(2); |
|
|
|
|
|
GUILayout.BeginHorizontal(); |
|
|
if(GUILayout.Button(new GUIContent("Loop", "Loop the effect (might not work properly on some effects such as explosions)"), EditorStyles.miniButtonLeft)) |
|
|
{ |
|
|
loopEffect(true); |
|
|
} |
|
|
if(GUILayout.Button(new GUIContent("Unloop", "Remove looping from the effect"), EditorStyles.miniButtonRight)) |
|
|
{ |
|
|
loopEffect(false); |
|
|
} |
|
|
if(GUILayout.Button(new GUIContent("Prewarm On", "Prewarm the effect (if looped)"), EditorStyles.miniButtonLeft)) |
|
|
{ |
|
|
prewarmEffect(true); |
|
|
} |
|
|
if(GUILayout.Button(new GUIContent("Prewarm Off", "Don't prewarm the effect (if looped)"), EditorStyles.miniButtonRight)) |
|
|
{ |
|
|
prewarmEffect(false); |
|
|
} |
|
|
GUILayout.EndHorizontal(); |
|
|
|
|
|
GUILayout.Space(2); |
|
|
|
|
|
//---------------------------------------------------------------- |
|
|
|
|
|
} |
|
|
|
|
|
//Separator |
|
|
GUISeparator(); |
|
|
//GUILayout.Box("",GUILayout.Width(this.position.width - 12), GUILayout.Height(3)); |
|
|
|
|
|
EditorGUI.BeginChangeCheck(); |
|
|
colorFoldout = EditorGUILayout.Foldout(colorFoldout, "COLOR EDIT", true); |
|
|
if(colorFoldout) |
|
|
{ |
|
|
GUILayout.Space(4); |
|
|
|
|
|
//---------------------------------------------------------------- |
|
|
|
|
|
GUILayout.BeginHorizontal(); |
|
|
if(GUILayout.Button(new GUIContent("Set Start Color(s)", "Changes the color(s) of the Particle System(s)\nSecond Color is used when Start Color is 'Random Between Two Colors'."),GUILayout.Width(120))) |
|
|
{ |
|
|
applyColor(); |
|
|
} |
|
|
ColorValue = EditorGUILayout.ColorField(ColorValue); |
|
|
ColorValue2 = EditorGUILayout.ColorField(ColorValue2); |
|
|
AffectAlpha = GUILayout.Toggle(AffectAlpha, new GUIContent("Alpha", "If checked, the alpha value will also be changed")); |
|
|
GUILayout.EndHorizontal(); |
|
|
|
|
|
//---------------------------------------------------------------- |
|
|
|
|
|
GUILayout.Space(8); |
|
|
|
|
|
using(new EditorGUI.DisabledScope(!TintStartColor && !TintColorModule && !TintColorSpeedModule && !TintTrailsModule && !TintCustomData1 && !TintCustomData2)) |
|
|
{ |
|
|
GUILayout.BeginHorizontal(); |
|
|
if(GUILayout.Button(new GUIContent("Tint Colors", "Colorize the Particle System(s) to a specific color, including gradients!\n(preserving their saturation and value)"), GUILayout.Width(120))) |
|
|
{ |
|
|
tintColor(); |
|
|
} |
|
|
TintColorValue = EditorGUILayout.ColorField(TintColorValue); |
|
|
TintColorValue = HSLColor.FromRGBA(TintColorValue).VividColor(); |
|
|
GUILayout.EndHorizontal(); |
|
|
|
|
|
//---------------------------------------------------------------- |
|
|
|
|
|
GUILayout.BeginHorizontal(); |
|
|
if(GUILayout.Button(new GUIContent("Hue Shift", "Tints the colors of the Particle System(s) by shifting the original hues by a value\n(preserving differences between colors)"), GUILayout.Width(120))) |
|
|
{ |
|
|
hueShift(); |
|
|
} |
|
|
TintHueShiftValue = EditorGUILayout.Slider(TintHueShiftValue, -180f, 180f); |
|
|
GUILayout.EndHorizontal(); |
|
|
|
|
|
//---------------------------------------------------------------- |
|
|
|
|
|
GUILayout.BeginHorizontal(); |
|
|
if(GUILayout.Button(new GUIContent("Saturation Shift", "Change the saturation of the colors of the Particle System(s)\n(preserving their hue and value)"), GUILayout.Width(120))) |
|
|
{ |
|
|
satShift(); |
|
|
} |
|
|
SatShiftValue = EditorGUILayout.Slider(SatShiftValue, -1, 1); |
|
|
GUILayout.EndHorizontal(); |
|
|
|
|
|
//---------------------------------------------------------------- |
|
|
|
|
|
GUILayout.BeginHorizontal(); |
|
|
if(GUILayout.Button(new GUIContent("Value Shift", "Change the value of the colors of the Particle System(s)\n(preserving their hue and saturation)"), GUILayout.Width(120))) |
|
|
{ |
|
|
valShift(); |
|
|
} |
|
|
ValShiftValue = EditorGUILayout.Slider(ValShiftValue, -1, 1); |
|
|
GUILayout.EndHorizontal(); |
|
|
|
|
|
//---------------------------------------------------------------- |
|
|
|
|
|
GUILayout.BeginHorizontal(); |
|
|
if (GUILayout.Button(new GUIContent("Gamma -> Linear", "Converts the colors from Gamma to Linear color space"))) |
|
|
{ |
|
|
gammaToLinear(); |
|
|
} |
|
|
if (GUILayout.Button(new GUIContent("Linear -> Gamma", "Converts the colors from Linear to Gamma color space"))) |
|
|
{ |
|
|
linearToGamma(); |
|
|
} |
|
|
GUILayout.EndHorizontal(); |
|
|
} |
|
|
|
|
|
GUILayout.Space(4); |
|
|
|
|
|
//---------------------------------------------------------------- |
|
|
|
|
|
/* |
|
|
GUILayout.BeginHorizontal(); |
|
|
GUILayout.Label("Add/Substract Lightness:"); |
|
|
|
|
|
LightnessStep = EditorGUILayout.IntField(LightnessStep, GUILayout.Width(30)); |
|
|
if(LightnessStep > 99) LightnessStep = 99; |
|
|
else if(LightnessStep < 1) LightnessStep = 1; |
|
|
GUILayout.Label("%"); |
|
|
|
|
|
if(GUILayout.Button("-", EditorStyles.miniButtonLeft, GUILayout.Width(22))) |
|
|
{ |
|
|
addLightness(true); |
|
|
} |
|
|
if(GUILayout.Button("+", EditorStyles.miniButtonRight, GUILayout.Width(22))) |
|
|
{ |
|
|
addLightness(false); |
|
|
} |
|
|
GUILayout.FlexibleSpace(); |
|
|
GUILayout.EndHorizontal(); |
|
|
*/ |
|
|
|
|
|
//---------------------------------------------------------------- |
|
|
|
|
|
GUILayout.Label("Color Modules to affect:"); |
|
|
|
|
|
GUILayout.BeginHorizontal(); |
|
|
GUILayout.Space(4); |
|
|
TintStartColor = GUILayout.Toggle(TintStartColor, new GUIContent("Start Color", "If checked, the \"Start Color\" value(s) will be affected."), EditorStyles.toolbarButton); |
|
|
TintColorModule = GUILayout.Toggle(TintColorModule, new GUIContent("Color over Lifetime", "If checked, the \"Color over Lifetime\" value(s) will be affected."), EditorStyles.toolbarButton); |
|
|
TintColorSpeedModule = GUILayout.Toggle(TintColorSpeedModule, new GUIContent("Color by Speed", "If checked, the \"Color by Speed\" value(s) will be affected."), EditorStyles.toolbarButton); |
|
|
GUILayout.Space(4); |
|
|
GUILayout.EndHorizontal(); |
|
|
GUILayout.BeginHorizontal(); |
|
|
GUILayout.Space(4); |
|
|
TintTrailsModule = GUILayout.Toggle(TintTrailsModule, new GUIContent("Trails", "If checked, the \"Trails\" value(s) will be affected."), EditorStyles.toolbarButton); |
|
|
TintCustomData1 = GUILayout.Toggle(TintCustomData1, new GUIContent("Custom Data 1", "If checked, the \"Custom Data 1\" value(s) will be affected if they have been set to a color value."), EditorStyles.toolbarButton); |
|
|
TintCustomData2 = GUILayout.Toggle(TintCustomData2, new GUIContent("Custom Data 2", "If checked, the \"Custom Data 2\" value(s) will be affected if they have been set to a color value."), EditorStyles.toolbarButton); |
|
|
GUILayout.Space(4); |
|
|
GUILayout.EndHorizontal(); |
|
|
|
|
|
TintLights = GUILayout.Toggle(TintLights, new GUIContent(" Tint Lights found in the effect's Hierarchy", "Will search for and tint any Lights found in the effect hierarchy.")); |
|
|
|
|
|
GUILayout.Space(4); |
|
|
|
|
|
//---------------------------------------------------------------- |
|
|
|
|
|
} |
|
|
|
|
|
GUISeparator(); |
|
|
|
|
|
//---------------------------------------------------------------- |
|
|
|
|
|
EditorGUI.BeginChangeCheck(); |
|
|
copyFoldout = EditorGUILayout.Foldout(copyFoldout, "COPY MODULES", true); |
|
|
if(copyFoldout) |
|
|
{ |
|
|
GUILayout.Space(4); |
|
|
|
|
|
EditorGUILayout.HelpBox("Copy selected modules from a Particle System to others!", MessageType.Info); |
|
|
|
|
|
GUILayout.Label("Source Particle System to copy from:"); |
|
|
GUILayout.BeginHorizontal(); |
|
|
{ |
|
|
EditorGUI.BeginChangeCheck(); |
|
|
copyModulesSourceParticleSystem = (ParticleSystem)EditorGUILayout.ObjectField(copyModulesSourceParticleSystem, typeof(ParticleSystem), true); |
|
|
if (GUILayout.Button("Get Selected", EditorStyles.miniButton)) |
|
|
{ |
|
|
if (Selection.activeGameObject != null) |
|
|
{ |
|
|
var ps = Selection.activeGameObject.GetComponent<ParticleSystem>(); |
|
|
if (ps != null) |
|
|
{ |
|
|
copyModulesSourceParticleSystem = ps; |
|
|
} |
|
|
} |
|
|
} |
|
|
if (EditorGUI.EndChangeCheck()) |
|
|
{ |
|
|
if (copyModulesSourceParticleSystem != null) |
|
|
{ |
|
|
FetchParticleSystemModules(copyModulesSourceParticleSystem); |
|
|
RefreshCurrentlyEnabledModules(copyModulesSourceParticleSystem, ref enabledModules); |
|
|
} |
|
|
} |
|
|
} |
|
|
GUILayout.EndHorizontal(); |
|
|
|
|
|
EditorGUILayout.LabelField("Modules to Copy:"); |
|
|
|
|
|
GUILayout.Space(4); |
|
|
|
|
|
DrawSelectableModules(ref selectedModules, ref enabledModules, copyModulesSourceParticleSystem); |
|
|
|
|
|
/* |
|
|
|
|
|
GUILayout.BeginHorizontal(); |
|
|
GUILayout.Space(8f); |
|
|
GUISelectModule(modulesToCopy[0]); |
|
|
GUISelectModule(modulesToCopy[1]); |
|
|
GUISelectModule(modulesToCopy[2]); |
|
|
GUILayout.EndHorizontal(); |
|
|
|
|
|
SelectModulesSpace(); |
|
|
GUILayout.BeginHorizontal(); |
|
|
GUILayout.Space(8f); |
|
|
#if UNITY_5_4_OR_NEWER |
|
|
GUISelectModule(modulesToCopy[3]); |
|
|
GUISelectModule(modulesToCopy[4]); |
|
|
GUISelectModule(modulesToCopy[16]); |
|
|
GUISelectModule(modulesToCopy[5]); |
|
|
#else |
|
|
GUISelectModule(modulesToCopy[3]); |
|
|
GUISelectModule(modulesToCopy[4]); |
|
|
GUISelectModule(modulesToCopy[5]); |
|
|
#endif |
|
|
GUILayout.EndHorizontal(); |
|
|
|
|
|
SelectModulesSpace(); |
|
|
GUILayout.BeginHorizontal(); |
|
|
GUILayout.Space(8f); |
|
|
GUISelectModule(modulesToCopy[6]); |
|
|
GUISelectModule(modulesToCopy[7]); |
|
|
GUILayout.EndHorizontal(); |
|
|
|
|
|
SelectModulesSpace(); |
|
|
GUILayout.BeginHorizontal(); |
|
|
GUILayout.Space(8f); |
|
|
GUISelectModule(modulesToCopy[8]); |
|
|
GUISelectModule(modulesToCopy[9]); |
|
|
GUILayout.EndHorizontal(); |
|
|
|
|
|
SelectModulesSpace(); |
|
|
GUILayout.BeginHorizontal(); |
|
|
GUILayout.Space(8f); |
|
|
GUISelectModule(modulesToCopy[10]); |
|
|
GUISelectModule(modulesToCopy[11]); |
|
|
GUILayout.EndHorizontal(); |
|
|
|
|
|
SelectModulesSpace(); |
|
|
GUILayout.BeginHorizontal(); |
|
|
GUILayout.Space(8f); |
|
|
GUISelectModule(modulesToCopy[12]); |
|
|
#if UNITY_5_4_OR_NEWER |
|
|
GUISelectModule(modulesToCopy[17]); |
|
|
#endif |
|
|
GUISelectModule(modulesToCopy[13]); |
|
|
GUILayout.EndHorizontal(); |
|
|
|
|
|
SelectModulesSpace(); |
|
|
GUILayout.BeginHorizontal(); |
|
|
GUILayout.Space(8f); |
|
|
#if UNITY_5_5_OR_NEWER |
|
|
GUISelectModule(modulesToCopy[20]); |
|
|
GUISelectModule(modulesToCopy[19]); |
|
|
GUISelectModule(modulesToCopy[18]); |
|
|
#endif |
|
|
GUISelectModule(modulesToCopy[14]); |
|
|
GUILayout.EndHorizontal(); |
|
|
|
|
|
SelectModulesSpace(); |
|
|
GUILayout.BeginHorizontal(); |
|
|
GUILayout.Space(8f); |
|
|
GUISelectModule(modulesToCopy[15]); |
|
|
GUILayout.EndHorizontal(); |
|
|
|
|
|
GUI.color = guiColor; |
|
|
|
|
|
SelectModulesSpace(); |
|
|
|
|
|
*/ |
|
|
|
|
|
GUILayout.BeginHorizontal(); |
|
|
{ |
|
|
GUILayout.FlexibleSpace(); |
|
|
if (GUILayout.Button("Copy properties to\nselected Object(s)", GUILayout.Height(Mathf.Ceil(EditorGUIUtility.singleLineHeight * 2.1f)))) |
|
|
{ |
|
|
bool foundPs = false; |
|
|
foreach (GameObject go in Selection.gameObjects) |
|
|
{ |
|
|
var system = go.GetComponent<ParticleSystem>(); |
|
|
if (system != null) |
|
|
{ |
|
|
foundPs = true; |
|
|
CopyModules(copyModulesSourceParticleSystem, system); |
|
|
} |
|
|
} |
|
|
|
|
|
if (!foundPs) |
|
|
{ |
|
|
EditorApplication.Beep(); |
|
|
Debug.LogWarning("Cartoon FX Easy Editor: No Particle System found in the selected GameObject(s)!"); |
|
|
} |
|
|
} |
|
|
} |
|
|
GUILayout.EndHorizontal(); |
|
|
} |
|
|
|
|
|
/* |
|
|
|
|
|
GUISeparator(); |
|
|
|
|
|
// TODO full list of the Properties with saving/loading presets |
|
|
|
|
|
mutateFoldout = EditorGUILayout.Foldout(mutateFoldout, "MUTATE MODULES", true); |
|
|
if (mutateFoldout) |
|
|
{ |
|
|
GUILayout.Space(4); |
|
|
|
|
|
DrawSelectableModules(ref selectedModulesMutate, ref enabledModulesMutate, selectedParticleSystem); |
|
|
|
|
|
EditorGUI.BeginChangeCheck(); |
|
|
float newValue = EditorGUILayout.Slider("<EFBFBD> percent", Mathf.Floor(mutatePercentage * 100), 0, 100); |
|
|
if (EditorGUI.EndChangeCheck()) |
|
|
{ |
|
|
mutatePercentage = newValue / 100f; |
|
|
} |
|
|
|
|
|
if (GUILayout.Button("Mutate Modules", GUILayout.Height(EditorGUIUtility.singleLineHeight*2.1f))) |
|
|
{ |
|
|
MutateModules(); |
|
|
} |
|
|
} |
|
|
|
|
|
*/ |
|
|
|
|
|
//---------------------------------------------------------------- |
|
|
|
|
|
GUILayout.Space(8); |
|
|
|
|
|
//Resize window if needed |
|
|
if (Event.current.type == EventType.Repaint) |
|
|
{ |
|
|
float h = GUILayoutUtility.GetLastRect().yMax; |
|
|
if (lastHeight != h) |
|
|
{ |
|
|
lastHeight = h; |
|
|
this.minSize = new Vector2(300, h); |
|
|
this.maxSize = new Vector2(300, h); |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
float lastHeight = 0; |
|
|
|
|
|
void DrawSelectableModules(ref bool[] selected, ref bool[] enabled, ParticleSystem target) |
|
|
{ |
|
|
if (modulesToCopy != null) |
|
|
{ |
|
|
if (enabled == null || enabled.Length != modulesToCopy.Length) |
|
|
{ |
|
|
enabled = new bool[modulesToCopy.Length]; |
|
|
} |
|
|
|
|
|
|
|
|
// +1 for the Renderer component |
|
|
if (selected == null || selected.Length != (modulesToCopy.Length + 1)) |
|
|
{ |
|
|
selected = new bool[modulesToCopy.Length + 1]; |
|
|
} |
|
|
int renderer = selected.Length - 1; |
|
|
|
|
|
// quick select: |
|
|
GUILayout.BeginHorizontal(); |
|
|
GUILayout.Label("Select:", GUILayout.Width(60)); |
|
|
if (GUILayout.Button(" All ", EditorStyles.miniButton)) |
|
|
{ |
|
|
for (int i = 0; i < modulesToCopy.Length; i++) |
|
|
{ |
|
|
if (!pref_HideDisabledModulesCopy || enabled[i]) |
|
|
{ |
|
|
selected[i] = true; |
|
|
} |
|
|
selected[renderer] = true; |
|
|
} |
|
|
} |
|
|
|
|
|
var guiColor = GUI.color; |
|
|
GUI.color *= new Color(1.0f, 0.5f, 0.5f); |
|
|
if (GUILayout.Button(" None ", EditorStyles.miniButton)) |
|
|
{ |
|
|
for (int i = 0; i < modulesToCopy.Length; i++) |
|
|
{ |
|
|
selected[i] = false; |
|
|
} |
|
|
selected[renderer] = false; |
|
|
} |
|
|
GUILayout.EndHorizontal(); |
|
|
GUI.color = guiColor; |
|
|
|
|
|
GUILayout.BeginHorizontal(); |
|
|
GUILayout.Label(" ", GUILayout.Width(60)); |
|
|
if (GUILayout.Button(" Size ", EditorStyles.miniButton)) |
|
|
{ |
|
|
for (int i = 0; i < modulesToCopy.Length; i++) |
|
|
{ |
|
|
switch (modulesToCopy[i].serializedPropertyPath) |
|
|
{ |
|
|
case "SizeModule": |
|
|
case "SizeBySpeedModule": |
|
|
selected[i] = true; |
|
|
break; |
|
|
} |
|
|
} |
|
|
} |
|
|
if (GUILayout.Button(" Movement ", EditorStyles.miniButton)) |
|
|
{ |
|
|
for (int i = 0; i < modulesToCopy.Length; i++) |
|
|
{ |
|
|
switch (modulesToCopy[i].serializedPropertyPath) |
|
|
{ |
|
|
case "VelocityModule": |
|
|
case "InheritVelocityModule": |
|
|
case "ForceModule": |
|
|
case "ExternalForcesModule": |
|
|
case "ClampVelocityModule": |
|
|
case "NoiseModule": |
|
|
case "CollisionModule": |
|
|
selected[i] = true; |
|
|
break; |
|
|
} |
|
|
} |
|
|
} |
|
|
if (GUILayout.Button(" Color/Appearance ", EditorStyles.miniButton)) |
|
|
{ |
|
|
for (int i = 0; i < modulesToCopy.Length; i++) |
|
|
{ |
|
|
switch (modulesToCopy[i].serializedPropertyPath) |
|
|
{ |
|
|
case "ColorModule": |
|
|
case "ColorBySpeedModule": |
|
|
case "TrailModule": |
|
|
case "LightsModule": |
|
|
case "UVModule": |
|
|
selected[i] = true; |
|
|
break; |
|
|
} |
|
|
selected[renderer] = true; |
|
|
} |
|
|
} |
|
|
GUILayout.EndHorizontal(); |
|
|
|
|
|
using (new EditorGUI.DisabledScope(target == null)) |
|
|
{ |
|
|
EditorGUI.BeginChangeCheck(); |
|
|
pref_HideDisabledModulesCopy = GUILayout.Toggle(pref_HideDisabledModulesCopy, new GUIContent(" Hide disabled modules", "Will hide modules that are disabled on the current source Particle System")); |
|
|
if (EditorGUI.EndChangeCheck()) |
|
|
{ |
|
|
EditorPrefs.SetBool("CFX_HideDisabledModulesCopy", pref_HideDisabledModulesCopy); |
|
|
RefreshCurrentlyEnabledModules(target, ref enabled); |
|
|
} |
|
|
} |
|
|
|
|
|
const int row = 4; |
|
|
const int padding = 4; |
|
|
for (int i = 0; i < modulesToCopy.Length; i += row) |
|
|
{ |
|
|
GUILayout.BeginHorizontal(); |
|
|
{ |
|
|
GUILayout.Space(padding); |
|
|
for (int j = 0; j < row; j++) |
|
|
{ |
|
|
if (i+j < modulesLabels.Length) |
|
|
{ |
|
|
var col = GUI.color; |
|
|
|
|
|
// special case: renderer |
|
|
/* |
|
|
if (i+j == modulesLabels.Length-1) |
|
|
{ |
|
|
if (selectedModuleRenderer) GUI.color *= Color.cyan; |
|
|
selectedModuleRenderer = GUILayout.Toggle(selectedModuleRenderer, modulesLabels[i+j], EditorStyles.toolbarButton); |
|
|
} |
|
|
else |
|
|
*/ |
|
|
{ |
|
|
bool enbl = (i+j) >= enabled.Length ? true : enabled[i+j]; |
|
|
if (pref_HideDisabledModulesCopy && !enbl) |
|
|
{ |
|
|
continue; |
|
|
} |
|
|
if (selected[i+j]) GUI.color *= Color.cyan; |
|
|
selected[i+j] = GUILayout.Toggle(selected[i+j], modulesLabels[i+j], EditorStyles.toolbarButton); |
|
|
} |
|
|
GUI.color = col; |
|
|
} |
|
|
} |
|
|
GUILayout.Space(padding); |
|
|
} |
|
|
GUILayout.EndHorizontal(); |
|
|
} |
|
|
} |
|
|
else |
|
|
{ |
|
|
EditorGUILayout.HelpBox("Select a Particle System to initialize the module list.", MessageType.Info); |
|
|
} |
|
|
} |
|
|
|
|
|
void RefreshCurrentlyEnabledModules(ParticleSystem source, ref bool[] enabledModules) |
|
|
{ |
|
|
if (modulesToCopy == null) |
|
|
{ |
|
|
return; |
|
|
} |
|
|
|
|
|
if (enabledModules == null || enabledModules.Length != modulesToCopy.Length) |
|
|
{ |
|
|
// note: no need for extra slot for renderer, consider it always enabled |
|
|
enabledModules = new bool[modulesToCopy.Length]; |
|
|
} |
|
|
|
|
|
if (source != null) |
|
|
{ |
|
|
var so = new SerializedObject(source); |
|
|
for (int i = 0; i < modulesToCopy.Length; i++) |
|
|
{ |
|
|
enabledModules[i] = modulesToCopy[i].CheckIfEnabledInSource(so); |
|
|
} |
|
|
} |
|
|
else |
|
|
{ |
|
|
for (int i = 0; i < enabledModules.Length; i++) |
|
|
{ |
|
|
enabledModules[i] = true; |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
//Loop effects |
|
|
private void loopEffect(bool setLoop) |
|
|
{ |
|
|
foreach(GameObject go in Selection.gameObjects) |
|
|
{ |
|
|
//Scale Shuriken Particles Values |
|
|
ParticleSystem[] systems; |
|
|
if(pref_IncludeChildren) |
|
|
systems = go.GetComponentsInChildren<ParticleSystem>(true); |
|
|
else |
|
|
systems = go.GetComponents<ParticleSystem>(); |
|
|
|
|
|
foreach(ParticleSystem ps in systems) |
|
|
{ |
|
|
SerializedObject so = new SerializedObject(ps); |
|
|
so.FindProperty("looping").boolValue = setLoop; |
|
|
so.ApplyModifiedProperties(); |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
//Prewarm effects |
|
|
private void prewarmEffect(bool setPrewarm) |
|
|
{ |
|
|
foreach(GameObject go in Selection.gameObjects) |
|
|
{ |
|
|
//Scale Shuriken Particles Values |
|
|
ParticleSystem[] systems; |
|
|
if(pref_IncludeChildren) |
|
|
systems = go.GetComponentsInChildren<ParticleSystem>(true); |
|
|
else |
|
|
systems = go.GetComponents<ParticleSystem>(); |
|
|
|
|
|
foreach(ParticleSystem ps in systems) |
|
|
{ |
|
|
SerializedObject so = new SerializedObject(ps); |
|
|
so.FindProperty("prewarm").boolValue = setPrewarm; |
|
|
so.ApplyModifiedProperties(); |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
//Scale Size |
|
|
private void applyScale() |
|
|
{ |
|
|
Undo.IncrementCurrentGroup(); |
|
|
int groupId = Undo.GetCurrentGroup(); |
|
|
|
|
|
foreach(GameObject go in Selection.gameObjects) |
|
|
{ |
|
|
//Scale Shuriken Particles Values |
|
|
ParticleSystem[] systems; |
|
|
if(pref_IncludeChildren) |
|
|
systems = go.GetComponentsInChildren<ParticleSystem>(true); |
|
|
else |
|
|
systems = go.GetComponents<ParticleSystem>(); |
|
|
|
|
|
foreach(ParticleSystem ps in systems) |
|
|
{ |
|
|
Undo.RegisterCompleteObjectUndo(ps, "Apply Particle Scale"); |
|
|
Undo.RegisterCompleteObjectUndo(ps.transform, "Apply Particle Scale"); |
|
|
ScaleParticleValues(ps, go); |
|
|
} |
|
|
|
|
|
//Scale Lights' range |
|
|
Light[] lights = go.GetComponentsInChildren<Light>(); |
|
|
foreach(Light light in lights) |
|
|
{ |
|
|
Undo.RegisterCompleteObjectUndo(light, "Apply Particle Scale"); |
|
|
Undo.RegisterCompleteObjectUndo(light.transform, "Apply Particle Scale"); |
|
|
light.range *= ScalingValue; |
|
|
light.transform.localPosition *= ScalingValue; |
|
|
} |
|
|
} |
|
|
|
|
|
Undo.CollapseUndoOperations(groupId); |
|
|
} |
|
|
|
|
|
//Change Color |
|
|
private void applyColor() |
|
|
{ |
|
|
foreach(GameObject go in Selection.gameObjects) |
|
|
{ |
|
|
ParticleSystem[] systems; |
|
|
if(pref_IncludeChildren) |
|
|
systems = go.GetComponentsInChildren<ParticleSystem>(true); |
|
|
else |
|
|
systems = go.GetComponents<ParticleSystem>(); |
|
|
|
|
|
foreach(ParticleSystem ps in systems) |
|
|
{ |
|
|
SerializedObject psSerial = new SerializedObject(ps); |
|
|
if(!AffectAlpha) |
|
|
{ |
|
|
psSerial.FindProperty("InitialModule.startColor.maxColor").colorValue = new Color(ColorValue.r, ColorValue.g, ColorValue.b, psSerial.FindProperty("InitialModule.startColor.maxColor").colorValue.a); |
|
|
psSerial.FindProperty("InitialModule.startColor.minColor").colorValue = new Color(ColorValue2.r, ColorValue2.g, ColorValue2.b, psSerial.FindProperty("InitialModule.startColor.minColor").colorValue.a); |
|
|
} |
|
|
else |
|
|
{ |
|
|
psSerial.FindProperty("InitialModule.startColor.maxColor").colorValue = ColorValue; |
|
|
psSerial.FindProperty("InitialModule.startColor.minColor").colorValue = ColorValue2; |
|
|
} |
|
|
psSerial.ApplyModifiedProperties(); |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
//TINT COLORS ================================================================================================================================ |
|
|
|
|
|
private void tintColor() |
|
|
{ |
|
|
float hue = HSLColor.FromRGBA(TintColorValue).h; |
|
|
GenericProcessColors(color => |
|
|
{ |
|
|
return HSLColor.FromRGBA(color).ColorWithHue(hue, false); |
|
|
}); |
|
|
} |
|
|
|
|
|
private void hueShift() |
|
|
{ |
|
|
GenericProcessColors(color => |
|
|
{ |
|
|
return HSLColor.FromRGBA(color).ColorWithHue(TintHueShiftValue, true); |
|
|
}); |
|
|
} |
|
|
|
|
|
private void satShift() |
|
|
{ |
|
|
GenericProcessColors(color => |
|
|
{ |
|
|
return HSLColor.FromRGBA(color).ColorWithSaturationOffset(SatShiftValue); |
|
|
}); |
|
|
} |
|
|
|
|
|
private void valShift() |
|
|
{ |
|
|
GenericProcessColors(color => |
|
|
{ |
|
|
return HSLColor.FromRGBA(color).ColorWithLightnessOffset(ValShiftValue); |
|
|
}); |
|
|
} |
|
|
|
|
|
private void GenericTintColorProperty(SerializedProperty colorProperty, float hue, bool shift) |
|
|
{ |
|
|
GenericEditColorProperty(colorProperty, color => |
|
|
{ |
|
|
return HSLColor.FromRGBA(color).ColorWithHue(hue, shift); |
|
|
}); |
|
|
} |
|
|
|
|
|
private void GenericEditGradient(SerializedProperty gradientProperty, System.Func<Color, Color> callback) |
|
|
{ |
|
|
gradientProperty.FindPropertyRelative("key0").colorValue = callback(gradientProperty.FindPropertyRelative("key0").colorValue); |
|
|
gradientProperty.FindPropertyRelative("key1").colorValue = callback(gradientProperty.FindPropertyRelative("key1").colorValue); |
|
|
gradientProperty.FindPropertyRelative("key2").colorValue = callback(gradientProperty.FindPropertyRelative("key2").colorValue); |
|
|
gradientProperty.FindPropertyRelative("key3").colorValue = callback(gradientProperty.FindPropertyRelative("key3").colorValue); |
|
|
gradientProperty.FindPropertyRelative("key4").colorValue = callback(gradientProperty.FindPropertyRelative("key4").colorValue); |
|
|
gradientProperty.FindPropertyRelative("key5").colorValue = callback(gradientProperty.FindPropertyRelative("key5").colorValue); |
|
|
gradientProperty.FindPropertyRelative("key6").colorValue = callback(gradientProperty.FindPropertyRelative("key6").colorValue); |
|
|
gradientProperty.FindPropertyRelative("key7").colorValue = callback(gradientProperty.FindPropertyRelative("key7").colorValue); |
|
|
} |
|
|
|
|
|
private void gammaToLinear() |
|
|
{ |
|
|
GenericProcessColors(color => |
|
|
{ |
|
|
return color.gamma; |
|
|
}); |
|
|
} |
|
|
|
|
|
private void linearToGamma() |
|
|
{ |
|
|
GenericProcessColors(color => |
|
|
{ |
|
|
return color.linear; |
|
|
}); |
|
|
} |
|
|
|
|
|
private void GenericProcessColors(System.Func<Color, Color> callback) |
|
|
{ |
|
|
foreach (GameObject go in Selection.gameObjects) |
|
|
{ |
|
|
ParticleSystem[] systems; |
|
|
if (pref_IncludeChildren) |
|
|
systems = go.GetComponentsInChildren<ParticleSystem>(true); |
|
|
else |
|
|
systems = go.GetComponents<ParticleSystem>(); |
|
|
|
|
|
foreach (ParticleSystem ps in systems) |
|
|
{ |
|
|
SerializedObject psSerial = new SerializedObject(ps); |
|
|
|
|
|
if (TintStartColor) GenericEditColorProperty(psSerial.FindProperty("InitialModule.startColor"), callback); |
|
|
if (TintColorModule) GenericEditColorProperty(psSerial.FindProperty("ColorModule.gradient"), callback); |
|
|
if (TintColorSpeedModule) GenericEditColorProperty(psSerial.FindProperty("ColorBySpeedModule.gradient"), callback); |
|
|
if (TintCustomData1) GenericEditColorProperty(psSerial.FindProperty("CustomDataModule.color0"), callback); |
|
|
if (TintCustomData2) GenericEditColorProperty(psSerial.FindProperty("CustomDataModule.color1"), callback); |
|
|
|
|
|
psSerial.ApplyModifiedProperties(); |
|
|
} |
|
|
|
|
|
if (TintLights) |
|
|
{ |
|
|
var lights = go.GetComponentsInChildren<Light>(); |
|
|
foreach (var light in lights) |
|
|
{ |
|
|
var psLight = new SerializedObject(light); |
|
|
var colorProperty = psLight.FindProperty("m_Color"); |
|
|
colorProperty.colorValue = callback(colorProperty.colorValue); |
|
|
psLight.ApplyModifiedProperties(); |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
private void GenericEditColorProperty(SerializedProperty colorProperty, System.Func<Color, Color> callback) |
|
|
{ |
|
|
int state = colorProperty.FindPropertyRelative("minMaxState").intValue; |
|
|
switch (state) |
|
|
{ |
|
|
//Constant Color |
|
|
case 0: |
|
|
colorProperty.FindPropertyRelative("maxColor").colorValue = callback(colorProperty.FindPropertyRelative("maxColor").colorValue); |
|
|
break; |
|
|
|
|
|
//Gradient |
|
|
case 1: |
|
|
GenericEditGradient(colorProperty.FindPropertyRelative("maxGradient"), callback); |
|
|
break; |
|
|
|
|
|
//Random between 2 Colors |
|
|
case 2: |
|
|
colorProperty.FindPropertyRelative("minColor").colorValue = callback(colorProperty.FindPropertyRelative("minColor").colorValue); |
|
|
colorProperty.FindPropertyRelative("maxColor").colorValue = callback(colorProperty.FindPropertyRelative("maxColor").colorValue); |
|
|
break; |
|
|
|
|
|
//Random between 2 Gradients |
|
|
case 3: |
|
|
GenericEditGradient(colorProperty.FindPropertyRelative("maxGradient"), callback); |
|
|
GenericEditGradient(colorProperty.FindPropertyRelative("minGradient"), callback); |
|
|
break; |
|
|
} |
|
|
} |
|
|
|
|
|
//LIGHTNESS OFFSET ================================================================================================================================ |
|
|
|
|
|
private void addLightness(bool substract) |
|
|
{ |
|
|
if(!TintStartColor && !TintColorModule && !TintColorSpeedModule) |
|
|
{ |
|
|
Debug.LogWarning("Cartoon FX Easy Editor: You must toggle at least one of the three Color Modules to be able to change lightness!"); |
|
|
return; |
|
|
} |
|
|
|
|
|
float lightness = (float)(LightnessStep/100f); |
|
|
if(substract) |
|
|
lightness *= -1f; |
|
|
|
|
|
foreach(GameObject go in Selection.gameObjects) |
|
|
{ |
|
|
ParticleSystem[] systems; |
|
|
if(pref_IncludeChildren) |
|
|
systems = go.GetComponentsInChildren<ParticleSystem>(true); |
|
|
else |
|
|
systems = go.GetComponents<ParticleSystem>(); |
|
|
|
|
|
foreach(ParticleSystem ps in systems) |
|
|
{ |
|
|
SerializedObject psSerial = new SerializedObject(ps); |
|
|
|
|
|
if(TintStartColor) |
|
|
GenericAddLightness(psSerial.FindProperty("InitialModule.startColor"), lightness); |
|
|
|
|
|
if(TintColorModule) |
|
|
GenericAddLightness(psSerial.FindProperty("ColorModule.gradient"), lightness); |
|
|
|
|
|
if(TintColorSpeedModule) |
|
|
GenericAddLightness(psSerial.FindProperty("ColorBySpeedModule.gradient"), lightness); |
|
|
|
|
|
psSerial.ApplyModifiedProperties(); |
|
|
psSerial.Update(); |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
private void GenericAddLightness(SerializedProperty colorProperty, float lightness) |
|
|
{ |
|
|
int state = colorProperty.FindPropertyRelative("minMaxState").intValue; |
|
|
switch(state) |
|
|
{ |
|
|
//Constant Color |
|
|
case 0: |
|
|
colorProperty.FindPropertyRelative("maxColor").colorValue = HSLColor.FromRGBA(colorProperty.FindPropertyRelative("maxColor").colorValue).ColorWithLightnessOffset(lightness); |
|
|
break; |
|
|
|
|
|
//Gradient |
|
|
case 1: |
|
|
AddLightnessGradient(colorProperty.FindPropertyRelative("maxGradient"), lightness); |
|
|
break; |
|
|
|
|
|
//Random between 2 Colors |
|
|
case 2: |
|
|
colorProperty.FindPropertyRelative("minColor").colorValue = HSLColor.FromRGBA(colorProperty.FindPropertyRelative("minColor").colorValue).ColorWithLightnessOffset(lightness); |
|
|
colorProperty.FindPropertyRelative("maxColor").colorValue = HSLColor.FromRGBA(colorProperty.FindPropertyRelative("maxColor").colorValue).ColorWithLightnessOffset(lightness); |
|
|
break; |
|
|
|
|
|
//Random between 2 Gradients |
|
|
case 3: |
|
|
AddLightnessGradient(colorProperty.FindPropertyRelative("maxGradient"), lightness); |
|
|
AddLightnessGradient(colorProperty.FindPropertyRelative("minGradient"), lightness); |
|
|
break; |
|
|
} |
|
|
} |
|
|
|
|
|
private void AddLightnessGradient(SerializedProperty gradientProperty, float lightness) |
|
|
{ |
|
|
gradientProperty.FindPropertyRelative("key0").colorValue = HSLColor.FromRGBA(gradientProperty.FindPropertyRelative("key0").colorValue).ColorWithLightnessOffset(lightness); |
|
|
gradientProperty.FindPropertyRelative("key1").colorValue = HSLColor.FromRGBA(gradientProperty.FindPropertyRelative("key1").colorValue).ColorWithLightnessOffset(lightness); |
|
|
gradientProperty.FindPropertyRelative("key2").colorValue = HSLColor.FromRGBA(gradientProperty.FindPropertyRelative("key2").colorValue).ColorWithLightnessOffset(lightness); |
|
|
gradientProperty.FindPropertyRelative("key3").colorValue = HSLColor.FromRGBA(gradientProperty.FindPropertyRelative("key3").colorValue).ColorWithLightnessOffset(lightness); |
|
|
gradientProperty.FindPropertyRelative("key4").colorValue = HSLColor.FromRGBA(gradientProperty.FindPropertyRelative("key4").colorValue).ColorWithLightnessOffset(lightness); |
|
|
gradientProperty.FindPropertyRelative("key5").colorValue = HSLColor.FromRGBA(gradientProperty.FindPropertyRelative("key5").colorValue).ColorWithLightnessOffset(lightness); |
|
|
gradientProperty.FindPropertyRelative("key6").colorValue = HSLColor.FromRGBA(gradientProperty.FindPropertyRelative("key6").colorValue).ColorWithLightnessOffset(lightness); |
|
|
gradientProperty.FindPropertyRelative("key7").colorValue = HSLColor.FromRGBA(gradientProperty.FindPropertyRelative("key7").colorValue).ColorWithLightnessOffset(lightness); |
|
|
} |
|
|
|
|
|
//RGB / HSL Conversions |
|
|
private struct HSLColor |
|
|
{ |
|
|
public float h; |
|
|
public float s; |
|
|
public float l; |
|
|
public float a; |
|
|
|
|
|
public HSLColor(float h, float s, float l, float a) |
|
|
{ |
|
|
this.h = h; |
|
|
this.s = s; |
|
|
this.l = l; |
|
|
this.a = a; |
|
|
} |
|
|
|
|
|
public HSLColor(float h, float s, float l) |
|
|
{ |
|
|
this.h = h; |
|
|
this.s = s; |
|
|
this.l = l; |
|
|
this.a = 1f; |
|
|
} |
|
|
|
|
|
public HSLColor(Color c) |
|
|
{ |
|
|
HSLColor temp = FromRGBA(c); |
|
|
h = temp.h; |
|
|
s = temp.s; |
|
|
l = temp.l; |
|
|
a = temp.a; |
|
|
} |
|
|
|
|
|
public static HSLColor FromRGBA(Color c) |
|
|
{ |
|
|
float h, s, l, a; |
|
|
a = c.a; |
|
|
|
|
|
float cmin = Mathf.Min(Mathf.Min(c.r, c.g), c.b); |
|
|
float cmax = Mathf.Max(Mathf.Max(c.r, c.g), c.b); |
|
|
|
|
|
l = (cmin + cmax) / 2f; |
|
|
|
|
|
if (cmin == cmax) |
|
|
{ |
|
|
s = 0; |
|
|
h = 0; |
|
|
} |
|
|
else |
|
|
{ |
|
|
float delta = cmax - cmin; |
|
|
|
|
|
s = (l <= .5f) ? (delta / (cmax + cmin)) : (delta / (2f - (cmax + cmin))); |
|
|
|
|
|
h = 0; |
|
|
|
|
|
if (c.r == cmax) |
|
|
{ |
|
|
h = (c.g - c.b) / delta; |
|
|
} |
|
|
else if (c.g == cmax) |
|
|
{ |
|
|
h = 2f + (c.b - c.r) / delta; |
|
|
} |
|
|
else if (c.b == cmax) |
|
|
{ |
|
|
h = 4f + (c.r - c.g) / delta; |
|
|
} |
|
|
|
|
|
h = Mathf.Repeat(h * 60f, 360f); |
|
|
} |
|
|
|
|
|
return new HSLColor(h, s, l, a); |
|
|
} |
|
|
|
|
|
public Color ToRGBA() |
|
|
{ |
|
|
float r, g, b, a; |
|
|
a = this.a; |
|
|
|
|
|
float m1, m2; |
|
|
|
|
|
m2 = (l <= .5f) ? (l * (1f + s)) : (l + s - l * s); |
|
|
m1 = 2f * l - m2; |
|
|
|
|
|
if (s == 0f) |
|
|
{ |
|
|
r = g = b = l; |
|
|
} |
|
|
else |
|
|
{ |
|
|
r = Value(m1, m2, h + 120f); |
|
|
g = Value(m1, m2, h); |
|
|
b = Value(m1, m2, h - 120f); |
|
|
} |
|
|
|
|
|
return new Color(r, g, b, a); |
|
|
} |
|
|
|
|
|
static float Value(float n1, float n2, float hue) |
|
|
{ |
|
|
hue = Mathf.Repeat(hue, 360f); |
|
|
|
|
|
if (hue < 60f) |
|
|
{ |
|
|
return n1 + (n2 - n1) * hue / 60f; |
|
|
} |
|
|
else if (hue < 180f) |
|
|
{ |
|
|
return n2; |
|
|
} |
|
|
else if (hue < 240f) |
|
|
{ |
|
|
return n1 + (n2 - n1) * (240f - hue) / 60f; |
|
|
} |
|
|
else |
|
|
{ |
|
|
return n1; |
|
|
} |
|
|
} |
|
|
|
|
|
public Color VividColor() |
|
|
{ |
|
|
this.l = 0.5f; |
|
|
this.s = 1.0f; |
|
|
return this.ToRGBA(); |
|
|
} |
|
|
|
|
|
public Color ColorWithHue(float hue, bool shift) |
|
|
{ |
|
|
if(shift) |
|
|
{ |
|
|
this.h += hue; |
|
|
while(this.h >= 360f) |
|
|
this.h -= 360f; |
|
|
while(this.h <= -360f) |
|
|
this.h += 360f; |
|
|
} |
|
|
else |
|
|
this.h = hue; |
|
|
|
|
|
return this.ToRGBA(); |
|
|
} |
|
|
|
|
|
public Color ColorWithLightnessOffset(float lightness) |
|
|
{ |
|
|
this.l += lightness; |
|
|
if(this.l > 1.0f) this.l = 1.0f; |
|
|
else if(this.l < 0.0f) this.l = 0.0f; |
|
|
|
|
|
return this.ToRGBA(); |
|
|
} |
|
|
|
|
|
public Color ColorWithSaturationOffset(float saturation) |
|
|
{ |
|
|
this.s += saturation; |
|
|
if(this.s > 1.0f) this.s = 1.0f; |
|
|
else if(this.s < 0.0f) this.s = 0.0f; |
|
|
|
|
|
return this.ToRGBA(); |
|
|
} |
|
|
|
|
|
public static implicit operator HSLColor(Color src) |
|
|
{ |
|
|
return FromRGBA(src); |
|
|
} |
|
|
|
|
|
public static implicit operator Color(HSLColor src) |
|
|
{ |
|
|
return src.ToRGBA(); |
|
|
} |
|
|
} |
|
|
|
|
|
//Scale Lifetime only |
|
|
private void applySpeed() |
|
|
{ |
|
|
foreach(GameObject go in Selection.gameObjects) |
|
|
{ |
|
|
ParticleSystem[] systems; |
|
|
if(pref_IncludeChildren) |
|
|
systems = go.GetComponentsInChildren<ParticleSystem>(true); |
|
|
else |
|
|
systems = go.GetComponents<ParticleSystem>(); |
|
|
|
|
|
//Scale Lifetime |
|
|
foreach(ParticleSystem ps in systems) |
|
|
{ |
|
|
#if UNITY_5_5_OR_NEWER |
|
|
var main = ps.main; |
|
|
main.simulationSpeed = LTScalingValue; |
|
|
#else |
|
|
ps.playbackSpeed = LTScalingValue; |
|
|
#endif |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
//Set Duration |
|
|
private void applyDuration() |
|
|
{ |
|
|
foreach(GameObject go in Selection.gameObjects) |
|
|
{ |
|
|
//Scale Shuriken Particles Values |
|
|
ParticleSystem[] systems; |
|
|
if(pref_IncludeChildren) |
|
|
systems = go.GetComponentsInChildren<ParticleSystem>(true); |
|
|
else |
|
|
systems = go.GetComponents<ParticleSystem>(); |
|
|
|
|
|
foreach(ParticleSystem ps in systems) |
|
|
{ |
|
|
SerializedObject so = new SerializedObject(ps); |
|
|
so.FindProperty("lengthInSec").floatValue = DurationValue; |
|
|
so.ApplyModifiedProperties(); |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
//Change delay |
|
|
private void applyDelay() |
|
|
{ |
|
|
foreach(GameObject go in Selection.gameObjects) |
|
|
{ |
|
|
ParticleSystem[] systems; |
|
|
if(pref_IncludeChildren) |
|
|
systems = go.GetComponentsInChildren<ParticleSystem>(true); |
|
|
else |
|
|
systems = go.GetComponents<ParticleSystem>(); |
|
|
|
|
|
//Scale Lifetime |
|
|
foreach(ParticleSystem ps in systems) |
|
|
{ |
|
|
#if UNITY_5_5_OR_NEWER |
|
|
var main = ps.main; |
|
|
main.startDelay = DelayValue; |
|
|
#else |
|
|
ps.startDelay = DelayValue; |
|
|
#endif |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
//Copy Selected Modules |
|
|
private void CopyModules(ParticleSystem source, ParticleSystem dest) |
|
|
{ |
|
|
if(source == null) |
|
|
{ |
|
|
Debug.LogWarning("Cartoon FX Easy Editor: Select a source Particle System to copy properties from first!"); |
|
|
return; |
|
|
} |
|
|
|
|
|
SerializedObject psSource = new SerializedObject(source); |
|
|
SerializedObject psDest = new SerializedObject(dest); |
|
|
|
|
|
for (int i = 0; i < modulesToCopy.Length; i++) |
|
|
{ |
|
|
var module = modulesToCopy[i]; |
|
|
|
|
|
if (!selectedModules[i]) |
|
|
{ |
|
|
continue; |
|
|
} |
|
|
|
|
|
var sp = psSource.FindProperty(module.serializedPropertyPath); |
|
|
if (sp == null) |
|
|
{ |
|
|
Debug.LogError("Couldn't find module in SerializedObject: " + module.serializedPropertyPath); |
|
|
continue; |
|
|
} |
|
|
|
|
|
psDest.CopyFromSerializedProperty(sp); |
|
|
|
|
|
// special case: extra properties for initial module |
|
|
if (i == 0) |
|
|
{ |
|
|
foreach (var path in initialModuleExtraProperties) |
|
|
{ |
|
|
var extraSp = psSource.FindProperty(path); |
|
|
if (extraSp != null) |
|
|
{ |
|
|
psDest.CopyFromSerializedProperty(extraSp); |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
psDest.ApplyModifiedProperties(); |
|
|
} |
|
|
|
|
|
//Renderer |
|
|
if (selectedModules[selectedModules.Length-1]) |
|
|
{ |
|
|
ParticleSystemRenderer rendSource = source.GetComponent<ParticleSystemRenderer>(); |
|
|
ParticleSystemRenderer rendDest = dest.GetComponent<ParticleSystemRenderer>(); |
|
|
UnityEditorInternal.ComponentUtility.CopyComponent(rendSource); |
|
|
UnityEditorInternal.ComponentUtility.PasteComponentValues(rendDest); |
|
|
} |
|
|
} |
|
|
|
|
|
/* |
|
|
private void MutateModules() |
|
|
{ |
|
|
var systems = pref_IncludeChildren ? Selection.activeGameObject.GetComponentsInChildren<ParticleSystem>() : Selection.activeGameObject.GetComponents<ParticleSystem>(); |
|
|
var so = new SerializedObject(systems); |
|
|
|
|
|
for (int i = 0; i < modulesToCopy.Length; i++) |
|
|
{ |
|
|
if (!selectedModulesMutate[i]) |
|
|
{ |
|
|
continue; |
|
|
} |
|
|
|
|
|
var sp = so.FindProperty(modulesToCopy[i].serializedPropertyPath); |
|
|
if (sp != null) |
|
|
{ |
|
|
if (sp.FindPropertyRelative("enabled").boolValue) |
|
|
{ |
|
|
GenericMutateProperty(sp); |
|
|
sp.serializedObject.ApplyModifiedProperties(); |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
private void GenericMutateProperty(SerializedProperty sp, bool recursive = true) |
|
|
{ |
|
|
System.Func<int, int> randomizeInt = intValue => |
|
|
{ |
|
|
return intValue + Mathf.RoundToInt(intValue * Random.Range(-mutatePercentage, +mutatePercentage)); |
|
|
}; |
|
|
System.Func<float, float> randomizeFloat = floatValue => |
|
|
{ |
|
|
return floatValue + (floatValue * Random.Range(-mutatePercentage, +mutatePercentage)); |
|
|
}; |
|
|
System.Func<float, float> randomizeHue = hueValue => |
|
|
{ |
|
|
hueValue = randomizeFloat(hueValue); |
|
|
while (hueValue > 1) hueValue -= 1; |
|
|
while (hueValue < 0) hueValue += 1; |
|
|
return hueValue; |
|
|
}; |
|
|
|
|
|
//Debug.Log(new string('\t', sp.depth) + sp.name + ": " + sp.type + ", " + sp.propertyType); |
|
|
|
|
|
switch (sp.type) |
|
|
{ |
|
|
case "MinMaxCurve": |
|
|
GenericMutateProperty(sp.FindPropertyRelative("scalar"), false); |
|
|
GenericMutateProperty(sp.FindPropertyRelative("minScalar"), false); |
|
|
return; |
|
|
|
|
|
case "MinMaxGradient": |
|
|
GenericEditColorProperty(sp, color => |
|
|
{ |
|
|
float h, s, v; |
|
|
Color.RGBToHSV(color, out h, out s, out v); |
|
|
h = randomizeHue(h); |
|
|
return Color.HSVToRGB(h, s, v); |
|
|
}); |
|
|
return; |
|
|
} |
|
|
|
|
|
switch (sp.propertyType) |
|
|
{ |
|
|
case SerializedPropertyType.Float: sp.floatValue = randomizeFloat(sp.floatValue); break; |
|
|
case SerializedPropertyType.Integer: sp.intValue = randomizeInt(sp.intValue); break; |
|
|
case SerializedPropertyType.Vector2: sp.vector2Value += new Vector2(randomizeFloat(sp.vector2Value.x), randomizeFloat(sp.vector2Value.y)); break; |
|
|
case SerializedPropertyType.Vector3: sp.vector3Value += new Vector3(randomizeFloat(sp.vector3Value.x), randomizeFloat(sp.vector3Value.y), randomizeFloat(sp.vector3Value.z)); break; |
|
|
case SerializedPropertyType.Vector4: sp.vector4Value += new Vector4(randomizeFloat(sp.vector4Value.x), randomizeFloat(sp.vector4Value.y), randomizeFloat(sp.vector4Value.z), randomizeFloat(sp.vector4Value.w)); break; |
|
|
} |
|
|
|
|
|
if (recursive && sp.hasVisibleChildren) |
|
|
{ |
|
|
var endProp = sp.GetEndProperty(); |
|
|
while (!SerializedProperty.EqualContents(endProp, sp) && sp.NextVisible(true)) |
|
|
{ |
|
|
GenericMutateProperty(sp, false); |
|
|
} |
|
|
} |
|
|
} |
|
|
*/ |
|
|
|
|
|
//Scale System |
|
|
private void ScaleParticleValues(ParticleSystem ps, GameObject parent) |
|
|
{ |
|
|
//Particle System |
|
|
if (ps.gameObject != parent) |
|
|
{ |
|
|
ps.transform.localPosition *= ScalingValue; |
|
|
} |
|
|
|
|
|
SerializedObject psSerial = new SerializedObject(ps); |
|
|
|
|
|
foreach(var path in PropertiesToScale) |
|
|
{ |
|
|
var prop = psSerial.FindProperty(path); |
|
|
if(prop != null) |
|
|
{ |
|
|
if(prop.propertyType == SerializedPropertyType.Float) |
|
|
{ |
|
|
prop.floatValue *= ScalingValue; |
|
|
} |
|
|
else |
|
|
{ |
|
|
Debug.LogWarning("Property in ParticleSystem is not a float: " + path + "\n"); |
|
|
} |
|
|
} |
|
|
else |
|
|
{ |
|
|
Debug.LogWarning("Property doesn't exist in ParticleSystem: " + path + "\n"); |
|
|
} |
|
|
} |
|
|
|
|
|
//Shape Module special case |
|
|
/* |
|
|
if(psSerial.FindProperty("ShapeModule.enabled").boolValue) |
|
|
{ |
|
|
//(ShapeModule.type 6 == Mesh) |
|
|
if(psSerial.FindProperty("ShapeModule.type").intValue == 6) |
|
|
{ |
|
|
//Unity 4+ : changing the Transform scale will affect the shape Mesh |
|
|
ps.transform.localScale = ps.transform.localScale * ScalingValue; |
|
|
EditorUtility.SetDirty(ps.transform); |
|
|
} |
|
|
} |
|
|
*/ |
|
|
|
|
|
//Apply Modified Properties |
|
|
psSerial.ApplyModifiedPropertiesWithoutUndo(); |
|
|
} |
|
|
|
|
|
//Properties to scale, with per-version differences |
|
|
private string[] PropertiesToScale = new string[] |
|
|
{ |
|
|
//Initial |
|
|
"InitialModule.startSize.scalar", |
|
|
"InitialModule.startSpeed.scalar", |
|
|
#if UNITY_2017_1_OR_NEWER |
|
|
"InitialModule.startSize.minScalar", |
|
|
"InitialModule.startSpeed.minScalar", |
|
|
|
|
|
"InitialModule.startSizeY.scalar", |
|
|
"InitialModule.startSizeY.minScalar", |
|
|
"InitialModule.startSizeZ.scalar", |
|
|
"InitialModule.startSizeZ.minScalar", |
|
|
#endif |
|
|
//Size by Speed |
|
|
"SizeBySpeedModule.range.x", |
|
|
"SizeBySpeedModule.range.y", |
|
|
//Velocity over Lifetime |
|
|
"VelocityModule.x.scalar", |
|
|
"VelocityModule.y.scalar", |
|
|
"VelocityModule.z.scalar", |
|
|
#if UNITY_2017_1_OR_NEWER |
|
|
"VelocityModule.x.minScalar", |
|
|
"VelocityModule.y.minScalar", |
|
|
"VelocityModule.z.minScalar", |
|
|
|
|
|
"VelocityModule.orbitalX.scalar", |
|
|
"VelocityModule.orbitalX.minScalar", |
|
|
"VelocityModule.orbitalY.scalar", |
|
|
"VelocityModule.orbitalY.minScalar", |
|
|
"VelocityModule.orbitalZ.scalar", |
|
|
"VelocityModule.orbitalZ.minScalar", |
|
|
|
|
|
"VelocityModule.orbitalOffsetX.scalar", |
|
|
"VelocityModule.orbitalOffsetX.minScalar", |
|
|
"VelocityModule.orbitalOffsetY.scalar", |
|
|
"VelocityModule.orbitalOffsetY.minScalar", |
|
|
"VelocityModule.orbitalOffsetZ.scalar", |
|
|
"VelocityModule.orbitalOffsetZ.minScalar", |
|
|
|
|
|
"VelocityModule.radial.scalar", |
|
|
"VelocityModule.radial.minScalar", |
|
|
|
|
|
"VelocityModule.speedModifier.scalar", |
|
|
"VelocityModule.speedModifier.minScalar", |
|
|
|
|
|
"InheritVelocityModule.m_Curve.scalar", |
|
|
"InheritVelocityModule.m_Curve.minScalar", |
|
|
|
|
|
"ExternalForcesModule.multiplier", |
|
|
|
|
|
"NoiseModule.strength.scalar", |
|
|
"NoiseModule.strength.minScalar", |
|
|
"NoiseModule.strengthY.scalar", |
|
|
"NoiseModule.strengthY.minScalar", |
|
|
"NoiseModule.strengthZ.scalar", |
|
|
"NoiseModule.strengthZ.minScalar", |
|
|
#endif |
|
|
//Limit Velocity over Lifetime |
|
|
"ClampVelocityModule.x.scalar", |
|
|
"ClampVelocityModule.y.scalar", |
|
|
"ClampVelocityModule.z.scalar", |
|
|
#if UNITY_2017_1_OR_NEWER |
|
|
"ClampVelocityModule.x.minScalar", |
|
|
"ClampVelocityModule.y.minScalar", |
|
|
"ClampVelocityModule.z.minScalar", |
|
|
#endif |
|
|
"ClampVelocityModule.magnitude.scalar", |
|
|
//Force over Lifetime |
|
|
"ForceModule.x.scalar", |
|
|
"ForceModule.y.scalar", |
|
|
"ForceModule.z.scalar", |
|
|
#if UNITY_2017_1_OR_NEWER |
|
|
"ForceModule.x.minScalar", |
|
|
"ForceModule.y.minScalar", |
|
|
"ForceModule.z.minScalar", |
|
|
#endif |
|
|
//Special cases per Unity version |
|
|
#if UNITY_2017_1_OR_NEWER |
|
|
"ShapeModule.m_Scale.x", |
|
|
"ShapeModule.m_Scale.y", |
|
|
"ShapeModule.m_Scale.z", |
|
|
#else |
|
|
"ShapeModule.boxX", |
|
|
"ShapeModule.boxY", |
|
|
"ShapeModule.boxZ", |
|
|
#if UNITY_5_6_OR_NEWER |
|
|
"ShapeModule.radius.value", |
|
|
#else |
|
|
"ShapeModule.radius", |
|
|
#endif |
|
|
#endif |
|
|
#if UNITY_5_5_OR_NEWER |
|
|
"EmissionModule.rateOverDistance.scalar", |
|
|
"InitialModule.gravityModifier.scalar", |
|
|
#if UNITY_2017_1_OR_NEWER |
|
|
"EmissionModule.rateOverDistance.minScalar", |
|
|
"InitialModule.gravityModifier.minScalar", |
|
|
#endif |
|
|
#else |
|
|
"InitialModule.gravityModifier", |
|
|
"EmissionModule.rate.scalar", |
|
|
#endif |
|
|
}; |
|
|
|
|
|
void GUISeparator() |
|
|
{ |
|
|
GUILayout.Space(4); |
|
|
if(EditorGUIUtility.isProSkin) |
|
|
{ |
|
|
GUILine(new Color(.15f, .15f, .15f), 1); |
|
|
GUILine(new Color(.4f, .4f, .4f), 1); |
|
|
} |
|
|
else |
|
|
{ |
|
|
GUILine(new Color(.3f, .3f, .3f), 1); |
|
|
GUILine(new Color(.9f, .9f, .9f), 1); |
|
|
} |
|
|
GUILayout.Space(4); |
|
|
} |
|
|
|
|
|
static public void GUILine(Color color, float height = 2f) |
|
|
{ |
|
|
Rect position = GUILayoutUtility.GetRect(0f, float.MaxValue, height, height, LineStyle); |
|
|
|
|
|
if(Event.current.type == EventType.Repaint) |
|
|
{ |
|
|
Color orgColor = GUI.color; |
|
|
GUI.color = orgColor * color; |
|
|
LineStyle.Draw(position, false, false, false, false); |
|
|
GUI.color = orgColor; |
|
|
} |
|
|
} |
|
|
|
|
|
static public GUIStyle _LineStyle; |
|
|
static public GUIStyle LineStyle |
|
|
{ |
|
|
get |
|
|
{ |
|
|
if(_LineStyle == null) |
|
|
{ |
|
|
_LineStyle = new GUIStyle(); |
|
|
_LineStyle.normal.background = EditorGUIUtility.whiteTexture; |
|
|
_LineStyle.stretchWidth = true; |
|
|
} |
|
|
|
|
|
return _LineStyle; |
|
|
} |
|
|
} |
|
|
}
|
|
|
|