You've already forked ParticleEffectForUGUI
mirror of
https://github.com/mob-sakai/ParticleEffectForUGUI.git
synced 2026-05-16 21:30:07 +00:00
Compare commits
8 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
592d871da2 | ||
|
|
4d0cfd3510 | ||
|
|
4c5251a5ba | ||
|
|
cbb37b0b3a | ||
|
|
3c54f6dc8d | ||
|
|
d3532b9708 | ||
|
|
2ac8a1175b | ||
|
|
9a37e64b20 |
@@ -4,7 +4,7 @@
|
|||||||
"release-4.x",
|
"release-4.x",
|
||||||
{
|
{
|
||||||
"name": "release-preview",
|
"name": "release-preview",
|
||||||
"prerelease": true
|
"prerelease": "preview"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"plugins": [
|
"plugins": [
|
||||||
|
|||||||
16
CHANGELOG.md
16
CHANGELOG.md
@@ -1,3 +1,19 @@
|
|||||||
|
# [4.8.0](https://github.com/mob-sakai/ParticleEffectForUGUI/compare/v4.7.2...v4.8.0) (2024-06-27)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* generated baking-camera object remains in the prefab or scene (again) ([de35cba](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/de35cba34c6312c1405ed522e9927c620c78e72d))
|
||||||
|
* SetParticleSystemInstance/Prefab APIs destroy generated objects ([ae3f3a8](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/ae3f3a8e62cc733420354d237ab765ac777127c8))
|
||||||
|
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* add 'custom view' option. ([a703c29](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/a703c2921ca08c2280d0c8fde01e4c0b33b5c69e))
|
||||||
|
* remove overlay window (editor) ([8358170](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/835817049f4fcf00dd2bf98dbada14f041ad3544))
|
||||||
|
* restore `Transform.localScale` when setting `autoScalingMode` to something other than `Transform` (again) ([88a970d](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/88a970d93a2b69cf011d86bd1807569e90538e0e))
|
||||||
|
* the rendering order list in inspector is now more compact ([be90172](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/be901724e064befacf617f4940b0331e1d31e1ca))
|
||||||
|
|
||||||
## [4.7.2](https://github.com/mob-sakai/ParticleEffectForUGUI/compare/v4.7.1...v4.7.2) (2024-06-21)
|
## [4.7.2](https://github.com/mob-sakai/ParticleEffectForUGUI/compare/v4.7.1...v4.7.2) (2024-06-21)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -31,35 +31,35 @@ namespace Coffee.UIExtensions
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
result.Aggregate(s_Sb, (a, b) => s_Sb.AppendFormat("{0}, ", b));
|
result.Aggregate(s_Sb, (a, b) =>
|
||||||
|
{
|
||||||
|
s_Sb.Append(b);
|
||||||
|
return s_Sb.Append(", ");
|
||||||
|
});
|
||||||
s_Sb.Length -= 2;
|
s_Sb.Length -= 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
return s_Sb.ToString();
|
return s_Sb.ToString();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void Draw(SerializedProperty sp, Material[] mats)
|
public static void Draw(SerializedProperty sp, List<Material> mats)
|
||||||
{
|
{
|
||||||
bool isClicked;
|
var pos = EditorGUILayout.GetControlRect(true);
|
||||||
using (new EditorGUILayout.HorizontalScope(GUILayout.ExpandWidth(false)))
|
var label = new GUIContent(sp.displayName, sp.tooltip);
|
||||||
{
|
var rect = EditorGUI.PrefixLabel(pos, label);
|
||||||
var pos = EditorGUILayout.GetControlRect(true);
|
var text = sp.hasMultipleDifferentValues
|
||||||
var label = new GUIContent(sp.displayName, sp.tooltip);
|
? "-"
|
||||||
var rect = EditorGUI.PrefixLabel(pos, label);
|
: CollectActiveNames(sp, s_ActiveNames);
|
||||||
var text = sp.hasMultipleDifferentValues
|
|
||||||
? "-"
|
|
||||||
: CollectActiveNames(sp, s_ActiveNames);
|
|
||||||
isClicked = GUI.Button(rect, text, EditorStyles.popup);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!isClicked) return;
|
if (!GUI.Button(rect, text, EditorStyles.popup)) return;
|
||||||
|
|
||||||
var gm = new GenericMenu();
|
var gm = new GenericMenu();
|
||||||
gm.AddItem(s_ContentNothing, s_ActiveNames.Count == 0, () =>
|
gm.AddItem(s_ContentNothing, s_ActiveNames.Count == 0, x =>
|
||||||
{
|
{
|
||||||
sp.ClearArray();
|
var current = (SerializedProperty)x;
|
||||||
sp.serializedObject.ApplyModifiedProperties();
|
current.ClearArray();
|
||||||
});
|
current.serializedObject.ApplyModifiedProperties();
|
||||||
|
}, sp);
|
||||||
|
|
||||||
if (!sp.hasMultipleDifferentValues)
|
if (!sp.hasMultipleDifferentValues)
|
||||||
{
|
{
|
||||||
@@ -73,7 +73,7 @@ namespace Coffee.UIExtensions
|
|||||||
}
|
}
|
||||||
|
|
||||||
s_Names.Clear();
|
s_Names.Clear();
|
||||||
for (var j = 0; j < mats.Length; j++)
|
for (var j = 0; j < mats.Count; j++)
|
||||||
{
|
{
|
||||||
var mat = mats[j];
|
var mat = mats[j];
|
||||||
if (!mat || !mat.shader) continue;
|
if (!mat || !mat.shader) continue;
|
||||||
@@ -82,8 +82,7 @@ namespace Coffee.UIExtensions
|
|||||||
{
|
{
|
||||||
var name = ShaderUtil.GetPropertyName(mat.shader, i);
|
var name = ShaderUtil.GetPropertyName(mat.shader, i);
|
||||||
var type = (AnimatableProperty.ShaderPropertyType)ShaderUtil.GetPropertyType(mat.shader, i);
|
var type = (AnimatableProperty.ShaderPropertyType)ShaderUtil.GetPropertyType(mat.shader, i);
|
||||||
if (s_Names.Contains(name)) continue;
|
if (!s_Names.Add(name)) continue;
|
||||||
s_Names.Add(name);
|
|
||||||
|
|
||||||
AddMenu(gm, sp, new ShaderProperty(name, type), true);
|
AddMenu(gm, sp, new ShaderProperty(name, type), true);
|
||||||
|
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ using UnityEditor;
|
|||||||
using UnityEditor.UI;
|
using UnityEditor.UI;
|
||||||
using UnityEditorInternal;
|
using UnityEditorInternal;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
|
using UnityEngine.Profiling;
|
||||||
using UnityEngine.UI;
|
using UnityEngine.UI;
|
||||||
using Coffee.UIParticleExtensions;
|
using Coffee.UIParticleExtensions;
|
||||||
#if UNITY_2021_2_OR_NEWER
|
#if UNITY_2021_2_OR_NEWER
|
||||||
@@ -26,41 +27,24 @@ namespace Coffee.UIExtensions
|
|||||||
[CanEditMultipleObjects]
|
[CanEditMultipleObjects]
|
||||||
internal class UIParticleEditor : GraphicEditor
|
internal class UIParticleEditor : GraphicEditor
|
||||||
{
|
{
|
||||||
#if UNITY_2021_2_OR_NEWER
|
|
||||||
#if UNITY_2022_1_OR_NEWER
|
|
||||||
[Overlay(typeof(SceneView), "Scene View/UI Particles", "UI Particles", true,
|
|
||||||
defaultDockPosition = DockPosition.Bottom,
|
|
||||||
defaultDockZone = DockZone.Floating,
|
|
||||||
defaultLayout = Layout.Panel)]
|
|
||||||
#else
|
|
||||||
[Overlay(typeof(SceneView), "Scene View/UI Particles", "UI Particles", true)]
|
|
||||||
#endif
|
|
||||||
private class UIParticleOverlay : IMGUIOverlay, ITransientOverlay
|
|
||||||
{
|
|
||||||
public bool visible => s_SerializedObject != null;
|
|
||||||
|
|
||||||
public override void OnGUI()
|
|
||||||
{
|
|
||||||
if (visible)
|
|
||||||
{
|
|
||||||
WindowFunction();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
//################################
|
//################################
|
||||||
// Constant or Static Members.
|
// Constant or Static Members.
|
||||||
//################################
|
//################################
|
||||||
|
private static readonly GUIContent[] s_ContentMaterials = new[]
|
||||||
|
{
|
||||||
|
new GUIContent("Material"),
|
||||||
|
new GUIContent("Trail Material")
|
||||||
|
};
|
||||||
|
|
||||||
private static readonly GUIContent s_ContentRenderingOrder = new GUIContent("Rendering Order");
|
private static readonly GUIContent s_ContentRenderingOrder = new GUIContent("Rendering Order");
|
||||||
private static readonly GUIContent s_ContentRefresh = new GUIContent("Refresh");
|
private static readonly GUIContent s_ContentRefresh = new GUIContent("Refresh");
|
||||||
private static readonly GUIContent s_ContentFix = new GUIContent("Fix");
|
private static readonly GUIContent s_ContentFix = new GUIContent("Fix");
|
||||||
private static readonly GUIContent s_ContentMaterial = new GUIContent("Material");
|
|
||||||
private static readonly GUIContent s_ContentTrailMaterial = new GUIContent("Trail Material");
|
|
||||||
private static readonly GUIContent s_Content3D = new GUIContent("3D");
|
private static readonly GUIContent s_Content3D = new GUIContent("3D");
|
||||||
private static readonly GUIContent s_ContentRandom = new GUIContent("Random");
|
private static readonly GUIContent s_ContentRandom = new GUIContent("Random");
|
||||||
private static readonly GUIContent s_ContentScale = new GUIContent("Scale");
|
private static readonly GUIContent s_ContentScale = new GUIContent("Scale");
|
||||||
private static SerializedObject s_SerializedObject;
|
private static readonly GUIContent s_ContentPrimary = new GUIContent("Primary");
|
||||||
|
private static readonly Regex s_RegexBuiltInGuid = new Regex(@"^0{16}.0{15}$", RegexOptions.Compiled);
|
||||||
|
private static readonly List<Material> s_TempMaterials = new List<Material>();
|
||||||
private static bool s_XYZMode;
|
private static bool s_XYZMode;
|
||||||
|
|
||||||
private SerializedProperty _maskable;
|
private SerializedProperty _maskable;
|
||||||
@@ -71,6 +55,8 @@ namespace Coffee.UIExtensions
|
|||||||
private SerializedProperty _groupMaxId;
|
private SerializedProperty _groupMaxId;
|
||||||
private SerializedProperty _positionMode;
|
private SerializedProperty _positionMode;
|
||||||
private SerializedProperty _autoScalingMode;
|
private SerializedProperty _autoScalingMode;
|
||||||
|
private SerializedProperty _useCustomView;
|
||||||
|
private SerializedProperty _customViewSize;
|
||||||
private ReorderableList _ro;
|
private ReorderableList _ro;
|
||||||
private bool _showMax;
|
private bool _showMax;
|
||||||
|
|
||||||
@@ -88,56 +74,6 @@ namespace Coffee.UIExtensions
|
|||||||
"_ColorMask"
|
"_ColorMask"
|
||||||
};
|
};
|
||||||
|
|
||||||
[InitializeOnLoadMethod]
|
|
||||||
private static void Init()
|
|
||||||
{
|
|
||||||
#if !UNITY_2021_2_OR_NEWER
|
|
||||||
var miSceneViewOverlayWindow = Type.GetType("UnityEditor.SceneViewOverlay, UnityEditor")
|
|
||||||
?.GetMethods(BindingFlags.Public | BindingFlags.Static)
|
|
||||||
.First(x => x.Name == "Window" && 5 <= x.GetParameters().Length);
|
|
||||||
var windowFunction = (Action<Object, SceneView>)WindowFunction;
|
|
||||||
var windowFunctionType = Type.GetType("UnityEditor.SceneViewOverlay+WindowFunction, UnityEditor");
|
|
||||||
var windowFunctionDelegate = Delegate.CreateDelegate(windowFunctionType, windowFunction.Method);
|
|
||||||
var windowTitle = new GUIContent(ObjectNames.NicifyVariableName(nameof(UIParticle)));
|
|
||||||
#if UNITY_2019_2_OR_NEWER
|
|
||||||
//public static void Window(GUIContent title, WindowFunction sceneViewFunc, int order, Object target, WindowDisplayOption option, EditorWindow window = null)
|
|
||||||
var sceneViewArgs = new object[] { windowTitle, windowFunctionDelegate, 599, null, 2, null };
|
|
||||||
#else
|
|
||||||
//public static void Window(GUIContent title, WindowFunction sceneViewFunc, int order, Object target, WindowDisplayOption option)
|
|
||||||
var sceneViewArgs = new object[] { windowTitle, windowFunctionDelegate, 599, null, 2 };
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if UNITY_2019_1_OR_NEWER
|
|
||||||
SceneView.duringSceneGui += _ =>
|
|
||||||
#else
|
|
||||||
SceneView.onSceneGUIDelegate += _ =>
|
|
||||||
#endif
|
|
||||||
{
|
|
||||||
if (s_SerializedObject != null)
|
|
||||||
{
|
|
||||||
miSceneViewOverlayWindow.Invoke(null, sceneViewArgs);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
#endif
|
|
||||||
|
|
||||||
SerializedObject CreateSerializeObject()
|
|
||||||
{
|
|
||||||
var uiParticles = Selection.gameObjects.Select(x => x.GetComponent<ParticleSystem>())
|
|
||||||
.Where(x => x)
|
|
||||||
.Select(x => x.GetComponentInParent<UIParticle>(true))
|
|
||||||
.Where(x => x && x.canvas)
|
|
||||||
.Concat(Selection.gameObjects.Select(x => x.GetComponent<UIParticle>())
|
|
||||||
.Where(x => x && x.canvas))
|
|
||||||
.Distinct()
|
|
||||||
.OfType<Object>()
|
|
||||||
.ToArray();
|
|
||||||
return 0 < uiParticles.Length ? new SerializedObject(uiParticles) : null;
|
|
||||||
}
|
|
||||||
|
|
||||||
s_SerializedObject = CreateSerializeObject();
|
|
||||||
Selection.selectionChanged += () => s_SerializedObject = CreateSerializeObject();
|
|
||||||
}
|
|
||||||
|
|
||||||
//################################
|
//################################
|
||||||
// Public/Protected Members.
|
// Public/Protected Members.
|
||||||
//################################
|
//################################
|
||||||
@@ -156,31 +92,43 @@ namespace Coffee.UIExtensions
|
|||||||
_groupMaxId = serializedObject.FindProperty("m_GroupMaxId");
|
_groupMaxId = serializedObject.FindProperty("m_GroupMaxId");
|
||||||
_positionMode = serializedObject.FindProperty("m_PositionMode");
|
_positionMode = serializedObject.FindProperty("m_PositionMode");
|
||||||
_autoScalingMode = serializedObject.FindProperty("m_AutoScalingMode");
|
_autoScalingMode = serializedObject.FindProperty("m_AutoScalingMode");
|
||||||
|
_useCustomView = serializedObject.FindProperty("m_UseCustomView");
|
||||||
|
_customViewSize = serializedObject.FindProperty("m_CustomViewSize");
|
||||||
|
|
||||||
var sp = serializedObject.FindProperty("m_Particles");
|
var sp = serializedObject.FindProperty("m_Particles");
|
||||||
_ro = new ReorderableList(sp.serializedObject, sp, true, true, true, true)
|
_ro = new ReorderableList(sp.serializedObject, sp, true, true, true, true)
|
||||||
{
|
{
|
||||||
elementHeight = EditorGUIUtility.singleLineHeight * 3 + 4,
|
elementHeightCallback = index =>
|
||||||
elementHeightCallback = _ => 3 * (EditorGUIUtility.singleLineHeight + 2),
|
{
|
||||||
|
var ps = sp.GetArrayElementAtIndex(index).objectReferenceValue as ParticleSystem;
|
||||||
|
var materialCount = 0;
|
||||||
|
if (ps && ps.TryGetComponent<ParticleSystemRenderer>(out var psr))
|
||||||
|
{
|
||||||
|
materialCount = psr.sharedMaterials.Length;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (materialCount + 1) * (EditorGUIUtility.singleLineHeight + 2);
|
||||||
|
},
|
||||||
drawElementCallback = (rect, index, _, __) =>
|
drawElementCallback = (rect, index, _, __) =>
|
||||||
{
|
{
|
||||||
EditorGUI.BeginDisabledGroup(sp.hasMultipleDifferentValues);
|
rect.y += 2;
|
||||||
rect.y += 1;
|
|
||||||
rect.height = EditorGUIUtility.singleLineHeight;
|
rect.height = EditorGUIUtility.singleLineHeight;
|
||||||
var p = sp.GetArrayElementAtIndex(index);
|
var p = sp.GetArrayElementAtIndex(index);
|
||||||
EditorGUI.ObjectField(rect, p, GUIContent.none);
|
EditorGUI.ObjectField(rect, p, GUIContent.none);
|
||||||
|
var ps = p.objectReferenceValue as ParticleSystem;
|
||||||
|
if (!ps || !ps.TryGetComponent<ParticleSystemRenderer>(out var psr)) return;
|
||||||
|
|
||||||
rect.x += 15;
|
rect.x += 15;
|
||||||
rect.width -= 15;
|
rect.width -= 15;
|
||||||
var ps = p.objectReferenceValue as ParticleSystem;
|
var materials = new SerializedObject(psr).FindProperty("m_Materials");
|
||||||
var materials = ps
|
var count = Mathf.Min(materials.arraySize, 2);
|
||||||
? new SerializedObject(ps.GetComponent<ParticleSystemRenderer>()).FindProperty("m_Materials")
|
for (var i = 0; i < count; i++)
|
||||||
: null;
|
{
|
||||||
rect.y += rect.height + 1;
|
rect.y += rect.height + 2;
|
||||||
MaterialField(rect, s_ContentMaterial, materials, 0);
|
EditorGUI.PropertyField(rect, materials.GetArrayElementAtIndex(i), s_ContentMaterials[i]);
|
||||||
rect.y += rect.height + 1;
|
}
|
||||||
MaterialField(rect, s_ContentTrailMaterial, materials, 1);
|
|
||||||
EditorGUI.EndDisabledGroup();
|
if (materials.serializedObject.hasModifiedProperties)
|
||||||
if (materials != null && materials.serializedObject.hasModifiedProperties)
|
|
||||||
{
|
{
|
||||||
materials.serializedObject.ApplyModifiedProperties();
|
materials.serializedObject.ApplyModifiedProperties();
|
||||||
}
|
}
|
||||||
@@ -216,20 +164,6 @@ namespace Coffee.UIExtensions
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void MaterialField(Rect rect, GUIContent label, SerializedProperty sp, int index)
|
|
||||||
{
|
|
||||||
if (sp == null || sp.arraySize <= index)
|
|
||||||
{
|
|
||||||
EditorGUI.BeginDisabledGroup(true);
|
|
||||||
EditorGUI.ObjectField(rect, label, null, typeof(Material), true);
|
|
||||||
EditorGUI.EndDisabledGroup();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
EditorGUI.PropertyField(rect, sp.GetArrayElementAtIndex(index), label);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Implement this function to make a custom inspector.
|
/// Implement this function to make a custom inspector.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -238,6 +172,7 @@ namespace Coffee.UIExtensions
|
|||||||
var current = target as UIParticle;
|
var current = target as UIParticle;
|
||||||
if (!current) return;
|
if (!current) return;
|
||||||
|
|
||||||
|
Profiler.BeginSample("(UIP:E) OnInspectorGUI");
|
||||||
serializedObject.Update();
|
serializedObject.Update();
|
||||||
|
|
||||||
// Maskable
|
// Maskable
|
||||||
@@ -249,13 +184,8 @@ namespace Coffee.UIExtensions
|
|||||||
EditorGUI.EndDisabledGroup();
|
EditorGUI.EndDisabledGroup();
|
||||||
|
|
||||||
// AnimatableProperties
|
// AnimatableProperties
|
||||||
var mats = current.particles
|
current.GetMaterials(s_TempMaterials);
|
||||||
.Where(x => x)
|
AnimatablePropertyEditor.Draw(_animatableProperties, s_TempMaterials);
|
||||||
.Select(x => x.GetComponent<ParticleSystemRenderer>().sharedMaterial)
|
|
||||||
.Where(x => x)
|
|
||||||
.ToArray();
|
|
||||||
|
|
||||||
AnimatablePropertyEditor.Draw(_animatableProperties, mats);
|
|
||||||
|
|
||||||
// Mesh sharing
|
// Mesh sharing
|
||||||
EditorGUI.BeginChangeCheck();
|
EditorGUI.BeginChangeCheck();
|
||||||
@@ -263,9 +193,12 @@ namespace Coffee.UIExtensions
|
|||||||
if (EditorGUI.EndChangeCheck())
|
if (EditorGUI.EndChangeCheck())
|
||||||
{
|
{
|
||||||
serializedObject.ApplyModifiedProperties();
|
serializedObject.ApplyModifiedProperties();
|
||||||
foreach (var uip in targets.OfType<UIParticle>())
|
foreach (var t in targets)
|
||||||
{
|
{
|
||||||
uip.ResetGroupId();
|
if (t is UIParticle uip)
|
||||||
|
{
|
||||||
|
uip.ResetGroupId();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -273,16 +206,29 @@ namespace Coffee.UIExtensions
|
|||||||
EditorGUILayout.PropertyField(_positionMode);
|
EditorGUILayout.PropertyField(_positionMode);
|
||||||
|
|
||||||
// Auto Scaling
|
// Auto Scaling
|
||||||
DrawAutoScaling(_autoScalingMode, targets.OfType<UIParticle>());
|
EditorGUILayout.PropertyField(_autoScalingMode);
|
||||||
|
|
||||||
|
// Custom View Size
|
||||||
|
EditorGUILayout.PropertyField(_useCustomView);
|
||||||
|
EditorGUI.BeginChangeCheck();
|
||||||
|
EditorGUI.BeginDisabledGroup(!_useCustomView.boolValue);
|
||||||
|
EditorGUI.indentLevel++;
|
||||||
|
EditorGUILayout.PropertyField(_customViewSize);
|
||||||
|
EditorGUI.indentLevel--;
|
||||||
|
EditorGUI.EndDisabledGroup();
|
||||||
|
if (EditorGUI.EndChangeCheck())
|
||||||
|
{
|
||||||
|
_customViewSize.floatValue = Mathf.Max(0.1f, _customViewSize.floatValue);
|
||||||
|
}
|
||||||
|
|
||||||
// Target ParticleSystems.
|
// Target ParticleSystems.
|
||||||
EditorGUI.BeginChangeCheck();
|
EditorGUI.BeginChangeCheck();
|
||||||
EditorGUI.BeginDisabledGroup(targets.OfType<UIParticle>().Any(x => !x.canvas));
|
|
||||||
_ro.DoLayoutList();
|
_ro.DoLayoutList();
|
||||||
EditorGUI.EndDisabledGroup();
|
|
||||||
serializedObject.ApplyModifiedProperties();
|
serializedObject.ApplyModifiedProperties();
|
||||||
|
|
||||||
if (EditorGUI.EndChangeCheck())
|
if (EditorGUI.EndChangeCheck())
|
||||||
{
|
{
|
||||||
|
EditorApplication.QueuePlayerLoopUpdate();
|
||||||
foreach (var uip in targets.OfType<UIParticle>())
|
foreach (var uip in targets.OfType<UIParticle>())
|
||||||
{
|
{
|
||||||
uip.RefreshParticles(uip.particles);
|
uip.RefreshParticles(uip.particles);
|
||||||
@@ -290,7 +236,8 @@ namespace Coffee.UIExtensions
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Non-UI built-in shader is not supported.
|
// Non-UI built-in shader is not supported.
|
||||||
foreach (var mat in current.materials)
|
Profiler.BeginSample("(UIP:E) Non-UI built-in shader is not supported.");
|
||||||
|
foreach (var mat in s_TempMaterials)
|
||||||
{
|
{
|
||||||
if (!mat || !mat.shader) continue;
|
if (!mat || !mat.shader) continue;
|
||||||
var shader = mat.shader;
|
var shader = mat.shader;
|
||||||
@@ -303,15 +250,18 @@ namespace Coffee.UIExtensions
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Profiler.EndSample();
|
||||||
|
|
||||||
// Does the shader support UI masks?
|
// Does the shader support UI masks?
|
||||||
|
Profiler.BeginSample("(UIP:E) Does the shader support UI masks?");
|
||||||
if (current.maskable && current.GetComponentInParent<Mask>(false))
|
if (current.maskable && current.GetComponentInParent<Mask>(false))
|
||||||
{
|
{
|
||||||
foreach (var mat in current.materials)
|
foreach (var mat in s_TempMaterials)
|
||||||
{
|
{
|
||||||
if (!mat || !mat.shader) continue;
|
if (!mat || !mat.shader) continue;
|
||||||
var shader = mat.shader;
|
var shader = mat.shader;
|
||||||
if (s_Shaders.Contains(shader)) continue;
|
if (!s_Shaders.Add(shader)) continue;
|
||||||
s_Shaders.Add(shader);
|
|
||||||
foreach (var propName in s_MaskablePropertyNames)
|
foreach (var propName in s_MaskablePropertyNames)
|
||||||
{
|
{
|
||||||
if (mat.HasProperty(propName)) continue;
|
if (mat.HasProperty(propName)) continue;
|
||||||
@@ -325,7 +275,9 @@ namespace Coffee.UIExtensions
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
s_TempMaterials.Clear();
|
||||||
s_Shaders.Clear();
|
s_Shaders.Clear();
|
||||||
|
Profiler.EndSample();
|
||||||
|
|
||||||
// UIParticle for trail should be removed.
|
// UIParticle for trail should be removed.
|
||||||
var label = "This UIParticle component should be removed. The UIParticle for trails is no longer needed.";
|
var label = "This UIParticle component should be removed. The UIParticle for trails is no longer needed.";
|
||||||
@@ -364,12 +316,15 @@ namespace Coffee.UIExtensions
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
Profiler.EndSample();
|
||||||
|
EditorApplication.delayCall += () => Profiler.enabled = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool IsBuiltInObject(Object obj)
|
private static bool IsBuiltInObject(Object obj)
|
||||||
{
|
{
|
||||||
return AssetDatabase.TryGetGUIDAndLocalFileIdentifier(obj, out var guid, out long _)
|
return AssetDatabase.IsMainAsset(obj)
|
||||||
&& Regex.IsMatch(guid, "^0{16}.0{15}$", RegexOptions.Compiled);
|
&& AssetDatabase.TryGetGUIDAndLocalFileIdentifier(obj, out var guid, out long _)
|
||||||
|
&& s_RegexBuiltInGuid.IsMatch(guid);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if UNITY_2018 || UNITY_2019
|
#if UNITY_2018 || UNITY_2019
|
||||||
@@ -463,7 +418,7 @@ namespace Coffee.UIExtensions
|
|||||||
{
|
{
|
||||||
EditorGUI.BeginDisabledGroup(true);
|
EditorGUI.BeginDisabledGroup(true);
|
||||||
var obj = UIParticleUpdater.GetPrimary(spGroupId.intValue);
|
var obj = UIParticleUpdater.GetPrimary(spGroupId.intValue);
|
||||||
EditorGUILayout.ObjectField("Primary", obj, typeof(UIParticle), false);
|
EditorGUILayout.ObjectField(s_ContentPrimary, obj, typeof(UIParticle), false);
|
||||||
EditorGUI.EndDisabledGroup();
|
EditorGUI.EndDisabledGroup();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -473,43 +428,11 @@ namespace Coffee.UIExtensions
|
|||||||
return showMax;
|
return showMax;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void DrawAutoScaling(SerializedProperty prop, IEnumerable<UIParticle> uiParticles)
|
private static void DrawAutoScaling(SerializedProperty prop)
|
||||||
{
|
{
|
||||||
EditorGUILayout.PropertyField(prop);
|
EditorGUILayout.PropertyField(prop);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if UNITY_2021_2_OR_NEWER
|
|
||||||
private static void WindowFunction()
|
|
||||||
#else
|
|
||||||
private static void WindowFunction(Object _, SceneView __)
|
|
||||||
#endif
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
if (s_SerializedObject == null || !s_SerializedObject.targetObject) return;
|
|
||||||
var uiParticles = s_SerializedObject.targetObjects.OfType<UIParticle>().ToArray();
|
|
||||||
if (uiParticles.Any(x => !x || !x.canvas)) return;
|
|
||||||
|
|
||||||
s_SerializedObject.Update();
|
|
||||||
using (new EditorGUILayout.VerticalScope(GUILayout.Width(220f)))
|
|
||||||
{
|
|
||||||
var labelWidth = EditorGUIUtility.labelWidth;
|
|
||||||
EditorGUIUtility.labelWidth = 100;
|
|
||||||
EditorGUILayout.PropertyField(s_SerializedObject.FindProperty("m_Enabled"));
|
|
||||||
s_XYZMode = DrawFloatOrVector3Field(s_SerializedObject.FindProperty("m_Scale3D"), s_XYZMode);
|
|
||||||
EditorGUILayout.PropertyField(s_SerializedObject.FindProperty("m_PositionMode"));
|
|
||||||
DrawAutoScaling(s_SerializedObject.FindProperty("m_AutoScalingMode"), uiParticles);
|
|
||||||
EditorGUIUtility.labelWidth = labelWidth;
|
|
||||||
}
|
|
||||||
|
|
||||||
s_SerializedObject.ApplyModifiedProperties();
|
|
||||||
}
|
|
||||||
catch
|
|
||||||
{
|
|
||||||
// ignored
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void DestroyUIParticle(UIParticle p, bool ignoreCurrent = false)
|
private void DestroyUIParticle(UIParticle p, bool ignoreCurrent = false)
|
||||||
{
|
{
|
||||||
if (!p || (ignoreCurrent && target == p)) return;
|
if (!p || (ignoreCurrent && target == p)) return;
|
||||||
|
|||||||
152
README.md
152
README.md
@@ -1,4 +1,4 @@
|
|||||||
# Particle Effect For UGUI (UI Particle)
|
# <img alt="UIParticleIcon" src="https://github.com/mob-sakai/ParticleEffectForUGUI/assets/12690315/d76e105e-a840-4f61-a1f6-8cf311c0812d" width="26"/> Particle Effect For UGUI (UI Particle)
|
||||||
|
|
||||||
This package provides a component to render particle effects for uGUI in Unity 2018.2 or later.
|
This package provides a component to render particle effects for uGUI in Unity 2018.2 or later.
|
||||||
The particle rendering is maskable and sortable, without the need for an extra Camera, RenderTexture, or Canvas.
|
The particle rendering is maskable and sortable, without the need for an extra Camera, RenderTexture, or Canvas.
|
||||||
@@ -17,45 +17,36 @@ The particle rendering is maskable and sortable, without the need for an extra C
|
|||||||
|
|
||||||
## 📝 Description
|
## 📝 Description
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
This package utilizes the new APIs `MeshBake/MashTrailBake` (introduced with Unity 2018.2) to render particles through
|
This package uses the new APIs `MeshBake/MeshTrailBake` (introduced in Unity 2018.2) to render particles through CanvasRenderer.
|
||||||
CanvasRenderer.
|
You can render, mask, and sort your ParticleSystems for UI without the need for an additional Camera, RenderTexture, or Canvas.
|
||||||
You can render, mask, and sort your ParticleSystems for UI without the necessity of an additional Camera, RenderTexture,
|
|
||||||
or Canvas.
|
|
||||||
|
|
||||||
### Features
|
### Key Features
|
||||||
|
|
||||||
* Easy to use: The package is ready to use out of the box.
|
* **Easy to use:** The package is ready to use out of the box.
|
||||||
* Sort particle effects and other UI by sibling index.
|
* **Sortable:** Sort particle effects and other UI elements by sibling index.
|
||||||
* No extra Camera, RenderTexture, or Canvas required.
|
* **Maskable:** Supports `Mask` or `RectMask2D`.
|
||||||
* Masking options for Mask or RectMask2D.
|
* **No extra components required:** No need for an additional `Camera`, `RenderTexture`, or `Canvas`.
|
||||||
* Support for the Trail module.
|
* **Trail module support:** Fully supports the Trail module.
|
||||||
* Support for CanvasGroup alpha.
|
* **CanvasGroup alpha support:** Integrates with `CanvasGroup` alpha.
|
||||||
* No allocations needed to render particles.
|
* **No allocations:** Efficiently renders particles without allocations.
|
||||||
* Compatibility with overlay, camera space, and world space.
|
* **Any canvas render mode support:** Works with overlay, camera space, and world space.
|
||||||
* Support for Universal Render Pipeline (URP) and High Definition Render Pipeline (HDRP).
|
* **Any Render pipeline support:** Compatible with Universal Render Pipeline (URP) and High Definition Render Pipeline (HDRP).
|
||||||
* Support for disabling `Enter Play Mode Options > Reload Domain`.
|
* **Disabling domain reload support:** Supports disabling `Enter Play Mode Options > Reload Domain`.
|
||||||
* Support for changing material property with AnimationClip (AnimatableProperty).
|
* **Animatable material properties:** Supports changing material properties with AnimationClip (AnimatableProperty).
|
||||||
![AnimatableProperty.gif][AnimatableProperty.gif]
|

|
||||||
* [4.0.0+] Support for 8+ materials.
|
* **Multiple materials:** Supports 8+ materials.
|
||||||
* [4.0.0+] Correct world space particle position adjustment when changing window size for standalone platforms (Windows,
|
* **Correct positioning:** Adjusts world space particle positions correctly when changing window size for standalone platforms (Windows, MacOSX, and Linux).
|
||||||
MacOSX, and Linux).
|
* **Adaptive scaling:** Provides adaptive scaling for UI (AutoScalingMode).
|
||||||
* [4.0.0+] Adaptive scaling for UI.
|
* **Performance optimization:** Mesh sharing group to improve performance.
|
||||||
* [4.0.0+] Mesh sharing group to improve performance.
|
<img alt="MeshSharing.gif" src="https://user-images.githubusercontent.com/12690315/174311048-c882df81-6c34-4eba-b0aa-5645457692f1.gif" width="450"/>
|
||||||
![MeshSharing.gif][MeshSharing.gif]
|
* **Particle attractor:** Includes a particle attractor component.
|
||||||
* [4.0.0+] Particle attractor component.
|
<img alt="ParticleAttractor.gif" src="https://user-images.githubusercontent.com/12690315/174311027-462929a4-13f0-4ec4-86ea-9c832f2eecf1.gif" width="450"/>
|
||||||
![ParticleAttractor.gif][ParticleAttractor.gif]
|
* **Emission position mode:** Supports relative/absolute particle emission position modes.
|
||||||
* [4.1.0+] Relative/Absolute particle position mode.
|
<img alt="AbsolutePosition.gif" src="https://user-images.githubusercontent.com/12690315/175751579-5a2357e8-2ecf-4afd-83c8-66e9771bde39.gif" width="450"/>
|
||||||
![AbsolutePosition.gif][AbsolutePosition.gif]
|
* **Custom view size:** Fixes min/max particle size mismatch.
|
||||||
|

|
||||||
[AnimatableProperty.gif]: https://user-images.githubusercontent.com/12690315/53286323-2d94a980-37b0-11e9-8afb-c4a207805ff2.gif
|
|
||||||
|
|
||||||
[MeshSharing.gif]: https://user-images.githubusercontent.com/12690315/174311048-c882df81-6c34-4eba-b0aa-5645457692f1.gif
|
|
||||||
|
|
||||||
[ParticleAttractor.gif]: https://user-images.githubusercontent.com/12690315/174311027-462929a4-13f0-4ec4-86ea-9c832f2eecf1.gif
|
|
||||||
|
|
||||||
[AbsolutePosition.gif]: https://user-images.githubusercontent.com/12690315/175751579-5a2357e8-2ecf-4afd-83c8-66e9771bde39.gif
|
|
||||||
|
|
||||||
<br><br>
|
<br><br>
|
||||||
|
|
||||||
@@ -76,44 +67,55 @@ or Canvas.
|
|||||||
|
|
||||||
[JMO]: https://assetstore.unity.com/publishers/1669
|
[JMO]: https://assetstore.unity.com/publishers/1669
|
||||||
|
|
||||||
|
|
||||||
<br><br>
|
<br><br>
|
||||||
|
|
||||||
## ⚙ Installation
|
## ⚙ Installation
|
||||||
|
|
||||||
_This package requires Unity 2018.3 or later._
|
_This package requires **Unity 2018.3 or later**._
|
||||||
|
|
||||||
#### Install via OpenUPM
|
#### Install via OpenUPM
|
||||||
|
|
||||||
This package is available on [OpenUPM](https://openupm.com) package registry.
|
- This package is available on [OpenUPM](https://openupm.com) package registry.
|
||||||
This is the preferred method of installation, as you can easily receive updates as they're released.
|
- This is the preferred method of installation, as you can easily receive updates as they're released.
|
||||||
|
- If you have [openupm-cli](https://github.com/openupm/openupm-cli) installed, then run the following command in your project's directory:
|
||||||
|
```
|
||||||
|
openupm add com.coffee.ui-particle
|
||||||
|
```
|
||||||
|
- To update the package, use Package Manager UI (`Window > Package Manager`) or run the following command with `@{version}`:
|
||||||
|
```
|
||||||
|
openupm add com.coffee.ui-particle@4.8.0
|
||||||
|
```
|
||||||
|
|
||||||
If you have [openupm-cli](https://github.com/openupm/openupm-cli) installed, then run the following command in your
|
#### Install via UPM (with Package Manager UI)
|
||||||
project's directory:
|
|
||||||
|
|
||||||
```sh
|
- Click `Window > Package Manager` to open Package Manager UI.
|
||||||
openupm add com.coffee.ui-particle
|
- Click `+ > Add package from git URL...` and input the repository URL: `https://github.com/mob-sakai/ParticleEffectForUGUI.git`
|
||||||
```
|

|
||||||
|
- To update the package, change suffix `#{version}` to the target version.
|
||||||
|
- e.g. `https://github.com/mob-sakai/ParticleEffectForUGUI.git#4.8.0`
|
||||||
|
|
||||||
#### Install via UPM (using Git URL)
|
#### Install via UPM (Manually)
|
||||||
|
|
||||||
Navigate to your project's Packages folder and open the `manifest.json` file. Then add this package somewhere in
|
- Open the `Packages/manifest.json` file in your project. Then add this package somewhere in the `dependencies` block:
|
||||||
the `dependencies` block:
|
```json
|
||||||
|
{
|
||||||
```json
|
"dependencies": {
|
||||||
{
|
"com.coffee.ui-particle": "https://github.com/mob-sakai/ParticleEffectForUGUI.git",
|
||||||
"dependencies": {
|
...
|
||||||
"com.coffee.ui-particle": "https://github.com/mob-sakai/ParticleEffectForUGUI.git",
|
}
|
||||||
...
|
|
||||||
}
|
}
|
||||||
}
|
```
|
||||||
```
|
|
||||||
|
|
||||||
To update the package, change suffix `#{version}` to the target version.
|
- To update the package, change suffix `#{version}` to the target version.
|
||||||
|
- e.g. `"com.coffee.ui-particle": "https://github.com/mob-sakai/ParticleEffectForUGUI.git#4.8.0",`
|
||||||
|
|
||||||
* e.g. `"com.coffee.ui-particle": "https://github.com/mob-sakai/ParticleEffectForUGUI.git#4.6.0",`
|
#### Install as Embedded Package
|
||||||
|
|
||||||
Or, use [UpmGitExtension](https://github.com/mob-sakai/UpmGitExtension) to install and update the package.
|
1. Download a source code zip file from [Releases](https://github.com/mob-sakai/ParticleEffectForUGUI.git/releases) and extract it.
|
||||||
|
2. Place it in your project's `Packages` directory.
|
||||||
|

|
||||||
|
- If you want to fix bugs or add features, install it as an embedded package.
|
||||||
|
- To update the package, you need to re-download it and replace the contents.
|
||||||
|
|
||||||
<br><br>
|
<br><br>
|
||||||
|
|
||||||
@@ -123,19 +125,28 @@ Or, use [UpmGitExtension](https://github.com/mob-sakai/UpmGitExtension) to insta
|
|||||||
|
|
||||||
`UIParticle` controls the ParticleSystems that are attached to its own game objects and child game objects.
|
`UIParticle` controls the ParticleSystems that are attached to its own game objects and child game objects.
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
- **Maskable**: Does this graphic allow masking.
|
- **Maskable**: Does this graphic allow maskable.
|
||||||
- **Scale**: Scale the rendering. When the `3D` toggle is enabled, 3D scale (x, y, z) is supported.
|
- **Scale**: Scale the rendering particles. When the `3D` toggle is enabled, 3D scale (x, y, z) is supported.
|
||||||
- **Animatable Properties**: If you want to update material properties (e.g., `_MainTex_ST`, `_Color`) in AnimationClip,
|
- **Animatable Properties**: If you want to update material properties (e.g., `_MainTex_ST`, `_Color`) in AnimationClip,
|
||||||
use this to mark the changes.
|
use this to mark as animatable.
|
||||||
- **Mesh Sharing**: Particle simulation results are shared within the same group. A large number of the same effects can
|
- **Mesh Sharing**: Particle simulation results are shared within the same group. A large number of the same effects can
|
||||||
be displayed with a small load. When the `Random` toggle is enabled, it will be grouped randomly.
|
be displayed with a small load. When the `Random` toggle is enabled, it will be grouped randomly.
|
||||||
|
- **None:** Disable mesh sharing.
|
||||||
|
- **Auto:** Automatically select Primary/Replica.
|
||||||
|
- **Primary:** Provides particle simulation results to the same group.
|
||||||
|
- **Primary Simulator:** Primary, but do not render the particle (simulation only).
|
||||||
|
- **Replica:** Render simulation results provided by the primary.
|
||||||
- **Position Mode**: Emission position mode.
|
- **Position Mode**: Emission position mode.
|
||||||
- **Absolute:** Emit from the world position of the `ParticleSystem`.
|
- **Absolute:** The particles will be emitted from the world position.
|
||||||
- **Relative:** Emit from the scaled position of the `ParticleSystem`.
|
- **Relative:** The particles will be emitted from the scaled position.
|
||||||
- **Auto Scaling**: `Transform.lossyScale` (=world scale) will be set to `(1, 1, 1)` on update. It prevents the
|
- **Auto Scaling Mode**: How to automatically adjust when the Canvas scale is changed by the screen size or reference resolution.
|
||||||
root-Canvas scale from affecting the hierarchy-scaled `ParticleSystem`.
|
- **None:** Do nothing.
|
||||||
|
- **Transform:** Transform.lossyScale (=world scale) will be set to (1, 1, 1).
|
||||||
|
- **UIParticle:** UIParticle.scale will be adjusted.
|
||||||
|
- **Use Custom View:** Use this if the particles are not displayed correctly due to min/max particle size.
|
||||||
|
- **Custom view size:** Change the bake view size.
|
||||||
- **Rendering Order**: The ParticleSystem list to be rendered. You can change the order and the materials.
|
- **Rendering Order**: The ParticleSystem list to be rendered. You can change the order and the materials.
|
||||||
|
|
||||||
**NOTE:** Press the `Refresh` button to reconstruct the rendering order based on children ParticleSystem's sorting order
|
**NOTE:** Press the `Refresh` button to reconstruct the rendering order based on children ParticleSystem's sorting order
|
||||||
@@ -176,9 +187,10 @@ section.
|
|||||||
### Script usage
|
### Script usage
|
||||||
|
|
||||||
```cs
|
```cs
|
||||||
// Instant ParticleSystem prefab with UIParticle on runtime.
|
// Instantiate ParticleSystem prefab with UIParticle on runtime.
|
||||||
var go = GameObject.Instantiate(prefab);
|
var go = GameObject.Instantiate(prefab);
|
||||||
var uiParticle = go.AddComponent<UIParticle>();
|
var uiParticle = go.AddComponent<UIParticle>();
|
||||||
|
uiParticle.scale = 100;
|
||||||
|
|
||||||
// Control by ParticleSystem.
|
// Control by ParticleSystem.
|
||||||
particleSystem.Play();
|
particleSystem.Play();
|
||||||
@@ -195,7 +207,7 @@ uiParticle.Stop();
|
|||||||
|
|
||||||
`UIParticleAttractor` attracts particles generated by the specified ParticleSystem.
|
`UIParticleAttractor` attracts particles generated by the specified ParticleSystem.
|
||||||
|
|
||||||

|

|
||||||

|

|
||||||
|
|
||||||
- **Particle System**: Attracts particles generated by the specified particle system.
|
- **Particle System**: Attracts particles generated by the specified particle system.
|
||||||
|
|||||||
@@ -44,23 +44,26 @@ namespace Coffee.UIExtensions
|
|||||||
|
|
||||||
[HideInInspector]
|
[HideInInspector]
|
||||||
[SerializeField]
|
[SerializeField]
|
||||||
|
[Obsolete]
|
||||||
internal bool m_IsTrail;
|
internal bool m_IsTrail;
|
||||||
|
|
||||||
[HideInInspector]
|
[HideInInspector]
|
||||||
[FormerlySerializedAs("m_IgnoreParent")]
|
[FormerlySerializedAs("m_IgnoreParent")]
|
||||||
[SerializeField]
|
[SerializeField]
|
||||||
|
[Obsolete]
|
||||||
private bool m_IgnoreCanvasScaler;
|
private bool m_IgnoreCanvasScaler;
|
||||||
|
|
||||||
[HideInInspector]
|
[HideInInspector]
|
||||||
[SerializeField]
|
[SerializeField]
|
||||||
private bool m_AbsoluteMode;
|
[Obsolete]
|
||||||
|
internal bool m_AbsoluteMode;
|
||||||
|
|
||||||
[Tooltip("Particle effect scale")]
|
[Tooltip("Scale the rendering particles. When the `3D` toggle is enabled, 3D scale (x, y, z) is supported.")]
|
||||||
[SerializeField]
|
[SerializeField]
|
||||||
private Vector3 m_Scale3D = new Vector3(10, 10, 10);
|
private Vector3 m_Scale3D = new Vector3(10, 10, 10);
|
||||||
|
|
||||||
[Tooltip("Animatable material properties.\n" +
|
[Tooltip("If you want to update material properties (e.g. _MainTex_ST, _Color) in AnimationClip, " +
|
||||||
"If you want to change the material properties of the ParticleSystem in Animation, enable it.")]
|
"use this to mark as animatable.")]
|
||||||
[SerializeField]
|
[SerializeField]
|
||||||
internal AnimatableProperty[] m_AnimatableProperties = new AnimatableProperty[0];
|
internal AnimatableProperty[] m_AnimatableProperties = new AnimatableProperty[0];
|
||||||
|
|
||||||
@@ -68,12 +71,13 @@ namespace Coffee.UIExtensions
|
|||||||
[SerializeField]
|
[SerializeField]
|
||||||
private List<ParticleSystem> m_Particles = new List<ParticleSystem>();
|
private List<ParticleSystem> m_Particles = new List<ParticleSystem>();
|
||||||
|
|
||||||
[Tooltip("Mesh sharing.\n" +
|
[Tooltip("Particle simulation results are shared within the same group. " +
|
||||||
"None: disable mesh sharing.\n" +
|
"A large number of the same effects can be displayed with a small load.\n" +
|
||||||
"Auto: automatically select Primary/Replica.\n" +
|
"None: Disable mesh sharing.\n" +
|
||||||
"Primary: provides particle simulation results to the same group.\n" +
|
"Auto: Automatically select Primary/Replica.\n" +
|
||||||
|
"Primary: Provides particle simulation results to the same group.\n" +
|
||||||
"Primary Simulator: Primary, but do not render the particle (simulation only).\n" +
|
"Primary Simulator: Primary, but do not render the particle (simulation only).\n" +
|
||||||
"Replica: render simulation results provided by the primary.")]
|
"Replica: Render simulation results provided by the primary.")]
|
||||||
[SerializeField]
|
[SerializeField]
|
||||||
private MeshSharing m_MeshSharing = MeshSharing.None;
|
private MeshSharing m_MeshSharing = MeshSharing.None;
|
||||||
|
|
||||||
@@ -85,26 +89,41 @@ namespace Coffee.UIExtensions
|
|||||||
[SerializeField]
|
[SerializeField]
|
||||||
private int m_GroupMaxId;
|
private int m_GroupMaxId;
|
||||||
|
|
||||||
[Tooltip("Relative: The particles will be emitted from the scaled position of ParticleSystem.\n" +
|
[Tooltip("Emission position mode.\n" +
|
||||||
"Absolute: The particles will be emitted from the world position of ParticleSystem.")]
|
"Relative: The particles will be emitted from the scaled position.\n" +
|
||||||
|
"Absolute: The particles will be emitted from the world position.")]
|
||||||
[SerializeField]
|
[SerializeField]
|
||||||
private PositionMode m_PositionMode = PositionMode.Relative;
|
private PositionMode m_PositionMode = PositionMode.Relative;
|
||||||
|
|
||||||
[SerializeField]
|
[SerializeField]
|
||||||
[Tooltip("Prevent the root-Canvas scale from affecting the hierarchy-scaled ParticleSystem.")]
|
[Obsolete]
|
||||||
private bool m_AutoScaling = true;
|
internal bool m_AutoScaling;
|
||||||
|
|
||||||
[SerializeField]
|
[SerializeField]
|
||||||
[Tooltip("Transform: Transform.lossyScale (=world scale) will be set to (1, 1, 1)." +
|
[Tooltip(
|
||||||
"UIParticle: UIParticle.scale will be adjusted.")]
|
"How to automatically adjust when the Canvas scale is changed by the screen size or reference resolution.\n" +
|
||||||
|
"None: Do nothing.\n" +
|
||||||
|
"Transform: Transform.lossyScale (=world scale) will be set to (1, 1, 1).\n" +
|
||||||
|
"UIParticle: UIParticle.scale will be adjusted.")]
|
||||||
private AutoScalingMode m_AutoScalingMode = AutoScalingMode.Transform;
|
private AutoScalingMode m_AutoScalingMode = AutoScalingMode.Transform;
|
||||||
|
|
||||||
|
[SerializeField]
|
||||||
|
[Tooltip("Use a custom view.\n" +
|
||||||
|
"Use this if the particles are not displayed correctly due to min/max particle size.")]
|
||||||
|
private bool m_UseCustomView;
|
||||||
|
|
||||||
|
[SerializeField]
|
||||||
|
[Tooltip("Custom view size.\n" +
|
||||||
|
"Change the bake view size.")]
|
||||||
|
private float m_CustomViewSize = 10;
|
||||||
|
|
||||||
private readonly List<UIParticleRenderer> _renderers = new List<UIParticleRenderer>();
|
private readonly List<UIParticleRenderer> _renderers = new List<UIParticleRenderer>();
|
||||||
private int _groupId;
|
|
||||||
private Camera _bakeCamera;
|
private Camera _bakeCamera;
|
||||||
private DrivenRectTransformTracker _tracker;
|
private Canvas _canvas;
|
||||||
private Vector3 _storedScale;
|
private int _groupId;
|
||||||
private bool _isScaleStored;
|
private bool _isScaleStored;
|
||||||
|
private Vector3 _storedScale;
|
||||||
|
private DrivenRectTransformTracker _tracker;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Should this graphic be considered a target for ray-casting?
|
/// Should this graphic be considered a target for ray-casting?
|
||||||
@@ -116,7 +135,8 @@ namespace Coffee.UIExtensions
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Mesh sharing.
|
/// Particle simulation results are shared within the same group.
|
||||||
|
/// A large number of the same effects can be displayed with a small load.
|
||||||
/// None: disable mesh sharing.
|
/// None: disable mesh sharing.
|
||||||
/// Auto: automatically select Primary/Replica.
|
/// Auto: automatically select Primary/Replica.
|
||||||
/// Primary: provides particle simulation results to the same group.
|
/// Primary: provides particle simulation results to the same group.
|
||||||
@@ -159,9 +179,9 @@ namespace Coffee.UIExtensions
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Particle position mode.
|
/// Emission position mode.
|
||||||
/// Relative: The particles will be emitted from the scaled position of the ParticleSystem.
|
/// Relative: The particles will be emitted from the scaled position.
|
||||||
/// Absolute: The particles will be emitted from the world position of the ParticleSystem.
|
/// Absolute: The particles will be emitted from the world position.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public PositionMode positionMode
|
public PositionMode positionMode
|
||||||
{
|
{
|
||||||
@@ -174,6 +194,7 @@ namespace Coffee.UIExtensions
|
|||||||
/// Relative: The particles will be emitted from the scaled position of the ParticleSystem.
|
/// Relative: The particles will be emitted from the scaled position of the ParticleSystem.
|
||||||
/// Absolute: The particles will be emitted from the world position of the ParticleSystem.
|
/// Absolute: The particles will be emitted from the world position of the ParticleSystem.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
[Obsolete("The absoluteMode is now obsolete. Please use the autoScalingMode instead.", false)]
|
||||||
public bool absoluteMode
|
public bool absoluteMode
|
||||||
{
|
{
|
||||||
get => m_PositionMode == PositionMode.Absolute;
|
get => m_PositionMode == PositionMode.Absolute;
|
||||||
@@ -191,8 +212,12 @@ namespace Coffee.UIExtensions
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Auto scaling mode.
|
/// How to automatically adjust when the Canvas scale is changed by the screen size or reference resolution.
|
||||||
|
/// <para/>
|
||||||
|
/// None: Do nothing.
|
||||||
|
/// <para/>
|
||||||
/// Transform: Transform.lossyScale (=world scale) will be set to (1, 1, 1).
|
/// Transform: Transform.lossyScale (=world scale) will be set to (1, 1, 1).
|
||||||
|
/// <para/>
|
||||||
/// UIParticle: UIParticle.scale will be adjusted.
|
/// UIParticle: UIParticle.scale will be adjusted.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public AutoScalingMode autoScalingMode
|
public AutoScalingMode autoScalingMode
|
||||||
@@ -211,6 +236,26 @@ namespace Coffee.UIExtensions
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Use a custom view.
|
||||||
|
/// Use this if the particles are not displayed correctly due to min/max particle size.
|
||||||
|
/// </summary>
|
||||||
|
public bool useCustomView
|
||||||
|
{
|
||||||
|
get => m_UseCustomView;
|
||||||
|
set => m_UseCustomView = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Custom view size.
|
||||||
|
/// Change the bake view size.
|
||||||
|
/// </summary>
|
||||||
|
public float customViewSize
|
||||||
|
{
|
||||||
|
get => m_CustomViewSize;
|
||||||
|
set => m_CustomViewSize = Mathf.Max(0.1f, value);
|
||||||
|
}
|
||||||
|
|
||||||
internal bool useMeshSharing => m_MeshSharing != MeshSharing.None;
|
internal bool useMeshSharing => m_MeshSharing != MeshSharing.None;
|
||||||
|
|
||||||
internal bool isPrimary =>
|
internal bool isPrimary =>
|
||||||
@@ -256,24 +301,6 @@ namespace Coffee.UIExtensions
|
|||||||
|
|
||||||
public List<ParticleSystem> particles => m_Particles;
|
public List<ParticleSystem> particles => m_Particles;
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Get all base materials to render.
|
|
||||||
/// </summary>
|
|
||||||
public IEnumerable<Material> materials
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
for (var i = 0; i < _renderers.Count; i++)
|
|
||||||
{
|
|
||||||
var r = _renderers[i];
|
|
||||||
if (!r || !r.material) continue;
|
|
||||||
yield return r.material;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public override Material materialForRendering => null;
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Paused.
|
/// Paused.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -328,12 +355,20 @@ namespace Coffee.UIExtensions
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// This function is called when a direct or indirect parent of the transform of the GameObject has changed.
|
||||||
|
/// </summary>
|
||||||
|
protected override void OnTransformParentChanged()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
void ISerializationCallbackReceiver.OnBeforeSerialize()
|
void ISerializationCallbackReceiver.OnBeforeSerialize()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void ISerializationCallbackReceiver.OnAfterDeserialize()
|
void ISerializationCallbackReceiver.OnAfterDeserialize()
|
||||||
{
|
{
|
||||||
|
#pragma warning disable CS0612 // Type or member is obsolete
|
||||||
if (m_IgnoreCanvasScaler || m_AutoScaling)
|
if (m_IgnoreCanvasScaler || m_AutoScaling)
|
||||||
{
|
{
|
||||||
m_IgnoreCanvasScaler = false;
|
m_IgnoreCanvasScaler = false;
|
||||||
@@ -346,31 +381,47 @@ namespace Coffee.UIExtensions
|
|||||||
m_AbsoluteMode = false;
|
m_AbsoluteMode = false;
|
||||||
m_PositionMode = PositionMode.Absolute;
|
m_PositionMode = PositionMode.Absolute;
|
||||||
}
|
}
|
||||||
|
#pragma warning restore CS0612 // Type or member is obsolete
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Play the ParticleSystems.
|
||||||
|
/// </summary>
|
||||||
public void Play()
|
public void Play()
|
||||||
{
|
{
|
||||||
particles.Exec(p => p.Simulate(0, false, true));
|
particles.Exec(p => p.Simulate(0, false, true));
|
||||||
isPaused = false;
|
isPaused = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Pause the ParticleSystems.
|
||||||
|
/// </summary>
|
||||||
public void Pause()
|
public void Pause()
|
||||||
{
|
{
|
||||||
particles.Exec(p => p.Pause());
|
particles.Exec(p => p.Pause());
|
||||||
isPaused = true;
|
isPaused = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Unpause the ParticleSystems.
|
||||||
|
/// </summary>
|
||||||
public void Resume()
|
public void Resume()
|
||||||
{
|
{
|
||||||
isPaused = false;
|
isPaused = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Stop the ParticleSystems.
|
||||||
|
/// </summary>
|
||||||
public void Stop()
|
public void Stop()
|
||||||
{
|
{
|
||||||
particles.Exec(p => p.Stop());
|
particles.Exec(p => p.Stop());
|
||||||
isPaused = true;
|
isPaused = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Start emission of the ParticleSystems.
|
||||||
|
/// </summary>
|
||||||
public void StartEmission()
|
public void StartEmission()
|
||||||
{
|
{
|
||||||
particles.Exec(p =>
|
particles.Exec(p =>
|
||||||
@@ -380,6 +431,9 @@ namespace Coffee.UIExtensions
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Stop emission of the ParticleSystems.
|
||||||
|
/// </summary>
|
||||||
public void StopEmission()
|
public void StopEmission()
|
||||||
{
|
{
|
||||||
particles.Exec(p =>
|
particles.Exec(p =>
|
||||||
@@ -389,24 +443,52 @@ namespace Coffee.UIExtensions
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Clear the particles of the ParticleSystems.
|
||||||
|
/// </summary>
|
||||||
public void Clear()
|
public void Clear()
|
||||||
{
|
{
|
||||||
particles.Exec(p => p.Clear());
|
particles.Exec(p => p.Clear());
|
||||||
isPaused = true;
|
isPaused = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get all base materials to render.
|
||||||
|
/// </summary>
|
||||||
|
public void GetMaterials(List<Material> result)
|
||||||
|
{
|
||||||
|
if (result == null) return;
|
||||||
|
|
||||||
|
for (var i = 0; i < _renderers.Count; i++)
|
||||||
|
{
|
||||||
|
var r = _renderers[i];
|
||||||
|
if (!r || !r.material) continue;
|
||||||
|
result.Add(r.material);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Refresh UIParticle using the ParticleSystem instance.
|
||||||
|
/// </summary>
|
||||||
public void SetParticleSystemInstance(GameObject instance)
|
public void SetParticleSystemInstance(GameObject instance)
|
||||||
{
|
{
|
||||||
SetParticleSystemInstance(instance, true);
|
SetParticleSystemInstance(instance, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Refresh UIParticle using the ParticleSystem instance.
|
||||||
|
/// </summary>
|
||||||
public void SetParticleSystemInstance(GameObject instance, bool destroyOldParticles)
|
public void SetParticleSystemInstance(GameObject instance, bool destroyOldParticles)
|
||||||
{
|
{
|
||||||
if (!instance) return;
|
if (!instance) return;
|
||||||
|
|
||||||
foreach (Transform child in transform)
|
var childCount = transform.childCount;
|
||||||
|
for (var i = 0; i < childCount; i++)
|
||||||
{
|
{
|
||||||
var go = child.gameObject;
|
var go = transform.GetChild(i).gameObject;
|
||||||
|
if (go.TryGetComponent<Camera>(out var cam) && cam == _bakeCamera) continue;
|
||||||
|
if (go.TryGetComponent<UIParticleRenderer>(out var _)) continue;
|
||||||
|
|
||||||
go.SetActive(false);
|
go.SetActive(false);
|
||||||
if (destroyOldParticles)
|
if (destroyOldParticles)
|
||||||
{
|
{
|
||||||
@@ -421,6 +503,10 @@ namespace Coffee.UIExtensions
|
|||||||
RefreshParticles(instance);
|
RefreshParticles(instance);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Refresh UIParticle using the prefab.
|
||||||
|
/// The prefab is automatically instantiated.
|
||||||
|
/// </summary>
|
||||||
public void SetParticleSystemPrefab(GameObject prefab)
|
public void SetParticleSystemPrefab(GameObject prefab)
|
||||||
{
|
{
|
||||||
if (!prefab) return;
|
if (!prefab) return;
|
||||||
@@ -428,16 +514,31 @@ namespace Coffee.UIExtensions
|
|||||||
SetParticleSystemInstance(Instantiate(prefab.gameObject), true);
|
SetParticleSystemInstance(Instantiate(prefab.gameObject), true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Refresh UIParticle.
|
||||||
|
/// Collect ParticleSystems under the GameObject and refresh the UIParticle.
|
||||||
|
/// </summary>
|
||||||
public void RefreshParticles()
|
public void RefreshParticles()
|
||||||
{
|
{
|
||||||
RefreshParticles(gameObject);
|
RefreshParticles(gameObject);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Refresh UIParticle.
|
||||||
|
/// Collect ParticleSystems under the GameObject and refresh the UIParticle.
|
||||||
|
/// </summary>
|
||||||
private void RefreshParticles(GameObject root)
|
private void RefreshParticles(GameObject root)
|
||||||
{
|
{
|
||||||
if (!root) return;
|
if (!root) return;
|
||||||
root.GetComponentsInChildren(true, particles);
|
root.GetComponentsInChildren(true, particles);
|
||||||
particles.RemoveAll(x => x.GetComponentInParent<UIParticle>(true) != this);
|
for (var i = particles.Count - 1; 0 <= i; i--)
|
||||||
|
{
|
||||||
|
var ps = particles[i];
|
||||||
|
if (!ps || ps.GetComponentInParent<UIParticle>(true) != this)
|
||||||
|
{
|
||||||
|
particles.RemoveAt(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for (var i = 0; i < particles.Count; i++)
|
for (var i = 0; i < particles.Count; i++)
|
||||||
{
|
{
|
||||||
@@ -452,31 +553,39 @@ namespace Coffee.UIExtensions
|
|||||||
RefreshParticles(particles);
|
RefreshParticles(particles);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void RefreshParticles(List<ParticleSystem> particles)
|
/// <summary>
|
||||||
|
/// Refresh UIParticle using a list of ParticleSystems.
|
||||||
|
/// </summary>
|
||||||
|
public void RefreshParticles(List<ParticleSystem> particleSystems)
|
||||||
{
|
{
|
||||||
|
// Collect children UIParticleRenderer components.
|
||||||
// #246: Nullptr exceptions when using nested UIParticle components in hierarchy
|
// #246: Nullptr exceptions when using nested UIParticle components in hierarchy
|
||||||
_renderers.Clear();
|
_renderers.Clear();
|
||||||
foreach (Transform child in transform)
|
var childCount = transform.childCount;
|
||||||
|
for (var i = 0; i < childCount; i++)
|
||||||
{
|
{
|
||||||
var uiParticleRenderer = child.GetComponent<UIParticleRenderer>();
|
var child = transform.GetChild(i);
|
||||||
|
if (child.TryGetComponent(out UIParticleRenderer uiParticleRenderer))
|
||||||
if (uiParticleRenderer != null)
|
|
||||||
{
|
{
|
||||||
_renderers.Add(uiParticleRenderer);
|
_renderers.Add(uiParticleRenderer);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Reset the UIParticleRenderer components.
|
||||||
for (var i = 0; i < _renderers.Count; i++)
|
for (var i = 0; i < _renderers.Count; i++)
|
||||||
{
|
{
|
||||||
_renderers[i].Reset(i);
|
_renderers[i].Reset(i);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Set the ParticleSystem to the UIParticleRenderer. If the trail is enabled, set it additionally.
|
||||||
var j = 0;
|
var j = 0;
|
||||||
for (var i = 0; i < particles.Count; i++)
|
for (var i = 0; i < particleSystems.Count; i++)
|
||||||
{
|
{
|
||||||
var ps = particles[i];
|
var ps = particleSystems[i];
|
||||||
if (!ps) continue;
|
if (!ps) continue;
|
||||||
GetRenderer(j++).Set(this, ps, false);
|
GetRenderer(j++).Set(this, ps, false);
|
||||||
|
|
||||||
|
// If the trail is enabled, set it additionally.
|
||||||
if (ps.trails.enabled)
|
if (ps.trails.enabled)
|
||||||
{
|
{
|
||||||
GetRenderer(j++).Set(this, ps, true);
|
GetRenderer(j++).Set(this, ps, true);
|
||||||
@@ -501,8 +610,12 @@ namespace Coffee.UIExtensions
|
|||||||
}
|
}
|
||||||
|
|
||||||
var currentScale = transform.localScale;
|
var currentScale = transform.localScale;
|
||||||
_storedScale = currentScale;
|
if (!_isScaleStored)
|
||||||
_isScaleStored = true;
|
{
|
||||||
|
_storedScale = currentScale.IsVisible() ? currentScale : Vector3.one;
|
||||||
|
_isScaleStored = true;
|
||||||
|
}
|
||||||
|
|
||||||
_tracker.Add(this, rectTransform, DrivenTransformProperties.Scale);
|
_tracker.Add(this, rectTransform, DrivenTransformProperties.Scale);
|
||||||
var newScale = parentScale.Inverse();
|
var newScale = parentScale.Inverse();
|
||||||
if (currentScale != newScale)
|
if (currentScale != newScale)
|
||||||
@@ -518,11 +631,10 @@ namespace Coffee.UIExtensions
|
|||||||
for (var i = 0; i < _renderers.Count; i++)
|
for (var i = 0; i < _renderers.Count; i++)
|
||||||
{
|
{
|
||||||
var r = _renderers[i];
|
var r = _renderers[i];
|
||||||
if (!r)
|
if (r) continue;
|
||||||
{
|
|
||||||
RefreshParticles(particles);
|
RefreshParticles(particles);
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var bakeCamera = GetBakeCamera();
|
var bakeCamera = GetBakeCamera();
|
||||||
@@ -530,6 +642,7 @@ namespace Coffee.UIExtensions
|
|||||||
{
|
{
|
||||||
var r = _renderers[i];
|
var r = _renderers[i];
|
||||||
if (!r) continue;
|
if (!r) continue;
|
||||||
|
|
||||||
r.UpdateMesh(bakeCamera);
|
r.UpdateMesh(bakeCamera);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -581,7 +694,16 @@ namespace Coffee.UIExtensions
|
|||||||
private Camera GetBakeCamera()
|
private Camera GetBakeCamera()
|
||||||
{
|
{
|
||||||
if (!canvas) return Camera.main;
|
if (!canvas) return Camera.main;
|
||||||
if (_bakeCamera) return _bakeCamera;
|
if (!useCustomView && canvas.renderMode != RenderMode.ScreenSpaceOverlay && canvas.rootCanvas.worldCamera)
|
||||||
|
{
|
||||||
|
return canvas.rootCanvas.worldCamera;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_bakeCamera)
|
||||||
|
{
|
||||||
|
_bakeCamera.orthographicSize = useCustomView ? customViewSize : 10;
|
||||||
|
return _bakeCamera;
|
||||||
|
}
|
||||||
|
|
||||||
// Find existing baking camera.
|
// Find existing baking camera.
|
||||||
var childCount = transform.childCount;
|
var childCount = transform.childCount;
|
||||||
@@ -598,10 +720,7 @@ namespace Coffee.UIExtensions
|
|||||||
// Create baking camera.
|
// Create baking camera.
|
||||||
if (!_bakeCamera)
|
if (!_bakeCamera)
|
||||||
{
|
{
|
||||||
var go = new GameObject("[generated] UIParticle BakingCamera")
|
var go = new GameObject("[generated] UIParticle BakingCamera");
|
||||||
{
|
|
||||||
hideFlags = HideFlags.HideAndDontSave
|
|
||||||
};
|
|
||||||
go.SetActive(false);
|
go.SetActive(false);
|
||||||
go.transform.SetParent(transform, false);
|
go.transform.SetParent(transform, false);
|
||||||
_bakeCamera = go.AddComponent<Camera>();
|
_bakeCamera = go.AddComponent<Camera>();
|
||||||
@@ -609,7 +728,7 @@ namespace Coffee.UIExtensions
|
|||||||
|
|
||||||
// Setup baking camera.
|
// Setup baking camera.
|
||||||
_bakeCamera.enabled = false;
|
_bakeCamera.enabled = false;
|
||||||
_bakeCamera.orthographicSize = 1000;
|
_bakeCamera.orthographicSize = useCustomView ? customViewSize : 10;
|
||||||
_bakeCamera.transform.SetPositionAndRotation(new Vector3(0, 0, -1000), Quaternion.identity);
|
_bakeCamera.transform.SetPositionAndRotation(new Vector3(0, 0, -1000), Quaternion.identity);
|
||||||
_bakeCamera.orthographic = true;
|
_bakeCamera.orthographic = true;
|
||||||
_bakeCamera.farClipPlane = 2000f;
|
_bakeCamera.farClipPlane = 2000f;
|
||||||
@@ -620,6 +739,9 @@ namespace Coffee.UIExtensions
|
|||||||
_bakeCamera.renderingPath = RenderingPath.Forward;
|
_bakeCamera.renderingPath = RenderingPath.Forward;
|
||||||
_bakeCamera.useOcclusionCulling = false;
|
_bakeCamera.useOcclusionCulling = false;
|
||||||
|
|
||||||
|
_bakeCamera.gameObject.SetActive(false);
|
||||||
|
_bakeCamera.gameObject.hideFlags = HideFlags.HideAndDontSave;
|
||||||
|
|
||||||
return _bakeCamera;
|
return _bakeCamera;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -31,6 +31,7 @@ namespace Coffee.UIExtensions
|
|||||||
private Material _currentMaterialForRendering;
|
private Material _currentMaterialForRendering;
|
||||||
private bool _delay;
|
private bool _delay;
|
||||||
private int _index;
|
private int _index;
|
||||||
|
private bool _isPrevStored;
|
||||||
private bool _isTrail;
|
private bool _isTrail;
|
||||||
private Bounds _lastBounds;
|
private Bounds _lastBounds;
|
||||||
private Material _modifiedMaterial;
|
private Material _modifiedMaterial;
|
||||||
@@ -39,9 +40,8 @@ namespace Coffee.UIExtensions
|
|||||||
private float _prevCanvasScale;
|
private float _prevCanvasScale;
|
||||||
private Vector3 _prevPsPos;
|
private Vector3 _prevPsPos;
|
||||||
private Vector3 _prevScale;
|
private Vector3 _prevScale;
|
||||||
private bool _isPrevStored;
|
|
||||||
private Vector2Int _prevScreenSize;
|
private Vector2Int _prevScreenSize;
|
||||||
private bool _prewarm;
|
private bool _preWarm;
|
||||||
private ParticleSystemRenderer _renderer;
|
private ParticleSystemRenderer _renderer;
|
||||||
|
|
||||||
public override Texture mainTexture => _isTrail ? null : _particleSystem.GetTextureForSprite();
|
public override Texture mainTexture => _isTrail ? null : _particleSystem.GetTextureForSprite();
|
||||||
@@ -111,8 +111,7 @@ namespace Coffee.UIExtensions
|
|||||||
if (this && isActiveAndEnabled)
|
if (this && isActiveAndEnabled)
|
||||||
{
|
{
|
||||||
material = null;
|
material = null;
|
||||||
workerMesh.Clear();
|
canvasRenderer.Clear();
|
||||||
canvasRenderer.SetMesh(workerMesh);
|
|
||||||
_lastBounds = new Bounds();
|
_lastBounds = new Bounds();
|
||||||
enabled = false;
|
enabled = false;
|
||||||
}
|
}
|
||||||
@@ -221,20 +220,20 @@ namespace Coffee.UIExtensions
|
|||||||
gameObject.layer = parent.gameObject.layer;
|
gameObject.layer = parent.gameObject.layer;
|
||||||
|
|
||||||
_particleSystem = ps;
|
_particleSystem = ps;
|
||||||
_prewarm = _particleSystem.main.prewarm;
|
_preWarm = _particleSystem.main.prewarm;
|
||||||
|
|
||||||
#if UNITY_EDITOR
|
#if UNITY_EDITOR
|
||||||
if (Application.isPlaying)
|
if (Application.isPlaying)
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
if (_particleSystem.isPlaying || _prewarm)
|
if (_particleSystem.isPlaying || _preWarm)
|
||||||
{
|
{
|
||||||
_particleSystem.Clear();
|
_particleSystem.Clear();
|
||||||
_particleSystem.Pause();
|
_particleSystem.Pause();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_renderer = ps.GetComponent<ParticleSystemRenderer>();
|
ps.TryGetComponent(out _renderer);
|
||||||
_renderer.enabled = false;
|
_renderer.enabled = false;
|
||||||
|
|
||||||
//_emitter = emitter;
|
//_emitter = emitter;
|
||||||
@@ -563,10 +562,7 @@ namespace Coffee.UIExtensions
|
|||||||
return Matrix4x4.Scale(scale);
|
return Matrix4x4.Scale(scale);
|
||||||
case ParticleSystemSimulationSpace.Custom:
|
case ParticleSystemSimulationSpace.Custom:
|
||||||
return Matrix4x4.Translate(_particleSystem.main.customSimulationSpace.position.GetScaled(scale))
|
return Matrix4x4.Translate(_particleSystem.main.customSimulationSpace.position.GetScaled(scale))
|
||||||
//* Matrix4x4.Translate(wpos)
|
* Matrix4x4.Scale(scale);
|
||||||
* Matrix4x4.Scale(scale)
|
|
||||||
//* Matrix4x4.Translate(-wpos)
|
|
||||||
;
|
|
||||||
default:
|
default:
|
||||||
throw new NotSupportedException();
|
throw new NotSupportedException();
|
||||||
}
|
}
|
||||||
@@ -582,7 +578,8 @@ namespace Coffee.UIExtensions
|
|||||||
var screenSize = new Vector2Int(Screen.width, Screen.height);
|
var screenSize = new Vector2Int(Screen.width, Screen.height);
|
||||||
var isWorldSpace = _particleSystem.IsWorldSpace();
|
var isWorldSpace = _particleSystem.IsWorldSpace();
|
||||||
var canvasScale = _parent.canvas ? _parent.canvas.scaleFactor : 1f;
|
var canvasScale = _parent.canvas ? _parent.canvas.scaleFactor : 1f;
|
||||||
var resolutionChanged = _prevScreenSize != screenSize || _prevCanvasScale != canvasScale;
|
var resolutionChanged = _prevScreenSize != screenSize
|
||||||
|
|| !Mathf.Approximately(_prevCanvasScale, canvasScale);
|
||||||
if (resolutionChanged && isWorldSpace && _isPrevStored)
|
if (resolutionChanged && isWorldSpace && _isPrevStored)
|
||||||
{
|
{
|
||||||
// Update particle array size and get particles.
|
// Update particle array size and get particles.
|
||||||
@@ -590,7 +587,7 @@ namespace Coffee.UIExtensions
|
|||||||
var particles = ParticleSystemExtensions.GetParticleArray(size);
|
var particles = ParticleSystemExtensions.GetParticleArray(size);
|
||||||
_particleSystem.GetParticles(particles, size);
|
_particleSystem.GetParticles(particles, size);
|
||||||
|
|
||||||
// Resolusion resolver:
|
// Resolution resolver:
|
||||||
// (psPos / scale) / (prevPsPos / prevScale) -> psPos * scale.inv * prevPsPos.inv * prevScale
|
// (psPos / scale) / (prevPsPos / prevScale) -> psPos * scale.inv * prevPsPos.inv * prevScale
|
||||||
var modifier = psPos.GetScaled(
|
var modifier = psPos.GetScaled(
|
||||||
scale.Inverse(),
|
scale.Inverse(),
|
||||||
@@ -625,11 +622,11 @@ namespace Coffee.UIExtensions
|
|||||||
? Time.unscaledDeltaTime
|
? Time.unscaledDeltaTime
|
||||||
: Time.deltaTime;
|
: Time.deltaTime;
|
||||||
|
|
||||||
// Prewarm:
|
// Pre-warm:
|
||||||
if (0 < deltaTime && _prewarm)
|
if (0 < deltaTime && _preWarm)
|
||||||
{
|
{
|
||||||
deltaTime += main.duration;
|
deltaTime += main.duration;
|
||||||
_prewarm = false;
|
_preWarm = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// get world position.
|
// get world position.
|
||||||
|
|||||||
@@ -39,8 +39,9 @@ namespace Coffee.UIExtensions
|
|||||||
|
|
||||||
#if UNITY_EDITOR
|
#if UNITY_EDITOR
|
||||||
[InitializeOnLoadMethod]
|
[InitializeOnLoadMethod]
|
||||||
|
#else
|
||||||
|
[RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.BeforeSceneLoad)]
|
||||||
#endif
|
#endif
|
||||||
[RuntimeInitializeOnLoadMethod]
|
|
||||||
private static void InitializeOnLoad()
|
private static void InitializeOnLoad()
|
||||||
{
|
{
|
||||||
Canvas.willRenderCanvases -= Refresh;
|
Canvas.willRenderCanvases -= Refresh;
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
"name": "com.coffee.ui-particle",
|
"name": "com.coffee.ui-particle",
|
||||||
"displayName": "UI Particle",
|
"displayName": "UI Particle",
|
||||||
"description": "This package provides a component to render particle effects for uGUI.\nThe particle rendering is maskable and sortable, without the need for an extra Camera, RenderTexture, or Canvas.",
|
"description": "This package provides a component to render particle effects for uGUI.\nThe particle rendering is maskable and sortable, without the need for an extra Camera, RenderTexture, or Canvas.",
|
||||||
"version": "4.7.2",
|
"version": "4.8.0",
|
||||||
"unity": "2018.2",
|
"unity": "2018.2",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"repository": {
|
"repository": {
|
||||||
|
|||||||
Reference in New Issue
Block a user