You've already forked ParticleEffectForUGUI
mirror of
https://github.com/mob-sakai/ParticleEffectForUGUI.git
synced 2026-05-15 04:30:09 +00:00
Compare commits
9 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
888eac4e54 | ||
|
|
f6e64c325b | ||
|
|
beb6fa8367 | ||
|
|
6c2ed22e3a | ||
|
|
4c260061c8 | ||
|
|
fb2904160e | ||
|
|
7696451ac9 | ||
|
|
54098eea56 | ||
|
|
79bbc4de95 |
26
CHANGELOG.md
26
CHANGELOG.md
@@ -1,13 +1,31 @@
|
||||
# Changelog
|
||||
|
||||
## [v2.2.1](https://github.com/mob-sakai/ParticleEffectForUGUI/tree/v2.2.1) (2019-02-26)
|
||||
|
||||
[Full Changelog](https://github.com/mob-sakai/ParticleEffectForUGUI/compare/v2.2.0...v2.2.1)
|
||||
|
||||
**Fixed bugs:**
|
||||
|
||||
- v2.2.0 has 2 warnings [\#44](https://github.com/mob-sakai/ParticleEffectForUGUI/issues/44)
|
||||
- Disable ParticleSystemRenderer on reset [\#45](https://github.com/mob-sakai/ParticleEffectForUGUI/issues/45)
|
||||
|
||||
## [v2.2.0](https://github.com/mob-sakai/ParticleEffectForUGUI/tree/v2.2.0) (2019-02-23)
|
||||
|
||||
[Full Changelog](https://github.com/mob-sakai/ParticleEffectForUGUI/compare/v2.1.1...v2.2.0)
|
||||
|
||||
**Implemented enhancements:**
|
||||
|
||||
- Display warning when material does not support Mask [\#43](https://github.com/mob-sakai/ParticleEffectForUGUI/issues/43)
|
||||
- Support changing material property by AnimationClip [\#42](https://github.com/mob-sakai/ParticleEffectForUGUI/issues/42)
|
||||
|
||||
**Fixed bugs:**
|
||||
|
||||
- UV Animation is not work. [\#41](https://github.com/mob-sakai/ParticleEffectForUGUI/issues/41)
|
||||
|
||||
## [v2.1.1](https://github.com/mob-sakai/ParticleEffectForUGUI/tree/v2.1.1) (2019-02-15)
|
||||
|
||||
[Full Changelog](https://github.com/mob-sakai/ParticleEffectForUGUI/compare/v2.1.0...v2.1.1)
|
||||
|
||||
**Fixed bugs:**
|
||||
|
||||
- UIParticle.Scale - Rendering Order Issue [\#39](https://github.com/mob-sakai/ParticleEffectForUGUI/issues/39)
|
||||
|
||||
## [v2.1.0](https://github.com/mob-sakai/ParticleEffectForUGUI/tree/v2.1.0) (2019-02-07)
|
||||
|
||||
[Full Changelog](https://github.com/mob-sakai/ParticleEffectForUGUI/compare/v2.0.0...v2.1.0)
|
||||
|
||||
22
README.md
22
README.md
@@ -55,6 +55,8 @@ Compares this "Baking mesh" approach with the conventional approach:
|
||||

|
||||
* Scaled gizmo
|
||||

|
||||
* Animatable material property
|
||||

|
||||
|
||||
|
||||
|
||||
@@ -74,12 +76,13 @@ Find the manifest.json file in the Packages folder of your project and edit it t
|
||||
```js
|
||||
{
|
||||
"dependencies": {
|
||||
"com.coffee.ui-particle": "https://github.com/mob-sakai/ParticleEffectForUGUI.git#2.1.0",
|
||||
"com.coffee.ui-particle": "https://github.com/mob-sakai/ParticleEffectForUGUI.git#2.2.1",
|
||||
...
|
||||
},
|
||||
}
|
||||
```
|
||||
To update the package, change `#{version}` to the target version.
|
||||
To update the package, change `#{version}` to the target version.
|
||||
Or, use [UpmGitExtension](https://github.com/mob-sakai/UpmGitExtension).
|
||||
|
||||
#### Using .unitypackage file (for Unity 2018.2+)
|
||||
|
||||
@@ -124,6 +127,21 @@ Select `Assets > Import Package > Custom Package` from the menu.
|
||||
<br><br><br><br>
|
||||
## Development Note
|
||||
|
||||
#### Animatable material property
|
||||
|
||||

|
||||
|
||||
Animation clips can change the material properties of the Renderer, such as ParticleSystemRenderer.
|
||||
It uses MaterialPropertyBlock so it does not create new material instances.
|
||||
Using material properties, you can change UV animation, scale and color etc.
|
||||
|
||||
Well, there is a component called CanvasRenderer.
|
||||
It is used by all Graphic components for UI (Text, Image, Raw Image, etc.) including UIParticle.
|
||||
However, It is **NOT** a Renderer.
|
||||
Therefore, in UIParticle, changing ParticleSystemRenderer's MaterialPropertyBlock by animation clip is ignored.
|
||||
|
||||
To prevent this, Use "Animatable Material Property".
|
||||
"Animatable Material Property" gets the necessary properties from ParticleSystemRenderer's MaterialPropertyBlock and sets them to the CanvasRenderer's material.
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -6,6 +6,7 @@ using System.Linq;
|
||||
using UnityEditor.IMGUI.Controls;
|
||||
using System;
|
||||
using System.Reflection;
|
||||
using ShaderPropertyType = Coffee.UIExtensions.UIParticle.AnimatableProperty.ShaderPropertyType;
|
||||
|
||||
namespace Coffee.UIExtensions
|
||||
{
|
||||
@@ -13,6 +14,108 @@ namespace Coffee.UIExtensions
|
||||
[CanEditMultipleObjects]
|
||||
public class UIParticleEditor : GraphicEditor
|
||||
{
|
||||
class AnimatedPropertiesEditor
|
||||
{
|
||||
static readonly List<string> s_ActiveNames = new List<string> ();
|
||||
static readonly System.Text.StringBuilder s_Sb = new System.Text.StringBuilder ();
|
||||
|
||||
public string name;
|
||||
public ShaderPropertyType type;
|
||||
|
||||
static string CollectActiveNames (SerializedProperty sp, List<string> result)
|
||||
{
|
||||
result.Clear ();
|
||||
for (int i = 0; i < sp.arraySize; i++)
|
||||
{
|
||||
result.Add (sp.GetArrayElementAtIndex (i).FindPropertyRelative ("m_Name").stringValue);
|
||||
}
|
||||
|
||||
s_Sb.Length = 0;
|
||||
if (result.Count == 0)
|
||||
{
|
||||
s_Sb.Append ("Nothing");
|
||||
}
|
||||
else
|
||||
{
|
||||
result.Aggregate (s_Sb, (a, b) => s_Sb.AppendFormat ("{0}, ", b));
|
||||
s_Sb.Length -= 2;
|
||||
}
|
||||
|
||||
return s_Sb.ToString ();
|
||||
}
|
||||
|
||||
public static void DrawAnimatableProperties (SerializedProperty sp, Material mat)
|
||||
{
|
||||
if (!mat || !mat.shader)
|
||||
return;
|
||||
bool isClicked = false;
|
||||
using (new EditorGUILayout.HorizontalScope (GUILayout.ExpandWidth (false)))
|
||||
{
|
||||
var r = EditorGUI.PrefixLabel (EditorGUILayout.GetControlRect (true), new GUIContent (sp.displayName, sp.tooltip));
|
||||
isClicked = GUI.Button (r, CollectActiveNames (sp, s_ActiveNames), EditorStyles.popup);
|
||||
}
|
||||
|
||||
if (isClicked)
|
||||
{
|
||||
GenericMenu gm = new GenericMenu ();
|
||||
gm.AddItem (new GUIContent ("Nothing"), s_ActiveNames.Count == 0, () =>
|
||||
{
|
||||
sp.ClearArray ();
|
||||
sp.serializedObject.ApplyModifiedProperties ();
|
||||
});
|
||||
|
||||
|
||||
for (int i = 0; i < sp.arraySize; i++)
|
||||
{
|
||||
var p = sp.GetArrayElementAtIndex (i);
|
||||
var name = p.FindPropertyRelative ("m_Name").stringValue;
|
||||
var type = (ShaderPropertyType)p.FindPropertyRelative ("m_Type").intValue;
|
||||
AddMenu (gm, sp, new AnimatedPropertiesEditor () { name = name, type = type }, false);
|
||||
}
|
||||
|
||||
for (int i = 0; i < ShaderUtil.GetPropertyCount (mat.shader); i++)
|
||||
{
|
||||
var pName = ShaderUtil.GetPropertyName (mat.shader, i);
|
||||
var type = (ShaderPropertyType)ShaderUtil.GetPropertyType (mat.shader, i);
|
||||
AddMenu (gm, sp, new AnimatedPropertiesEditor () { name = pName, type = type }, true);
|
||||
|
||||
if (type == ShaderPropertyType.Texture)
|
||||
{
|
||||
AddMenu (gm, sp, new AnimatedPropertiesEditor () { name = pName + "_ST", type = ShaderPropertyType.Vector }, true);
|
||||
AddMenu (gm, sp, new AnimatedPropertiesEditor () { name = pName + "_HDR", type = ShaderPropertyType.Vector }, true);
|
||||
AddMenu (gm, sp, new AnimatedPropertiesEditor () { name = pName + "_TexelSize", type = ShaderPropertyType.Vector }, true);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
gm.ShowAsContext ();
|
||||
}
|
||||
}
|
||||
|
||||
public static void AddMenu (GenericMenu menu, SerializedProperty sp, AnimatedPropertiesEditor property, bool add)
|
||||
{
|
||||
if (add && s_ActiveNames.Contains (property.name))
|
||||
return;
|
||||
|
||||
menu.AddItem (new GUIContent (string.Format ("{0} ({1})", property.name, property.type)), s_ActiveNames.Contains (property.name), () =>
|
||||
{
|
||||
var index = s_ActiveNames.IndexOf (property.name);
|
||||
if (0 <= index)
|
||||
{
|
||||
sp.DeleteArrayElementAtIndex (index);
|
||||
}
|
||||
else
|
||||
{
|
||||
sp.InsertArrayElementAtIndex (sp.arraySize);
|
||||
var p = sp.GetArrayElementAtIndex (sp.arraySize - 1);
|
||||
p.FindPropertyRelative ("m_Name").stringValue = property.name;
|
||||
p.FindPropertyRelative ("m_Type").intValue = (int)property.type;
|
||||
}
|
||||
sp.serializedObject.ApplyModifiedProperties ();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
//################################
|
||||
// Constant or Static Members.
|
||||
//################################
|
||||
@@ -25,6 +128,15 @@ namespace Coffee.UIExtensions
|
||||
static readonly Color s_ShapeGizmoThicknessTint = new Color (0.7f, 0.7f, 0.7f, 1.0f);
|
||||
static Material s_Material;
|
||||
|
||||
static readonly List<string> s_MaskablePropertyNames = new List<string> ()
|
||||
{
|
||||
"_Stencil",
|
||||
"_StencilComp",
|
||||
"_StencilOp",
|
||||
"_StencilWriteMask",
|
||||
"_StencilReadMask",
|
||||
"_ColorMask",
|
||||
};
|
||||
|
||||
//################################
|
||||
// Public/Protected Members.
|
||||
@@ -39,6 +151,7 @@ namespace Coffee.UIExtensions
|
||||
_spTrailParticle = serializedObject.FindProperty ("m_TrailParticle");
|
||||
_spScale = serializedObject.FindProperty ("m_Scale");
|
||||
_spIgnoreParent = serializedObject.FindProperty ("m_IgnoreParent");
|
||||
_spAnimatableProperties = serializedObject.FindProperty ("m_AnimatableProperties");
|
||||
|
||||
if (!s_Material)
|
||||
{
|
||||
@@ -86,6 +199,9 @@ namespace Coffee.UIExtensions
|
||||
EditorGUILayout.PropertyField (_spScale);
|
||||
EditorGUI.EndDisabledGroup ();
|
||||
|
||||
// AnimatableProperties
|
||||
AnimatedPropertiesEditor.DrawAnimatableProperties (_spAnimatableProperties, current.material);
|
||||
|
||||
current.GetComponentsInChildren<ParticleSystem> (true, s_ParticleSystems);
|
||||
if (s_ParticleSystems.Any (x => x.GetComponent<UIParticle> () == null))
|
||||
{
|
||||
@@ -104,9 +220,28 @@ namespace Coffee.UIExtensions
|
||||
}
|
||||
s_ParticleSystems.Clear ();
|
||||
|
||||
if (current.maskable && current.material && current.material.shader)
|
||||
{
|
||||
var mat = current.material;
|
||||
var shader = mat.shader;
|
||||
foreach (var propName in s_MaskablePropertyNames)
|
||||
{
|
||||
if (!mat.HasProperty (propName))
|
||||
{
|
||||
EditorGUILayout.HelpBox (string.Format ("Shader {0} doesn't have '{1}' property. This graphic is not maskable.", shader.name, propName), MessageType.Warning);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
serializedObject.ApplyModifiedProperties ();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//################################
|
||||
// Private Members.
|
||||
//################################
|
||||
@@ -114,6 +249,7 @@ namespace Coffee.UIExtensions
|
||||
SerializedProperty _spTrailParticle;
|
||||
SerializedProperty _spScale;
|
||||
SerializedProperty _spIgnoreParent;
|
||||
SerializedProperty _spAnimatableProperties;
|
||||
UIParticle [] _particles;
|
||||
ArcHandle _arcHandle = new ArcHandle ();
|
||||
BoxBoundsHandle _boxBoundsHandle = new BoxBoundsHandle ();
|
||||
@@ -174,7 +310,7 @@ namespace Coffee.UIExtensions
|
||||
transformMatrix *= emitterMatrix;
|
||||
Handles.matrix = transformMatrix;
|
||||
|
||||
if(uip.canvas.renderMode == RenderMode.ScreenSpaceOverlay || ps.main.scalingMode == ParticleSystemScalingMode.Hierarchy)
|
||||
if (uip.canvas.renderMode == RenderMode.ScreenSpaceOverlay || ps.main.scalingMode == ParticleSystemScalingMode.Hierarchy)
|
||||
{
|
||||
Handles.matrix = Handles.matrix * Matrix4x4.Scale (Vector3.one * uip.scale);
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@ using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Profiling;
|
||||
using UnityEngine.UI;
|
||||
using ShaderPropertyType = Coffee.UIExtensions.UIParticle.AnimatableProperty.ShaderPropertyType;
|
||||
|
||||
|
||||
namespace Coffee.UIExtensions
|
||||
@@ -35,6 +36,42 @@ namespace Coffee.UIExtensions
|
||||
[Tooltip ("Ignore parent scale")]
|
||||
[SerializeField] bool m_IgnoreParent = false;
|
||||
|
||||
[Tooltip ("Animatable material properties. AnimationでParticleSystemのマテリアルプロパティを変更する場合、有効にしてください。")]
|
||||
[SerializeField] AnimatableProperty [] m_AnimatableProperties = new AnimatableProperty [0];
|
||||
|
||||
static MaterialPropertyBlock s_Mpb;
|
||||
|
||||
[System.Serializable]
|
||||
public class AnimatableProperty : ISerializationCallbackReceiver
|
||||
{
|
||||
public enum ShaderPropertyType
|
||||
{
|
||||
Color,
|
||||
Vector,
|
||||
Float,
|
||||
Range,
|
||||
Texture,
|
||||
};
|
||||
|
||||
[SerializeField]
|
||||
string m_Name = "";
|
||||
[SerializeField]
|
||||
ShaderPropertyType m_Type = ShaderPropertyType.Vector;
|
||||
public int id { get; private set; }
|
||||
public ShaderPropertyType type { get { return m_Type; } }
|
||||
|
||||
|
||||
public void OnBeforeSerialize ()
|
||||
{
|
||||
}
|
||||
|
||||
public void OnAfterDeserialize ()
|
||||
{
|
||||
id = Shader.PropertyToID (m_Name);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
//################################
|
||||
// Public/Protected Members.
|
||||
@@ -57,9 +94,7 @@ namespace Coffee.UIExtensions
|
||||
if (!tex && _renderer)
|
||||
{
|
||||
Profiler.BeginSample ("Check material");
|
||||
var mat = m_IsTrail
|
||||
? _renderer.trailMaterial
|
||||
: _renderer.sharedMaterial;
|
||||
var mat = material;
|
||||
if (mat && mat.HasProperty (s_IdMainTex))
|
||||
{
|
||||
tex = mat.mainTexture;
|
||||
@@ -70,6 +105,35 @@ namespace Coffee.UIExtensions
|
||||
}
|
||||
}
|
||||
|
||||
public override Material material
|
||||
{
|
||||
get
|
||||
{
|
||||
return _renderer
|
||||
? m_IsTrail
|
||||
? _renderer.trailMaterial
|
||||
: _renderer.sharedMaterial
|
||||
: null;
|
||||
}
|
||||
|
||||
set
|
||||
{
|
||||
if (!_renderer)
|
||||
{
|
||||
}
|
||||
else if (m_IsTrail && _renderer.trailMaterial != value)
|
||||
{
|
||||
_renderer.trailMaterial = value;
|
||||
SetMaterialDirty ();
|
||||
}
|
||||
else if (!m_IsTrail && _renderer.sharedMaterial != value)
|
||||
{
|
||||
_renderer.sharedMaterial = value;
|
||||
SetMaterialDirty ();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Particle effect scale.
|
||||
/// </summary>
|
||||
@@ -117,7 +181,15 @@ namespace Coffee.UIExtensions
|
||||
/// <param name="baseMaterial">Configured Material.</param>
|
||||
public override Material GetModifiedMaterial (Material baseMaterial)
|
||||
{
|
||||
return base.GetModifiedMaterial (_renderer ? _renderer.sharedMaterial : baseMaterial);
|
||||
Material mat = null;
|
||||
if (!_renderer)
|
||||
mat = baseMaterial;
|
||||
else if (m_AnimatableProperties.Length == 0)
|
||||
mat = _renderer.sharedMaterial;
|
||||
else
|
||||
mat = new Material (material);
|
||||
|
||||
return base.GetModifiedMaterial (mat);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -129,6 +201,7 @@ namespace Coffee.UIExtensions
|
||||
if (s_ActiveParticles.Count == 0)
|
||||
{
|
||||
Canvas.willRenderCanvases += UpdateMeshes;
|
||||
s_Mpb = new MaterialPropertyBlock ();
|
||||
}
|
||||
s_ActiveParticles.Add (this);
|
||||
|
||||
@@ -182,6 +255,21 @@ namespace Coffee.UIExtensions
|
||||
base.OnDisable ();
|
||||
}
|
||||
|
||||
#if UNITY_EDITOR
|
||||
/// <summary>
|
||||
/// Reset to default values.
|
||||
/// </summary>
|
||||
protected override void Reset ()
|
||||
{
|
||||
// Disable ParticleSystemRenderer on reset.
|
||||
if (cachedParticleSystem)
|
||||
{
|
||||
cachedParticleSystem.GetComponent<ParticleSystemRenderer> ().enabled = false;
|
||||
}
|
||||
base.Reset ();
|
||||
}
|
||||
#endif
|
||||
|
||||
/// <summary>
|
||||
/// Call to update the geometry of the Graphic onto the CanvasRenderer.
|
||||
/// </summary>
|
||||
@@ -369,6 +457,10 @@ namespace Coffee.UIExtensions
|
||||
Profiler.BeginSample ("Set mesh and texture to CanvasRenderer");
|
||||
canvasRenderer.SetMesh (_mesh);
|
||||
canvasRenderer.SetTexture (mainTexture);
|
||||
|
||||
// Copy the value from MaterialPropertyBlock to CanvasRenderer (#41)
|
||||
UpdateAnimatableMaterialProperties ();
|
||||
|
||||
Profiler.EndSample ();
|
||||
}
|
||||
}
|
||||
@@ -427,5 +519,43 @@ namespace Coffee.UIExtensions
|
||||
_parent._children.Add (this);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Copy the value from MaterialPropertyBlock to CanvasRenderer (#41)
|
||||
/// </summary>
|
||||
void UpdateAnimatableMaterialProperties ()
|
||||
{
|
||||
#if UNITY_EDITOR
|
||||
if (!Application.isPlaying)
|
||||
return;
|
||||
#endif
|
||||
if (0 == m_AnimatableProperties.Length)
|
||||
return;
|
||||
|
||||
_renderer.GetPropertyBlock (s_Mpb);
|
||||
for (int i = 0; i < canvasRenderer.materialCount; i++)
|
||||
{
|
||||
var mat = canvasRenderer.GetMaterial (i);
|
||||
foreach (var ap in m_AnimatableProperties)
|
||||
{
|
||||
switch (ap.type)
|
||||
{
|
||||
case ShaderPropertyType.Color:
|
||||
mat.SetColor (ap.id, s_Mpb.GetColor (ap.id));
|
||||
break;
|
||||
case ShaderPropertyType.Vector:
|
||||
mat.SetVector (ap.id, s_Mpb.GetVector (ap.id));
|
||||
break;
|
||||
case ShaderPropertyType.Float:
|
||||
case ShaderPropertyType.Range:
|
||||
mat.SetFloat (ap.id, s_Mpb.GetFloat (ap.id));
|
||||
break;
|
||||
case ShaderPropertyType.Texture:
|
||||
mat.SetTexture (ap.id, s_Mpb.GetTexture (ap.id));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -77,7 +77,7 @@
|
||||
v2f OUT;
|
||||
OUT.worldPosition = IN.vertex;
|
||||
OUT.vertex = UnityObjectToClipPos(IN.vertex);
|
||||
OUT.texcoord = IN.texcoord;
|
||||
OUT.texcoord = TRANSFORM_TEX(IN.texcoord, _MainTex);
|
||||
#ifdef UNITY_HALF_TEXEL_OFFSET
|
||||
OUT.vertex.xy += (_ScreenParams.zw-1.0)*float2(-1,1);
|
||||
#endif
|
||||
|
||||
Binary file not shown.
@@ -2,7 +2,7 @@
|
||||
"name": "com.coffee.ui-particle",
|
||||
"displayName": "UI Particle",
|
||||
"description": "This plugin provide a component to render particle effect for uGUI.\nThe particle rendering is maskable and sortable, without Camera, RenderTexture or Canvas.",
|
||||
"version": "2.1.1",
|
||||
"version": "2.2.1",
|
||||
"unity": "2018.2",
|
||||
"license": "MIT",
|
||||
"repository": {
|
||||
|
||||
Reference in New Issue
Block a user