diff --git a/.releaserc b/.releaserc deleted file mode 100644 index e69de29..0000000 diff --git a/CHANGELOG.md b/CHANGELOG.md index a3cab20..303b7cf 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,17 @@ +# [3.0.0-preview.38](https://github.com/mob-sakai/ParticleEffectForUGUI/compare/v3.0.0-preview.37...v3.0.0-preview.38) (2020-10-04) + + +### Bug Fixes + +* delete unused file in package ([2e69974](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/2e699749a8f0f620505621a13a628aa87f192875)) +* material dirty on validate (on editor) ([fa34301](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/fa3430130cdffa3f934e926645958ad9f19edc5d)) + + +### Features + +* display material properties in inspector ([313c1fc](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/313c1fc159429034f84b2e7c30424158c43b71e9)), closes [#104](https://github.com/mob-sakai/ParticleEffectForUGUI/issues/104) +* support 3D scaling ([a508c3b](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/a508c3bb86ad6694722868303385b20adc914134)), closes [#105](https://github.com/mob-sakai/ParticleEffectForUGUI/issues/105) + # [3.0.0-preview.37](https://github.com/mob-sakai/ParticleEffectForUGUI/compare/v3.0.0-preview.36...v3.0.0-preview.37) (2020-10-01) diff --git a/README.md b/README.md index 1df8db4..e659cdf 100644 --- a/README.md +++ b/README.md @@ -121,7 +121,8 @@ Unity 2018.2 supports embedded packages. 1. Open `Package Manager` window 2. Select `UI Particle` package in package list -3. Click `Import Sample` button +3. Click `Import Sample` button +![demo](https://user-images.githubusercontent.com/12690315/95017806-83bd1480-0696-11eb-8c24-c56f45ab1ac2.png) 4. The demo project is imported into `Assets/Samples/UI Particle/{version}/Demo` 5. Open `UIParticle_Demo` scene and play it @@ -137,22 +138,58 @@ Unity 2018.2 supports embedded packages. ## Usage +### UIParticle component + +`UIParticle` controls the ParticleSystems that is attached to its own game objects and child game objects. + +| Properties | Screenshot | +| -- | -- | +| **Ignore Canvas Scale:** Ignore the scale of the root canvas. This prevents it from displaying small even in hierarchy scaling mode of ParticleSystem.
**Scale:** Scale the rendering. When the `3D` toggle is enabled, 3D scale (x,y,z) is supported.
**AnimatableProperties:** If you want update material properties (e.g. `_MainTex_ST`, `_Color`) in AnimationClip, use this to mark the changes.
**Rendering Order:** The ParticleSystems to be rendered. You can change the rendering order and the materials. | ![][inspector] | + +[inspector]:https://user-images.githubusercontent.com/12690315/95017219-1cea2c00-0693-11eb-9490-c52b8d0fdbb6.png + +NOTE: Press `Refresh` button to reconstruct rendering order based on children ParticleSystem's sorting order and z position. + +

+ ### Basically usage -1. Select `Game Object/UI/ParticleSystem` to create UIParticle. -2. (Option) If you want to mask particles, set **a UI shader** such as `UI/UIAdditive` to material for ParticleSystem. -![](https://user-images.githubusercontent.com/12690315/42674022-134e3a40-86a9-11e8-8f44-a110d2f14185.gif) -3. Adjust the Scale property to change the size of the effect. -![](https://user-images.githubusercontent.com/12690315/49148937-19c1de80-f34c-11e8-87fc-138192777540.gif) +1. Select `Game Object/UI/ParticleSystem` to create UIParticle with a ParticleSystem. +![particle](https://user-images.githubusercontent.com/12690315/95007361-cad0e880-0649-11eb-8835-f145d62c5977.png) +2. Adjust the ParticleSystem as you like. +![particle1](https://user-images.githubusercontent.com/12690315/95007359-ca385200-0649-11eb-8383-627c9750bda8.png) -### With VFX assets +

-1. Select `Game Object/UI/ParticleSystem (Empty)` to create UIParticle. -2. Drag & drop VFX asset on UIParticle. -3. Click `Refresh` to setup. -4. Adjust the Scale property to change the size of the effect. +### With your ParticleSystem prefab + +1. Select `Game Object/UI/ParticleSystem (Empty)` to create UIParticle. +![empty](https://user-images.githubusercontent.com/12690315/95007362-cb697f00-0649-11eb-8a09-29b0a13791e4.png) +2. Drag & drop your ParticleSystem prefab on UIParticle. +![particle3](https://user-images.githubusercontent.com/12690315/95007356-c6a4cb00-0649-11eb-9316-562f4bce3f31.png) + +

+ +### With `Mask` or `MaskRect2D` component + +If you want to mask particles, set a stencil supported shader (such as `UI/UIAdditive`) to material for ParticleSystem. + +![](https://user-images.githubusercontent.com/12690315/95017591-3b512700-0695-11eb-864e-04166ea1809a.png) +

+ +### Script usage + +```cs +// Instant ParticleSystem prefab with UIParticle on runtime. +var go = GameObject.Instantiate(prefab); +var uiParticle = go.AddComponent(); + +// Play/Stop the controled ParticleSystems. +uiParticle.Play(); +uiParticle.Stop(); +```



@@ -224,5 +261,4 @@ With your support, I can spend more time on development. :) * GitHub page : https://github.com/mob-sakai/ParticleEffectForUGUI * Releases : https://github.com/mob-sakai/ParticleEffectForUGUI/releases * Issue tracker : https://github.com/mob-sakai/ParticleEffectForUGUI/issues -* Current project : https://github.com/mob-sakai/ParticleEffectForUGUI/projects/1 * Change log : https://github.com/mob-sakai/ParticleEffectForUGUI/blob/upm/CHANGELOG.md diff --git a/Scripts/Editor/UIParticleEditor.cs b/Scripts/Editor/UIParticleEditor.cs index 5f41458..cc4ce86 100644 --- a/Scripts/Editor/UIParticleEditor.cs +++ b/Scripts/Editor/UIParticleEditor.cs @@ -18,6 +18,10 @@ namespace Coffee.UIExtensions private static readonly GUIContent s_ContentRenderingOrder = new GUIContent("Rendering Order"); private static readonly GUIContent s_ContentRefresh = new GUIContent("Refresh"); 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_ContentScale = new GUIContent("Scale"); private static readonly List s_TempParents = new List(); private static readonly List s_TempChildren = new List(); @@ -26,6 +30,7 @@ namespace Coffee.UIExtensions private SerializedProperty _spAnimatableProperties; private ReorderableList _ro; + private bool _xyzMode; private static readonly List s_MaskablePropertyNames = new List { @@ -47,24 +52,48 @@ namespace Coffee.UIExtensions protected override void OnEnable() { base.OnEnable(); - _spScale = serializedObject.FindProperty("m_Scale"); + _spScale = serializedObject.FindProperty("m_Scale3D"); _spIgnoreCanvasScaler = serializedObject.FindProperty("m_IgnoreCanvasScaler"); _spAnimatableProperties = serializedObject.FindProperty("m_AnimatableProperties"); var sp = serializedObject.FindProperty("m_Particles"); - _ro = new ReorderableList(sp.serializedObject, sp, true, true, false, false); - _ro.elementHeight = EditorGUIUtility.singleLineHeight + 4; + _ro = new ReorderableList(sp.serializedObject, sp, true, true, true, true); + _ro.elementHeight = EditorGUIUtility.singleLineHeight * 3 + 4; _ro.drawElementCallback = (rect, index, active, focused) => { + EditorGUI.BeginDisabledGroup(sp.hasMultipleDifferentValues); rect.y += 1; rect.height = EditorGUIUtility.singleLineHeight; - EditorGUI.ObjectField(rect, sp.GetArrayElementAtIndex(index), GUIContent.none); + var p = sp.GetArrayElementAtIndex(index); + EditorGUI.ObjectField(rect, p, GUIContent.none); + + rect.x += 15; + rect.width -= 15; + var ps = p.objectReferenceValue as ParticleSystem; + var materials = ps + ? new SerializedObject(ps.GetComponent()).FindProperty("m_Materials") + : null; + rect.y += rect.height + 1; + MaterialField(rect, s_ContentMaterial, materials, 0); + rect.y += rect.height + 1; + MaterialField(rect, s_ContentTrailMaterial, materials, 1); + EditorGUI.EndDisabledGroup(); + if (materials != null) + { + materials.serializedObject.ApplyModifiedProperties(); + } }; _ro.drawHeaderCallback += rect => { EditorGUI.LabelField(new Rect(rect.x, rect.y, 150, rect.height), s_ContentRenderingOrder); - if (GUI.Button(new Rect(rect.width - 80, rect.y - 1, 80, rect.height), s_ContentRefresh, EditorStyles.miniButton)) + #if UNITY_2019_3_OR_NEWER + rect = new Rect(rect.width - 55, rect.y, 80, rect.height); + #else + rect = new Rect(rect.width - 55, rect.y - 1, 80, rect.height); + #endif + + if (GUI.Button(rect, s_ContentRefresh, EditorStyles.miniButton)) { foreach (UIParticle t in targets) { @@ -74,6 +103,20 @@ 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); + } + } + /// /// Implement this function to make a custom inspector. /// @@ -98,7 +141,7 @@ namespace Coffee.UIExtensions } // Scale - EditorGUILayout.PropertyField(_spScale); + _xyzMode = DrawFloatOrVector3Field(_spScale, _xyzMode); // AnimatableProperties var mats = current.particles @@ -106,8 +149,17 @@ namespace Coffee.UIExtensions .Select(x => x.GetComponent().sharedMaterial) .Where(x => x) .ToArray(); - AnimatedPropertiesEditor.DrawAnimatableProperties(_spAnimatableProperties, mats); + // Animated properties + EditorGUI.BeginChangeCheck(); + AnimatedPropertiesEditor.DrawAnimatableProperties(_spAnimatableProperties, mats); + if (EditorGUI.EndChangeCheck()) + { + foreach (UIParticle t in targets) + t.SetMaterialDirty(); + } + + // Target ParticleSystems. _ro.DoLayoutList(); serializedObject.ApplyModifiedProperties(); @@ -180,5 +232,42 @@ namespace Coffee.UIExtensions } } } + + private static bool DrawFloatOrVector3Field(SerializedProperty sp, bool showXyz) + { + var x = sp.FindPropertyRelative("x"); + var y = sp.FindPropertyRelative("y"); + var z = sp.FindPropertyRelative("z"); + + showXyz |= !Mathf.Approximately(x.floatValue, y.floatValue) || + !Mathf.Approximately(y.floatValue, z.floatValue) || + y.hasMultipleDifferentValues || + z.hasMultipleDifferentValues; + + EditorGUILayout.BeginHorizontal(); + if (showXyz) + { + EditorGUILayout.PropertyField(sp); + } + else + { + EditorGUI.BeginChangeCheck(); + EditorGUILayout.PropertyField(x, s_ContentScale); + if (EditorGUI.EndChangeCheck()) + z.floatValue = y.floatValue = x.floatValue; + } + + x.floatValue = Mathf.Max(0.001f, x.floatValue); + y.floatValue = Mathf.Max(0.001f, y.floatValue); + z.floatValue = Mathf.Max(0.001f, z.floatValue); + + EditorGUI.BeginChangeCheck(); + showXyz = GUILayout.Toggle(showXyz, s_Content3D, EditorStyles.miniButton, GUILayout.Width(30)); + if (EditorGUI.EndChangeCheck() && !showXyz) + z.floatValue = y.floatValue = x.floatValue; + EditorGUILayout.EndHorizontal(); + + return showXyz; + } } } diff --git a/Scripts/UIParticle.cs b/Scripts/UIParticle.cs index 04db9ca..995166f 100755 --- a/Scripts/UIParticle.cs +++ b/Scripts/UIParticle.cs @@ -30,6 +30,9 @@ namespace Coffee.UIExtensions [Tooltip("Particle effect scale")] [SerializeField] float m_Scale = 100; + [Tooltip("Particle effect scale")] [SerializeField] + private Vector3 m_Scale3D; + [Tooltip("Animatable material properties. If you want to change the material properties of the ParticleSystem in Animation, enable it.")] [SerializeField] internal AnimatableProperty[] m_AnimatableProperties = new AnimatableProperty[0]; @@ -74,8 +77,27 @@ namespace Coffee.UIExtensions /// public float scale { - get { return m_Scale; } - set { m_Scale = Mathf.Max(0.001f, value); } + get { return m_Scale3D.x; } + set + { + m_Scale = Mathf.Max(0.001f, value); + m_Scale3D = new Vector3(m_Scale, m_Scale, m_Scale); + } + } + + /// + /// Particle effect scale. + /// + public Vector3 scale3D + { + get { return m_Scale3D; } + set + { + if (m_Scale3D == value) return; + m_Scale3D.x = Mathf.Max(0.001f, value.x); + m_Scale3D.y = Mathf.Max(0.001f, value.y); + m_Scale3D.z = Mathf.Max(0.001f, value.z); + } } internal Mesh bakedMesh @@ -410,6 +432,14 @@ namespace Coffee.UIExtensions } #if UNITY_EDITOR + protected override void OnValidate() + { + SetLayoutDirty(); + SetVerticesDirty(); + m_ShouldRecalculateStencil = true; + RecalculateClipping(); + } + void ISerializationCallbackReceiver.OnBeforeSerialize() { if (Application.isPlaying) return; @@ -418,6 +448,11 @@ namespace Coffee.UIExtensions void ISerializationCallbackReceiver.OnAfterDeserialize() { + if (m_Scale3D == Vector3.zero) + { + scale = m_Scale; + } + UnityEditor.EditorApplication.delayCall += () => { if (Application.isPlaying || !this) return; diff --git a/Scripts/UIParticleUpdater.cs b/Scripts/UIParticleUpdater.cs index 6eee462..3fc0391 100755 --- a/Scripts/UIParticleUpdater.cs +++ b/Scripts/UIParticleUpdater.cs @@ -138,13 +138,17 @@ namespace Coffee.UIExtensions var rootMatrix = Matrix4x4.Rotate(root.rotation).inverse * Matrix4x4.Scale(root.lossyScale).inverse; var scale = particle.ignoreCanvasScaler - ? particle.canvas.rootCanvas.transform.localScale.x * particle.scale - : particle.scale; - var scaleMatrix = Matrix4x4.Scale(scale * Vector3.one); + ? Vector3.Scale( particle.canvas.rootCanvas.transform.localScale, particle.scale3D) + : particle.scale3D; + var scaleMatrix = Matrix4x4.Scale(scale); // Cache position var position = particle.transform.position; - var diff = (position - particle.cachedPosition) * (1 - 1 / scale); + var diff = position - particle.cachedPosition; + diff.x *= 1f - 1f / Mathf.Max(0.001f, scale.x); + diff.y *= 1f - 1f / Mathf.Max(0.001f, scale.y); + diff.z *= 1f - 1f / Mathf.Max(0.001f, scale.z); + particle.cachedPosition = position; for (var i = 0; i < particle.particles.Count; i++) diff --git a/package.json b/package.json index f9445e1..df38495 100644 --- a/package.json +++ b/package.json @@ -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": "3.0.0-preview.37", + "version": "3.0.0-preview.38", "unity": "2018.2", "license": "MIT", "repository": {