feat: UIParticle no longer inherits from MaskableGraphic
BREAKING CHANGE: Some members inherited from MaskableGraphic will no longer be available.
parent
a3e725fd5a
commit
acebfb27f6
|
@ -2,7 +2,6 @@ using System.Collections.Generic;
|
|||
using System.Linq;
|
||||
using System.Text.RegularExpressions;
|
||||
using UnityEditor;
|
||||
using UnityEditor.UI;
|
||||
using UnityEditorInternal;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
|
@ -18,6 +17,7 @@ using Object = UnityEngine.Object;
|
|||
|
||||
#if UNITY_2021_2_OR_NEWER
|
||||
using UnityEditor.SceneManagement;
|
||||
|
||||
#elif UNITY_2018_3_OR_NEWER
|
||||
using UnityEditor.Experimental.SceneManagement;
|
||||
#endif
|
||||
|
@ -26,7 +26,7 @@ namespace Coffee.UIExtensions
|
|||
{
|
||||
[CustomEditor(typeof(UIParticle))]
|
||||
[CanEditMultipleObjects]
|
||||
internal class UIParticleEditor : GraphicEditor
|
||||
internal class UIParticleEditor : Editor
|
||||
{
|
||||
#if UNITY_2021_2_OR_NEWER
|
||||
#if UNITY_2022_1_OR_NEWER
|
||||
|
@ -146,10 +146,8 @@ namespace Coffee.UIExtensions
|
|||
/// <summary>
|
||||
/// This function is called when the object becomes enabled and active.
|
||||
/// </summary>
|
||||
protected override void OnEnable()
|
||||
private void OnEnable()
|
||||
{
|
||||
base.OnEnable();
|
||||
|
||||
_maskable = serializedObject.FindProperty("m_Maskable");
|
||||
_scale3D = serializedObject.FindProperty("m_Scale3D");
|
||||
_animatableProperties = serializedObject.FindProperty("m_AnimatableProperties");
|
||||
|
@ -529,9 +527,7 @@ namespace Coffee.UIExtensions
|
|||
{
|
||||
if (!p || (ignoreCurrent && target == p)) return;
|
||||
|
||||
var cr = p.canvasRenderer;
|
||||
DestroyImmediate(p);
|
||||
DestroyImmediate(cr);
|
||||
|
||||
#if UNITY_2018_3_OR_NEWER
|
||||
var stage = PrefabStageUtility.GetCurrentPrefabStage();
|
||||
|
|
|
@ -6,7 +6,6 @@ using UnityEngine;
|
|||
using UnityEngine.EventSystems;
|
||||
using UnityEngine.Rendering;
|
||||
using UnityEngine.Serialization;
|
||||
using UnityEngine.UI;
|
||||
using Random = UnityEngine.Random;
|
||||
|
||||
[assembly: InternalsVisibleTo("Coffee.UIParticle.Editor")]
|
||||
|
@ -19,7 +18,7 @@ namespace Coffee.UIExtensions
|
|||
[ExecuteAlways]
|
||||
[RequireComponent(typeof(RectTransform))]
|
||||
[RequireComponent(typeof(CanvasRenderer))]
|
||||
public class UIParticle : MaskableGraphic, ISerializationCallbackReceiver
|
||||
public class UIParticle : UIBehaviour, ISerializationCallbackReceiver
|
||||
{
|
||||
public enum AutoScalingMode
|
||||
{
|
||||
|
@ -45,16 +44,19 @@ namespace Coffee.UIExtensions
|
|||
|
||||
[HideInInspector]
|
||||
[SerializeField]
|
||||
[Obsolete]
|
||||
internal bool m_IsTrail;
|
||||
|
||||
[HideInInspector]
|
||||
[FormerlySerializedAs("m_IgnoreParent")]
|
||||
[SerializeField]
|
||||
[Obsolete]
|
||||
private bool m_IgnoreCanvasScaler;
|
||||
|
||||
[HideInInspector]
|
||||
[SerializeField]
|
||||
private bool m_AbsoluteMode;
|
||||
[Obsolete]
|
||||
internal bool m_AbsoluteMode;
|
||||
|
||||
[Tooltip("Particle effect scale")]
|
||||
[SerializeField]
|
||||
|
@ -93,25 +95,54 @@ namespace Coffee.UIExtensions
|
|||
|
||||
[SerializeField]
|
||||
[Tooltip("Prevent the root-Canvas scale from affecting the hierarchy-scaled ParticleSystem.")]
|
||||
private bool m_AutoScaling = true;
|
||||
[Obsolete]
|
||||
internal bool m_AutoScaling;
|
||||
|
||||
[SerializeField]
|
||||
[Tooltip("Transform: Transform.lossyScale (=world scale) will be set to (1, 1, 1)." +
|
||||
"UIParticle: UIParticle.scale will be adjusted.")]
|
||||
private AutoScalingMode m_AutoScalingMode = AutoScalingMode.Transform;
|
||||
|
||||
[SerializeField]
|
||||
private bool m_Maskable = true;
|
||||
|
||||
private readonly List<UIParticleRenderer> _renderers = new List<UIParticleRenderer>();
|
||||
private Canvas _canvas;
|
||||
private int _groupId;
|
||||
private Camera _orthoCamera;
|
||||
private DrivenRectTransformTracker _tracker;
|
||||
|
||||
/// <summary>
|
||||
/// Should this graphic be considered a target for ray-casting?
|
||||
/// </summary>
|
||||
public override bool raycastTarget
|
||||
public RectTransform rectTransform => transform as RectTransform;
|
||||
|
||||
public Canvas canvas
|
||||
{
|
||||
get => false;
|
||||
set { }
|
||||
get
|
||||
{
|
||||
if (_canvas) return _canvas;
|
||||
|
||||
var tr = transform;
|
||||
while (tr && !_canvas)
|
||||
{
|
||||
if (tr.TryGetComponent(out _canvas)) return _canvas;
|
||||
tr = tr.parent;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Does this graphic allow masking.
|
||||
/// </summary>
|
||||
public bool maskable
|
||||
{
|
||||
get => m_Maskable;
|
||||
set
|
||||
{
|
||||
if (value == m_Maskable) return;
|
||||
m_Maskable = value;
|
||||
UpdateRendererMaterial();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -266,8 +297,6 @@ namespace Coffee.UIExtensions
|
|||
}
|
||||
}
|
||||
|
||||
public override Material materialForRendering => null;
|
||||
|
||||
/// <summary>
|
||||
/// Paused.
|
||||
/// </summary>
|
||||
|
@ -282,8 +311,8 @@ namespace Coffee.UIExtensions
|
|||
ResetGroupId();
|
||||
UpdateTracker();
|
||||
UIParticleUpdater.Register(this);
|
||||
RegisterDirtyMaterialCallback(UpdateRendererMaterial);
|
||||
|
||||
//
|
||||
if (0 < particles.Count)
|
||||
{
|
||||
RefreshParticles(particles);
|
||||
|
@ -293,7 +322,7 @@ namespace Coffee.UIExtensions
|
|||
RefreshParticles();
|
||||
}
|
||||
|
||||
base.OnEnable();
|
||||
UpdateRendererMaterial();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -304,9 +333,15 @@ namespace Coffee.UIExtensions
|
|||
UpdateTracker();
|
||||
UIParticleUpdater.Unregister(this);
|
||||
_renderers.ForEach(r => r.Reset());
|
||||
UnregisterDirtyMaterialCallback(UpdateRendererMaterial);
|
||||
_canvas = null;
|
||||
}
|
||||
|
||||
base.OnDisable();
|
||||
/// <summary>
|
||||
/// Called when the state of the parent Canvas is changed.
|
||||
/// </summary>
|
||||
protected override void OnCanvasHierarchyChanged()
|
||||
{
|
||||
_canvas = null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -316,11 +351,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()
|
||||
{
|
||||
_canvas = null;
|
||||
}
|
||||
|
||||
#if UNITY_EDITOR
|
||||
protected override void OnValidate()
|
||||
{
|
||||
base.OnValidate();
|
||||
UpdateTracker();
|
||||
UpdateRendererMaterial();
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -330,6 +374,7 @@ namespace Coffee.UIExtensions
|
|||
|
||||
void ISerializationCallbackReceiver.OnAfterDeserialize()
|
||||
{
|
||||
#pragma warning disable CS0612 // Type or member is obsolete
|
||||
if (m_IgnoreCanvasScaler || m_AutoScaling)
|
||||
{
|
||||
m_IgnoreCanvasScaler = false;
|
||||
|
@ -342,6 +387,7 @@ namespace Coffee.UIExtensions
|
|||
m_AbsoluteMode = false;
|
||||
m_PositionMode = PositionMode.Absolute;
|
||||
}
|
||||
#pragma warning restore CS0612 // Type or member is obsolete
|
||||
}
|
||||
|
||||
public void Play()
|
||||
|
@ -400,9 +446,10 @@ namespace Coffee.UIExtensions
|
|||
{
|
||||
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;
|
||||
go.SetActive(false);
|
||||
if (destroyOldParticles)
|
||||
{
|
||||
|
@ -433,7 +480,14 @@ namespace Coffee.UIExtensions
|
|||
{
|
||||
if (!root) return;
|
||||
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++)
|
||||
{
|
||||
|
@ -448,31 +502,39 @@ namespace Coffee.UIExtensions
|
|||
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
|
||||
_renderers.Clear();
|
||||
foreach (Transform child in transform)
|
||||
var childCount = transform.childCount;
|
||||
for (var i = 0; i < childCount; i++)
|
||||
{
|
||||
var uiParticleRenderer = child.GetComponent<UIParticleRenderer>();
|
||||
|
||||
if (uiParticleRenderer != null)
|
||||
var child = transform.GetChild(i);
|
||||
if (child.TryGetComponent(out UIParticleRenderer uiParticleRenderer))
|
||||
{
|
||||
_renderers.Add(uiParticleRenderer);
|
||||
}
|
||||
}
|
||||
|
||||
// Reset the UIParticleRenderer components.
|
||||
for (var i = 0; i < _renderers.Count; i++)
|
||||
{
|
||||
_renderers[i].Reset(i);
|
||||
}
|
||||
|
||||
// Set the ParticleSystem to the UIParticleRenderer. If the trail is enabled, set it additionally.
|
||||
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;
|
||||
GetRenderer(j++).Set(this, ps, false);
|
||||
|
||||
// If the trail is enabled, set it additionally.
|
||||
if (ps.trails.enabled)
|
||||
{
|
||||
GetRenderer(j++).Set(this, ps, true);
|
||||
|
@ -500,11 +562,10 @@ namespace Coffee.UIExtensions
|
|||
for (var i = 0; i < _renderers.Count; i++)
|
||||
{
|
||||
var r = _renderers[i];
|
||||
if (!r)
|
||||
{
|
||||
RefreshParticles(particles);
|
||||
break;
|
||||
}
|
||||
if (r) continue;
|
||||
|
||||
RefreshParticles(particles);
|
||||
break;
|
||||
}
|
||||
|
||||
var bakeCamera = GetBakeCamera();
|
||||
|
@ -512,6 +573,7 @@ namespace Coffee.UIExtensions
|
|||
{
|
||||
var r = _renderers[i];
|
||||
if (!r) continue;
|
||||
|
||||
r.UpdateMesh(bakeCamera);
|
||||
}
|
||||
}
|
||||
|
@ -523,17 +585,6 @@ namespace Coffee.UIExtensions
|
|||
: Random.Range(m_GroupId, m_GroupMaxId + 1);
|
||||
}
|
||||
|
||||
protected override void UpdateMaterial()
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Call to update the geometry of the Graphic onto the CanvasRenderer.
|
||||
/// </summary>
|
||||
protected override void UpdateGeometry()
|
||||
{
|
||||
}
|
||||
|
||||
private void UpdateRendererMaterial()
|
||||
{
|
||||
for (var i = 0; i < _renderers.Count; i++)
|
||||
|
@ -574,11 +625,12 @@ namespace Coffee.UIExtensions
|
|||
// When render mode is ScreenSpaceOverlay, use ortho-camera.
|
||||
if (!_orthoCamera)
|
||||
{
|
||||
// Find existing ortho-camera.
|
||||
foreach (Transform child in transform)
|
||||
// Find existing orthographic-camera.
|
||||
var childCount = transform.childCount;
|
||||
for (var i = 0; i < childCount; i++)
|
||||
{
|
||||
var cam = child.GetComponent<Camera>();
|
||||
if (cam && cam.name == "[generated] UIParticleOverlayCamera")
|
||||
if (transform.GetChild(i).TryGetComponent<Camera>(out var cam)
|
||||
&& cam.name == "[generated] UIParticleOverlayCamera")
|
||||
{
|
||||
_orthoCamera = cam;
|
||||
break;
|
||||
|
@ -600,8 +652,7 @@ namespace Coffee.UIExtensions
|
|||
}
|
||||
|
||||
//
|
||||
var size = ((RectTransform)root.transform).rect.size;
|
||||
_orthoCamera.orthographicSize = Mathf.Max(size.x, size.y) * root.scaleFactor;
|
||||
_orthoCamera.orthographicSize = 10;
|
||||
_orthoCamera.transform.SetPositionAndRotation(new Vector3(0, 0, -1000), Quaternion.identity);
|
||||
_orthoCamera.orthographic = true;
|
||||
_orthoCamera.farClipPlane = 2000f;
|
||||
|
@ -612,7 +663,7 @@ namespace Coffee.UIExtensions
|
|||
private void UpdateTracker()
|
||||
{
|
||||
#pragma warning disable CS0618 // Type or member is obsolete
|
||||
if (!enabled || !autoScaling || autoScalingMode != AutoScalingMode.Transform)
|
||||
if (!enabled || autoScalingMode != AutoScalingMode.Transform)
|
||||
#pragma warning restore CS0618 // Type or member is obsolete
|
||||
{
|
||||
_tracker.Clear();
|
||||
|
|
|
@ -33,6 +33,7 @@ namespace Coffee.UIExtensions
|
|||
private int _index;
|
||||
private bool _isTrail;
|
||||
private Bounds _lastBounds;
|
||||
private Material _materialForRendering;
|
||||
private Material _modifiedMaterial;
|
||||
private UIParticle _parent;
|
||||
private ParticleSystem _particleSystem;
|
||||
|
@ -91,6 +92,19 @@ namespace Coffee.UIExtensions
|
|||
}
|
||||
}
|
||||
|
||||
public override Material materialForRendering
|
||||
{
|
||||
get
|
||||
{
|
||||
if (!_materialForRendering)
|
||||
{
|
||||
_materialForRendering = base.materialForRendering;
|
||||
}
|
||||
|
||||
return _materialForRendering;
|
||||
}
|
||||
}
|
||||
|
||||
public void Reset(int index = -1)
|
||||
{
|
||||
if (_renderer)
|
||||
|
@ -110,8 +124,7 @@ namespace Coffee.UIExtensions
|
|||
if (this && isActiveAndEnabled)
|
||||
{
|
||||
material = null;
|
||||
workerMesh.Clear();
|
||||
canvasRenderer.SetMesh(workerMesh);
|
||||
canvasRenderer.Clear();
|
||||
_lastBounds = new Bounds();
|
||||
enabled = false;
|
||||
}
|
||||
|
@ -202,10 +215,11 @@ namespace Coffee.UIExtensions
|
|||
);
|
||||
if (!MaterialRepository.Valid(hash, _modifiedMaterial))
|
||||
{
|
||||
MaterialRepository.Get(hash, ref _modifiedMaterial, () => new Material(modifiedMaterial)
|
||||
MaterialRepository.Get(hash, ref _modifiedMaterial, x => new Material(x.mat)
|
||||
{
|
||||
hideFlags = HideFlags.HideAndDontSave
|
||||
});
|
||||
hideFlags = HideFlags.HideAndDontSave,
|
||||
mainTexture = x.texture ? x.texture : x.mat.mainTexture
|
||||
}, (mat: modifiedMaterial, texture));
|
||||
}
|
||||
|
||||
return _modifiedMaterial;
|
||||
|
@ -232,7 +246,7 @@ namespace Coffee.UIExtensions
|
|||
}
|
||||
}
|
||||
|
||||
_renderer = ps.GetComponent<ParticleSystemRenderer>();
|
||||
ps.TryGetComponent(out _renderer);
|
||||
_renderer.enabled = false;
|
||||
|
||||
//_emitter = emitter;
|
||||
|
@ -424,66 +438,49 @@ namespace Coffee.UIExtensions
|
|||
|
||||
Profiler.EndSample();
|
||||
|
||||
// Update animatable material properties.
|
||||
Profiler.BeginSample("[UIParticleRenderer] Update Animatable Material Properties");
|
||||
UpdateMaterialProperties();
|
||||
Profiler.EndSample();
|
||||
|
||||
// Get grouped renderers.
|
||||
Profiler.BeginSample("[UIParticleRenderer] Set Mesh");
|
||||
s_Renderers.Clear();
|
||||
if (_parent.useMeshSharing)
|
||||
{
|
||||
UIParticleUpdater.GetGroupedRenderers(_parent.groupId, _index, s_Renderers);
|
||||
}
|
||||
|
||||
// Set mesh to the CanvasRenderer.
|
||||
Profiler.BeginSample("[UIParticleRenderer] Set Mesh");
|
||||
for (var i = 0; i < s_Renderers.Count; i++)
|
||||
{
|
||||
if (s_Renderers[i] == this) continue;
|
||||
|
||||
s_Renderers[i].canvasRenderer.SetMesh(workerMesh);
|
||||
s_Renderers[i]._lastBounds = _lastBounds;
|
||||
s_Renderers[i].canvasRenderer.materialCount = 1;
|
||||
s_Renderers[i].canvasRenderer.SetMaterial(materialForRendering, 0);
|
||||
}
|
||||
|
||||
if (!_parent.canRender)
|
||||
if (_parent.canRender)
|
||||
{
|
||||
canvasRenderer.SetMesh(workerMesh);
|
||||
}
|
||||
else
|
||||
{
|
||||
workerMesh.Clear();
|
||||
}
|
||||
|
||||
canvasRenderer.SetMesh(workerMesh);
|
||||
Profiler.EndSample();
|
||||
|
||||
// Update animatable material properties.
|
||||
Profiler.BeginSample("[UIParticleRenderer] Update Animatable Material Properties");
|
||||
|
||||
#if UNITY_EDITOR
|
||||
if (_modifiedMaterial != material)
|
||||
{
|
||||
_renderer.GetSharedMaterials(s_Materials);
|
||||
material = s_Materials[_isTrail ? 1 : 0];
|
||||
s_Materials.Clear();
|
||||
SetMaterialDirty();
|
||||
}
|
||||
#endif
|
||||
|
||||
UpdateMaterialProperties();
|
||||
if (_parent.useMeshSharing)
|
||||
{
|
||||
if (!_currentMaterialForRendering)
|
||||
{
|
||||
_currentMaterialForRendering = materialForRendering;
|
||||
}
|
||||
|
||||
for (var i = 0; i < s_Renderers.Count; i++)
|
||||
{
|
||||
if (s_Renderers[i] == this) continue;
|
||||
|
||||
s_Renderers[i].canvasRenderer.materialCount = 1;
|
||||
s_Renderers[i].canvasRenderer.SetMaterial(_currentMaterialForRendering, 0);
|
||||
}
|
||||
}
|
||||
|
||||
Profiler.EndSample();
|
||||
|
||||
s_Renderers.Clear();
|
||||
}
|
||||
|
||||
public override void SetMaterialDirty()
|
||||
{
|
||||
_materialForRendering = null;
|
||||
base.SetMaterialDirty();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Call to update the geometry of the Graphic onto the CanvasRenderer.
|
||||
/// </summary>
|
||||
|
@ -687,12 +684,12 @@ namespace Coffee.UIExtensions
|
|||
if (s_Mpb.isEmpty) return;
|
||||
|
||||
// #41: Copy the value from MaterialPropertyBlock to CanvasRenderer
|
||||
if (!_modifiedMaterial) return;
|
||||
if (!materialForRendering) return;
|
||||
|
||||
for (var i = 0; i < _parent.m_AnimatableProperties.Length; i++)
|
||||
{
|
||||
var ap = _parent.m_AnimatableProperties[i];
|
||||
ap.UpdateMaterialProperties(_modifiedMaterial, s_Mpb);
|
||||
ap.UpdateMaterialProperties(materialForRendering, s_Mpb);
|
||||
}
|
||||
|
||||
s_Mpb.Clear();
|
||||
|
|
Loading…
Reference in New Issue