Compare commits

...

11 Commits

Author SHA1 Message Date
semantic-release-bot
18175c040e chore(release): 4.12.2 [skip ci]
## [4.12.2](https://github.com/mob-sakai/ParticleEffectForUGUI/compare/v4.12.1...v4.12.2) (2026-06-08)

### Bug Fixes

* add `meshCleared` flag to optimize mesh clearing ([859fa20](859fa20d29))
* fix Unity6.5 compile errors and warnings ([a5ee687](a5ee687821)), closes [#400](https://github.com/mob-sakai/ParticleEffectForUGUI/issues/400)
* potential access to UIParticleRenderer that has already been destroyed ([b740dd6](b740dd662d)), closes [#403](https://github.com/mob-sakai/ParticleEffectForUGUI/issues/403)
* updated support for some changed menu paths ([f8ac986](f8ac9869f1)), closes [#397](https://github.com/mob-sakai/ParticleEffectForUGUI/issues/397)
2026-06-08 13:33:41 +00:00
mob-sakai
9cd47c32bc chore: ignore alpha for test 2026-06-08 22:33:03 +09:00
mob-sakai
48b38ec34f update internal code 2026-06-08 15:55:42 +09:00
mob-sakai
b740dd662d fix: potential access to UIParticleRenderer that has already been destroyed
close #403
2026-06-08 13:28:24 +09:00
tako
f8ac9869f1 fix: updated support for some changed menu paths
close #397
2026-06-08 13:28:24 +09:00
tako
a5ee687821 fix: fix Unity6.5 compile errors and warnings
close #400
2026-06-08 13:28:24 +09:00
Minhyuk Kim
859fa20d29 fix: add meshCleared flag to optimize mesh clearing 2026-06-08 11:33:57 +09:00
semantic-release-bot
d89d394e04 chore(release): 4.12.1 [skip ci]
## [4.12.1](https://github.com/mob-sakai/ParticleEffectForUGUI/compare/v4.12.0...v4.12.1) (2026-03-24)

### Bug Fixes

* ignore "EditorOnly" tagged gameObjects on refresh ([031d46a](031d46a321))
2026-03-24 08:53:33 +00:00
mob-sakai
031d46a321 fix: ignore "EditorOnly" tagged gameObjects on refresh 2026-03-24 17:53:01 +09:00
semantic-release-bot
af0e98239b chore(release): 4.12.0 [skip ci]
# [4.12.0](https://github.com/mob-sakai/ParticleEffectForUGUI/compare/v4.11.4...v4.12.0) (2026-03-24)

### Features

* explicit null checks ([5384f61](5384f61c56))
2026-03-24 08:34:58 +00:00
mob-sakai
5384f61c56 feat: explicit null checks 2026-03-24 17:32:31 +09:00
31 changed files with 334 additions and 151 deletions

6
.github/CODEOWNERS vendored Normal file
View File

@@ -0,0 +1,6 @@
# This is a comment.
# Each line is a file pattern followed by one or more owners.
# https://docs.github.com/ja/repositories/managing-your-repositorys-settings-and-features/customizing-your-repository/about-code-owners
# Default owners
* @mob-sakai

12
.github/FUNDING.yml vendored Normal file
View File

@@ -0,0 +1,12 @@
# These are supported funding model platforms
github: mob-sakai # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2]
patreon: mob_sakai # Replace with a single Patreon username
open_collective: # Replace with a single Open Collective username
ko_fi: # Replace with a single Ko-fi username
tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel
community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry
liberapay: # Replace with a single Liberapay username
issuehunt: # Replace with a single IssueHunt username
otechie: # Replace with a single Otechie username
custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2']

35
.github/ISSUE_TEMPLATE/bug_report.md vendored Normal file
View File

@@ -0,0 +1,35 @@
---
name: Bug report
about: Create a report to help us improve
title: ''
labels: bug
assignees: mob-sakai
---
NOTE: Your issue may already be reported! Please search on the [issue tracker](../) before creating one.
**Describe the bug**
A clear and concise description of what the bug is.
**To Reproduce**
Steps to reproduce the behavior:
1. Go to '...'
2. Click on '....'
3. Scroll down to '....'
4. See error
**Expected behavior**
A clear and concise description of what you expected to happen.
**Screenshots**
If applicable, add screenshots to help explain your problem.
**Environment (please complete the following information):**
- Version [e.g. 1.0.0]
- Platform: [e.g. Editor(Windows/Mac), Standalone(Windows/Mac), iOS, Android, WebGL]
- Unity version: [e.g. 2018.2.8f1]
- Build options: [e.g. IL2CPP, .Net 4.x, LWRP]
**Additional context**
Add any other context about the problem here.

View File

@@ -0,0 +1,22 @@
---
name: Feature request
about: Suggest an idea for this project
title: ''
labels: enhancement
assignees: mob-sakai
---
NOTE: Your issue may already be reported! Please search on the [issue tracker](../) before creating one.
**Is your feature request related to a problem? Please describe.**
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
**Describe the solution you'd like**
A clear and concise description of what you want to happen.
**Describe alternatives you've considered**
A clear and concise description of any alternative solutions or features you've considered.
**Additional context**
Add any other context or screenshots about the feature request here.

16
.github/ISSUE_TEMPLATE/question.md vendored Normal file
View File

@@ -0,0 +1,16 @@
---
name: Question
about: Ask a question about this project
title: ''
labels: question
assignees: mob-sakai
---
NOTE: Your issue may already be reported! Please search on the [issue tracker](../) before creating one.
**Describe what help do you need**
A description of the question.
**Additional context**
Add any other context or screenshots about the question here.

37
.github/pull_request_template.md vendored Normal file
View File

@@ -0,0 +1,37 @@
# Pull Request Template
## Description
- Please include a summary of the change and which issue is fixed.
- Please also include relevant motivation and context.
- List any dependencies that are required for this change.
Fixes #{issue_number}
## Type of change
Please write the commit message in the format corresponding to the change type.
Please see [Conventional Commits](https://www.conventionalcommits.org/en/v1.0.0/) for more information.
- [ ] Bug fix (non-breaking change which fixes an issue)
- [ ] New feature (non-breaking change which adds functionality)
- [ ] Breaking change (fix or feature that would cause existing functionality to not work as expected)
- [ ] Update documentations
- [ ] Others (refactoring, style changes, etc.)
## Test environment
- Platform: [e.g. Editor(Windows/Mac), Standalone(Windows/Mac), iOS, Android, WebGL]
- Unity version: [e.g. 2022.2.0f1]
- Build options: [e.g. IL2CPP, .Net 4.x, URP/HDRP]
## Checklist
- [ ] This pull request is for merging into the `develop` branch
- [ ] My code follows the style guidelines of this project
- [ ] I have performed a self-review of my own code
- [ ] I have commented my code, particularly in hard-to-understand areas
- [ ] I have made corresponding changes to the documentation
- [ ] My changes generate no new warnings
- [ ] I have checked my code and corrected any misspellings

View File

@@ -27,10 +27,10 @@ jobs:
split_to: ${{ steps.summary.outputs.split_to }} split_to: ${{ steps.summary.outputs.split_to }}
steps: steps:
- name: 🚚 Checkout (${{ github.ref_name }}) - name: 🚚 Checkout (${{ github.ref_name }})
uses: actions/checkout@v5 uses: actions/checkout@v6
- name: 🔖 Run semantic release - name: 🔖 Run semantic release
uses: cycjimmy/semantic-release-action@v5 uses: cycjimmy/semantic-release-action@v6
id: release id: release
with: with:
working_directory: Packages/src working_directory: Packages/src

View File

@@ -7,9 +7,9 @@ run-name: 🧪 Test (${{ github.event.pull_request.title || github.ref_name }})
env: env:
# MINIMUM_VERSION: The minimum version of Unity. # MINIMUM_VERSION: The minimum version of Unity.
MINIMUM_VERSION: 2019.4 MINIMUM_VERSION: 2020.3
# EXCLUDE_FILTER: The excluded versions of Unity. # EXCLUDE_FILTER: The excluded versions of Unity.
EXCLUDE_FILTER: "(2020.2.0|2021.1|2023.3)" EXCLUDE_FILTER: "(2017|2018|2023.3)"
PROJECT_PATH: . PROJECT_PATH: .
on: on:
@@ -46,9 +46,9 @@ jobs:
id: setup id: setup
run: | run: |
echo "==== Target Unity Versions ====" echo "==== Target Unity Versions ===="
LATEST_VERSIONS=`npx unity-changeset@latest list --versions --latest-patch --min ${MINIMUM_VERSION} --json --all` LATEST_VERSIONS=`npx unity-changeset@latest list --versions --latest-patch --min ${MINIMUM_VERSION} --json --all --ignore-alpha`
if [ "${{ inputs.usePeriodVersions }}" = "true" ]; then if [ "${{ inputs.usePeriodVersions }}" = "true" ]; then
ADDITIONAL_VERSIONS=`npx unity-changeset list --versions --grep '0f' --min ${MINIMUM_VERSION} --json` ADDITIONAL_VERSIONS=`npx unity-changeset list --versions --grep '0f' --min ${MINIMUM_VERSION} --json --ignore-alpha`
else else
ADDITIONAL_VERSIONS=[] ADDITIONAL_VERSIONS=[]
fi fi
@@ -72,11 +72,11 @@ jobs:
steps: steps:
- name: 🚚 Checkout ($${{ github.ref }}) - name: 🚚 Checkout ($${{ github.ref }})
if: github.event_name == 'push' if: github.event_name == 'push'
uses: actions/checkout@v5 uses: actions/checkout@v6
- name: 🚚 Checkout pull request (pull_request_target) - name: 🚚 Checkout pull request (pull_request_target)
if: github.event_name == 'pull_request_target' if: github.event_name == 'pull_request_target'
uses: actions/checkout@v5 uses: actions/checkout@v6
with: with:
ref: ${{ github.event.pull_request.head.sha }} ref: ${{ github.event.pull_request.head.sha }}
fetch-depth: 0 fetch-depth: 0
@@ -90,7 +90,7 @@ jobs:
git log --oneline -n 10 git log --oneline -n 10
- name: 📥 Cache library - name: 📥 Cache library
uses: actions/cache@v4 uses: actions/cache@v5
with: with:
path: ${{ env.PROJECT_PATH }}/Library path: ${{ env.PROJECT_PATH }}/Library
key: ${{ env.PROJECT_PATH }}-Library-${{ matrix.unityVersion }}-${{ github.event.pull_request.head.sha || github.sha }} key: ${{ env.PROJECT_PATH }}-Library-${{ matrix.unityVersion }}-${{ github.event.pull_request.head.sha || github.sha }}
@@ -99,7 +99,7 @@ jobs:
${{ env.PROJECT_PATH }}-Library- ${{ env.PROJECT_PATH }}-Library-
- name: 🛠️ Build Unity Project (Test) - name: 🛠️ Build Unity Project (Test)
uses: game-ci/unity-builder@main uses: game-ci/unity-builder@v5
timeout-minutes: 45 timeout-minutes: 45
with: with:
customImage: ghcr.io/mob-sakai/unity3d:${{ matrix.unityVersion }} customImage: ghcr.io/mob-sakai/unity3d:${{ matrix.unityVersion }}

View File

@@ -1,3 +1,27 @@
## [4.12.2](https://github.com/mob-sakai/ParticleEffectForUGUI/compare/v4.12.1...v4.12.2) (2026-06-08)
### Bug Fixes
* add `meshCleared` flag to optimize mesh clearing ([859fa20](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/859fa20d297c3f44e3361f20dbb7ce966407e03e))
* fix Unity6.5 compile errors and warnings ([a5ee687](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/a5ee6878212be2fc4d7b48879426f239e8753009)), closes [#400](https://github.com/mob-sakai/ParticleEffectForUGUI/issues/400)
* potential access to UIParticleRenderer that has already been destroyed ([b740dd6](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/b740dd662d423c6bef849662ce1b0bfbb4940ed4)), closes [#403](https://github.com/mob-sakai/ParticleEffectForUGUI/issues/403)
* updated support for some changed menu paths ([f8ac986](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/f8ac9869f141238169730e74f5d65c4fc6081f51)), closes [#397](https://github.com/mob-sakai/ParticleEffectForUGUI/issues/397)
## [4.12.1](https://github.com/mob-sakai/ParticleEffectForUGUI/compare/v4.12.0...v4.12.1) (2026-03-24)
### Bug Fixes
* ignore "EditorOnly" tagged gameObjects on refresh ([031d46a](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/031d46a3216c942d2d1a6ccfadf5f0b9e3ce3006))
# [4.12.0](https://github.com/mob-sakai/ParticleEffectForUGUI/compare/v4.11.4...v4.12.0) (2026-03-24)
### Features
* explicit null checks ([5384f61](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/5384f61c569e9f78ff9d5b45acfc6f5c2f021a87))
## [4.11.4](https://github.com/mob-sakai/ParticleEffectForUGUI/compare/v4.11.3...v4.11.4) (2025-12-24) ## [4.11.4](https://github.com/mob-sakai/ParticleEffectForUGUI/compare/v4.11.3...v4.11.4) (2025-12-24)

View File

@@ -76,12 +76,21 @@ namespace Coffee.UIExtensions
for (var j = 0; j < mats.Count; j++) for (var j = 0; j < mats.Count; j++)
{ {
var mat = mats[j]; var mat = mats[j];
if (!mat || !mat.shader) continue; if (mat == null || mat.shader == null) continue;
#if UNITY_6000_5_OR_NEWER
for (var i = 0; i < mat.shader.GetPropertyCount(); i++)
#else
for (var i = 0; i < ShaderUtil.GetPropertyCount(mat.shader); i++) for (var i = 0; i < ShaderUtil.GetPropertyCount(mat.shader); i++)
#endif
{ {
#if UNITY_6000_5_OR_NEWER
var name = mat.shader.GetPropertyName(i);
var type = (AnimatableProperty.ShaderPropertyType)mat.shader.GetPropertyType(i);
#else
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);
#endif
if (!s_Names.Add(name)) continue; if (!s_Names.Add(name)) continue;
AddMenu(gm, sp, new ShaderProperty(name, type), true); AddMenu(gm, sp, new ShaderProperty(name, type), true);

View File

@@ -110,7 +110,7 @@ namespace Coffee.UIExtensions
{ {
var ps = sp.GetArrayElementAtIndex(index).objectReferenceValue as ParticleSystem; var ps = sp.GetArrayElementAtIndex(index).objectReferenceValue as ParticleSystem;
var materialCount = 0; var materialCount = 0;
if (ps && ps.TryGetComponent<ParticleSystemRenderer>(out var psr)) if (ps != null && ps.TryGetComponent<ParticleSystemRenderer>(out var psr))
{ {
materialCount = psr.sharedMaterials.Length; materialCount = psr.sharedMaterials.Length;
} }
@@ -124,7 +124,7 @@ namespace Coffee.UIExtensions
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; var ps = p.objectReferenceValue as ParticleSystem;
if (!ps || !ps.TryGetComponent<ParticleSystemRenderer>(out var psr)) return; if (ps == null || !ps.TryGetComponent<ParticleSystemRenderer>(out var psr)) return;
rect.x += 15; rect.x += 15;
rect.width -= 15; rect.width -= 15;
@@ -191,7 +191,7 @@ namespace Coffee.UIExtensions
public override void OnInspectorGUI() public override void OnInspectorGUI()
{ {
var current = target as UIParticle; var current = target as UIParticle;
if (!current) return; if (current == null) return;
Profiler.BeginSample("(UIP:E) OnInspectorGUI"); Profiler.BeginSample("(UIP:E) OnInspectorGUI");
serializedObject.Update(); serializedObject.Update();
@@ -267,7 +267,7 @@ namespace Coffee.UIExtensions
Profiler.BeginSample("(UIP:E) Non-UI built-in shader is not supported."); Profiler.BeginSample("(UIP:E) Non-UI built-in shader is not supported.");
foreach (var mat in s_TempMaterials) foreach (var mat in s_TempMaterials)
{ {
if (!mat || !mat.shader) continue; if (mat == null || mat.shader == null) continue;
var shader = mat.shader; var shader = mat.shader;
if (IsBuiltInObject(shader) && !shader.name.StartsWith("UI/")) if (IsBuiltInObject(shader) && !shader.name.StartsWith("UI/"))
{ {
@@ -286,7 +286,7 @@ namespace Coffee.UIExtensions
{ {
foreach (var mat in s_TempMaterials) foreach (var mat in s_TempMaterials)
{ {
if (!mat || !mat.shader) continue; if (mat == null || mat.shader == null) continue;
var shader = mat.shader; var shader = mat.shader;
if (!s_Shaders.Add(shader)) continue; if (!s_Shaders.Add(shader)) continue;

View File

@@ -6,11 +6,22 @@ namespace Coffee.UIExtensions
{ {
internal class UIParticleMenu internal class UIParticleMenu
{ {
[MenuItem("GameObject/UI/Particle System (Empty)", false, 2018)] #if UNITY_6000_5_OR_NEWER
private const string k_MenuPathToCreateParticleSystem = "GameObject/Visual Effects/Particle System";
#else
private const string k_MenuPathToCreateParticleSystem = "GameObject/Effects/Particle System";
#endif
#if UNITY_6000_3_OR_NEWER
private const string k_MenuPathForUgui = "GameObject/UI (Canvas)";
#else
private const string k_MenuPathForUgui = "GameObject/UI";
#endif
[MenuItem(k_MenuPathForUgui + "/Particle System (Empty)", false, 2018)]
private static void AddParticleEmpty(MenuCommand menuCommand) private static void AddParticleEmpty(MenuCommand menuCommand)
{ {
// Create empty UI element. // Create empty UI element.
EditorApplication.ExecuteMenuItem("GameObject/UI/Image"); EditorApplication.ExecuteMenuItem(k_MenuPathForUgui + "/Image");
var ui = Selection.activeGameObject; var ui = Selection.activeGameObject;
Object.DestroyImmediate(ui.GetComponent<Image>()); Object.DestroyImmediate(ui.GetComponent<Image>());
@@ -21,7 +32,7 @@ namespace Coffee.UIExtensions
uiParticle.rectTransform.sizeDelta = Vector2.zero; uiParticle.rectTransform.sizeDelta = Vector2.zero;
} }
[MenuItem("GameObject/UI/Particle System", false, 2019)] [MenuItem(k_MenuPathForUgui + "/Particle System", false, 2019)]
private static void AddParticle(MenuCommand menuCommand) private static void AddParticle(MenuCommand menuCommand)
{ {
// Create empty UIEffect. // Create empty UIEffect.
@@ -29,7 +40,7 @@ namespace Coffee.UIExtensions
var uiParticle = Selection.activeGameObject.GetComponent<UIParticle>(); var uiParticle = Selection.activeGameObject.GetComponent<UIParticle>();
// Create ParticleSystem. // Create ParticleSystem.
EditorApplication.ExecuteMenuItem("GameObject/Effects/Particle System"); EditorApplication.ExecuteMenuItem(k_MenuPathToCreateParticleSystem);
var ps = Selection.activeGameObject; var ps = Selection.activeGameObject;
ps.transform.SetParent(uiParticle.transform, false); ps.transform.SetParent(uiParticle.transform, false);
ps.transform.localPosition = Vector3.zero; ps.transform.localPosition = Vector3.zero;

View File

@@ -37,37 +37,17 @@ namespace Coffee.UIExtensions
switch (type) switch (type)
{ {
case ShaderPropertyType.Color: case ShaderPropertyType.Color:
var color = mpb.GetColor(id); material.SetColor(id, mpb.GetColor(id));
if (color != default)
{
material.SetColor(id, color);
}
break; break;
case ShaderPropertyType.Vector: case ShaderPropertyType.Vector:
var vector = mpb.GetVector(id); material.SetVector(id, mpb.GetVector(id));
if (vector != default)
{
material.SetVector(id, vector);
}
break; break;
case ShaderPropertyType.Float: case ShaderPropertyType.Float:
case ShaderPropertyType.Range: case ShaderPropertyType.Range:
var value = mpb.GetFloat(id); material.SetFloat(id, mpb.GetFloat(id));
if (!Mathf.Approximately(value, 0))
{
material.SetFloat(id, value);
}
break; break;
case ShaderPropertyType.Texture: case ShaderPropertyType.Texture:
var tex = mpb.GetTexture(id); material.SetTexture(id, mpb.GetTexture(id));
if (tex != default(Texture))
{
material.SetTexture(id, tex);
}
break; break;
} }
} }

View File

@@ -38,7 +38,7 @@ namespace Coffee.UIParticleInternal
private static void GetComponentsInChildren_Internal<T>(this Component self, List<T> results, int depth) private static void GetComponentsInChildren_Internal<T>(this Component self, List<T> results, int depth)
where T : Component where T : Component
{ {
if (!self || results == null || depth < 0) return; if (self == null || results == null || depth < 0) return;
var tr = self.transform; var tr = self.transform;
if (tr.TryGetComponent<T>(out var t)) if (tr.TryGetComponent<T>(out var t))
@@ -59,7 +59,7 @@ namespace Coffee.UIParticleInternal
/// </summary> /// </summary>
public static T GetOrAddComponent<T>(this Component self) where T : Component public static T GetOrAddComponent<T>(this Component self) where T : Component
{ {
if (!self) return null; if (self == null) return null;
return self.TryGetComponent<T>(out var component) return self.TryGetComponent<T>(out var component)
? component ? component
: self.gameObject.AddComponent<T>(); : self.gameObject.AddComponent<T>();
@@ -166,7 +166,7 @@ namespace Coffee.UIParticleInternal
#if !UNITY_2021_2_OR_NEWER && !UNITY_2020_3_45 && !UNITY_2020_3_46 && !UNITY_2020_3_47 && !UNITY_2020_3_48 #if !UNITY_2021_2_OR_NEWER && !UNITY_2020_3_45 && !UNITY_2020_3_46 && !UNITY_2020_3_47 && !UNITY_2020_3_48
public static T GetComponentInParent<T>(this Component self, bool includeInactive) where T : Component public static T GetComponentInParent<T>(this Component self, bool includeInactive) where T : Component
{ {
if (!self) return null; if (self == null) return null;
if (!includeInactive) return self.GetComponentInParent<T>(); if (!includeInactive) return self.GetComponentInParent<T>();
var current = self.transform; var current = self.transform;
@@ -186,7 +186,7 @@ namespace Coffee.UIParticleInternal
/// </summary> /// </summary>
internal static bool CanConvertTo<T>(this Object context) where T : MonoBehaviour internal static bool CanConvertTo<T>(this Object context) where T : MonoBehaviour
{ {
return context && context.GetType() != typeof(T); return context != null && context.GetType() != typeof(T);
} }
/// <summary> /// <summary>

View File

@@ -32,10 +32,10 @@ namespace Coffee.UIParticleInternal
/// </summary> /// </summary>
public static Texture2D GetActualTexture(this Sprite self) public static Texture2D GetActualTexture(this Sprite self)
{ {
if (!self) return null; if (self == null) return null;
var ret = s_GetActiveAtlasTextureMethod(self); var ret = s_GetActiveAtlasTextureMethod(self);
return ret ? ret : self.texture; return ret != null ? ret : self.texture;
} }
/// <summary> /// <summary>
@@ -43,7 +43,7 @@ namespace Coffee.UIParticleInternal
/// </summary> /// </summary>
public static SpriteAtlas GetActiveAtlas(this Sprite self) public static SpriteAtlas GetActiveAtlas(this Sprite self)
{ {
if (!self) return null; if (self == null) return null;
return s_GetActiveAtlasMethod(self); return s_GetActiveAtlasMethod(self);
} }
@@ -53,7 +53,7 @@ namespace Coffee.UIParticleInternal
/// </summary> /// </summary>
internal static Texture2D GetActualTexture(this Sprite self) internal static Texture2D GetActualTexture(this Sprite self)
{ {
return self ? self.texture : null; return self != null ? self.texture : null;
} }
#endif #endif
} }

View File

@@ -37,7 +37,7 @@ namespace Coffee.UIParticleInternal
foreach (var t in TypeCache.GetTypesDerivedFrom(typeof(PreloadedProjectSettings<>))) foreach (var t in TypeCache.GetTypesDerivedFrom(typeof(PreloadedProjectSettings<>)))
{ {
var defaultSettings = GetDefaultSettings(t); var defaultSettings = GetDefaultSettings(t);
if (!defaultSettings) if (defaultSettings == null)
{ {
// When create a new instance, automatically set it as default settings. // When create a new instance, automatically set it as default settings.
defaultSettings = CreateInstance(t) as PreloadedProjectSettings; defaultSettings = CreateInstance(t) as PreloadedProjectSettings;
@@ -48,7 +48,7 @@ namespace Coffee.UIParticleInternal
SetDefaultSettings(defaultSettings); SetDefaultSettings(defaultSettings);
} }
if (defaultSettings) if (defaultSettings != null)
{ {
defaultSettings.OnInitialize(); defaultSettings.OnInitialize();
} }
@@ -66,7 +66,7 @@ namespace Coffee.UIParticleInternal
private static Object[] GetPreloadedSettings(Type type) private static Object[] GetPreloadedSettings(Type type)
{ {
return PlayerSettings.GetPreloadedAssets() return PlayerSettings.GetPreloadedAssets()
.Where(x => x && x.GetType() == type) .Where(x => x != null && x.GetType() == type)
.ToArray(); .ToArray();
} }
@@ -76,12 +76,12 @@ namespace Coffee.UIParticleInternal
?? AssetDatabase.FindAssets($"t:{nameof(PreloadedProjectSettings)}") ?? AssetDatabase.FindAssets($"t:{nameof(PreloadedProjectSettings)}")
.Select(AssetDatabase.GUIDToAssetPath) .Select(AssetDatabase.GUIDToAssetPath)
.Select(AssetDatabase.LoadAssetAtPath<PreloadedProjectSettings>) .Select(AssetDatabase.LoadAssetAtPath<PreloadedProjectSettings>)
.FirstOrDefault(x => x && x.GetType() == type); .FirstOrDefault(x => x != null && x.GetType() == type);
} }
protected static void SetDefaultSettings(PreloadedProjectSettings asset) protected static void SetDefaultSettings(PreloadedProjectSettings asset)
{ {
if (!asset) return; if (asset == null) return;
var type = asset.GetType(); var type = asset.GetType();
if (string.IsNullOrEmpty(AssetDatabase.GetAssetPath(asset))) if (string.IsNullOrEmpty(AssetDatabase.GetAssetPath(asset)))
@@ -103,7 +103,7 @@ namespace Coffee.UIParticleInternal
var preloadedAssets = PlayerSettings.GetPreloadedAssets(); var preloadedAssets = PlayerSettings.GetPreloadedAssets();
var projectSettings = GetPreloadedSettings(type); var projectSettings = GetPreloadedSettings(type);
PlayerSettings.SetPreloadedAssets(preloadedAssets PlayerSettings.SetPreloadedAssets(preloadedAssets
.Where(x => x) .Where(x => x != null)
.Except(projectSettings.Except(new[] { asset })) .Except(projectSettings.Except(new[] { asset }))
.Append(asset) .Append(asset)
.Distinct() .Distinct()
@@ -133,19 +133,19 @@ namespace Coffee.UIParticleInternal
#if UNITY_EDITOR #if UNITY_EDITOR
private string _jsonText; private string _jsonText;
public static bool hasInstance => s_Instance; public static bool hasInstance => s_Instance != null;
public static T instance public static T instance
{ {
get get
{ {
if (s_Instance) return s_Instance; if (s_Instance != null) return s_Instance;
s_Instance = GetDefaultSettings(typeof(T)) as T; s_Instance = GetDefaultSettings(typeof(T)) as T;
if (s_Instance) return s_Instance; if (s_Instance != null) return s_Instance;
s_Instance = CreateInstance<T>(); s_Instance = CreateInstance<T>();
if (!s_Instance) if (s_Instance == null)
{ {
s_Instance = null; s_Instance = null;
return s_Instance; return s_Instance;
@@ -158,6 +158,8 @@ namespace Coffee.UIParticleInternal
private void OnPlayModeStateChanged(PlayModeStateChange state) private void OnPlayModeStateChanged(PlayModeStateChange state)
{ {
if (!this) return;
switch (state) switch (state)
{ {
case PlayModeStateChange.ExitingEditMode: case PlayModeStateChange.ExitingEditMode:
@@ -174,7 +176,7 @@ namespace Coffee.UIParticleInternal
} }
} }
#else #else
public static T instance => s_Instance ? s_Instance : s_Instance = CreateInstance<T>(); public static T instance => s_Instance != null ? s_Instance : s_Instance = CreateInstance<T>();
#endif #endif
/// <summary> /// <summary>
@@ -183,7 +185,7 @@ namespace Coffee.UIParticleInternal
protected virtual void OnEnable() protected virtual void OnEnable()
{ {
#if UNITY_EDITOR #if UNITY_EDITOR
var isDefaultSettings = !s_Instance || s_Instance == this || GetDefaultSettings(typeof(T)) == this; var isDefaultSettings = s_Instance == null || s_Instance == this || GetDefaultSettings(typeof(T)) == this;
if (!isDefaultSettings) if (!isDefaultSettings)
{ {
DestroyImmediate(this, true); DestroyImmediate(this, true);
@@ -193,7 +195,7 @@ namespace Coffee.UIParticleInternal
EditorApplication.playModeStateChanged += OnPlayModeStateChanged; EditorApplication.playModeStateChanged += OnPlayModeStateChanged;
#endif #endif
if (s_Instance) return; if (s_Instance != null) return;
s_Instance = this as T; s_Instance = this as T;
} }
@@ -222,7 +224,7 @@ namespace Coffee.UIParticleInternal
public override void OnGUI(string searchContext) public override void OnGUI(string searchContext)
{ {
if (!_target) if (_target == null)
{ {
if (_editor) if (_editor)
{ {

View File

@@ -11,7 +11,7 @@ using Conditional = System.Diagnostics.ConditionalAttribute;
namespace Coffee.UIParticleInternal namespace Coffee.UIParticleInternal
{ {
internal static class Logging internal static class Logger
{ {
#if !ENABLE_COFFEE_LOGGER #if !ENABLE_COFFEE_LOGGER
private const string k_DisableSymbol = "DISABLE_COFFEE_LOGGER"; private const string k_DisableSymbol = "DISABLE_COFFEE_LOGGER";
@@ -48,7 +48,7 @@ namespace Coffee.UIParticleInternal
public static void LogIf(bool enable, object tag, object message, Object context = null) public static void LogIf(bool enable, object tag, object message, Object context = null)
{ {
if (!enable) return; if (!enable) return;
Log_Internal(LogType.Log, tag, message, context ? context : tag as Object); Log_Internal(LogType.Log, tag, message, context != null ? context : tag as Object);
} }
#if !ENABLE_COFFEE_LOGGER #if !ENABLE_COFFEE_LOGGER
@@ -56,7 +56,7 @@ namespace Coffee.UIParticleInternal
#endif #endif
public static void Log(object tag, object message, Object context = null) public static void Log(object tag, object message, Object context = null)
{ {
Log_Internal(LogType.Log, tag, message, context ? context : tag as Object); Log_Internal(LogType.Log, tag, message, context != null ? context : tag as Object);
} }
#if !ENABLE_COFFEE_LOGGER #if !ENABLE_COFFEE_LOGGER
@@ -64,13 +64,13 @@ namespace Coffee.UIParticleInternal
#endif #endif
public static void LogWarning(object tag, object message, Object context = null) public static void LogWarning(object tag, object message, Object context = null)
{ {
Log_Internal(LogType.Warning, tag, message, context ? context : tag as Object); Log_Internal(LogType.Warning, tag, message, context != null ? context : tag as Object);
} }
public static void LogError(object tag, object message, Object context = null) public static void LogError(object tag, object message, Object context = null)
{ {
#if ENABLE_COFFEE_LOGGER #if ENABLE_COFFEE_LOGGER
Log_Internal(LogType.Error, tag, message, context ? context : tag as Object); Log_Internal(LogType.Error, tag, message, context != null ? context : tag as Object);
#else #else
Debug.LogError($"{tag}: {message}", context); Debug.LogError($"{tag}: {message}", context);
#endif #endif

View File

@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 4f9f22bb079324476b1473030ad9fec3

View File

@@ -1,11 +0,0 @@
fileFormatVersion: 2
guid: 8255313895da84e7cbdc876be3795334
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -20,7 +20,9 @@ namespace Coffee.UIParticleInternal
{ {
public static T[] FindObjectsOfType<T>() where T : Object public static T[] FindObjectsOfType<T>() where T : Object
{ {
#if UNITY_2023_1_OR_NEWER #if UNITY_6000_4_OR_NEWER
return Object.FindObjectsByType<T>(FindObjectsInactive.Include);
#elif UNITY_2023_1_OR_NEWER
return Object.FindObjectsByType<T>(FindObjectsInactive.Include, FindObjectsSortMode.None); return Object.FindObjectsByType<T>(FindObjectsInactive.Include, FindObjectsSortMode.None);
#else #else
return Object.FindObjectsOfType<T>(); return Object.FindObjectsOfType<T>();
@@ -29,7 +31,7 @@ namespace Coffee.UIParticleInternal
public static void Destroy(Object obj) public static void Destroy(Object obj)
{ {
if (!obj) return; if (obj == null) return;
#if UNITY_EDITOR #if UNITY_EDITOR
if (!Application.isPlaying) if (!Application.isPlaying)
{ {
@@ -44,7 +46,7 @@ namespace Coffee.UIParticleInternal
public static void DestroyImmediate(Object obj) public static void DestroyImmediate(Object obj)
{ {
if (!obj) return; if (obj == null) return;
#if UNITY_EDITOR #if UNITY_EDITOR
if (Application.isEditor) if (Application.isEditor)
{ {
@@ -61,7 +63,7 @@ namespace Coffee.UIParticleInternal
public static void SetDirty(Object obj) public static void SetDirty(Object obj)
{ {
#if UNITY_EDITOR #if UNITY_EDITOR
if (!obj) return; if (obj == null) return;
EditorUtility.SetDirty(obj); EditorUtility.SetDirty(obj);
#endif #endif
} }
@@ -117,11 +119,11 @@ namespace Coffee.UIParticleInternal
foreach (var type in types) foreach (var type in types)
{ {
var script = scripts.FirstOrDefault(x => x.GetClass() == type); var script = scripts.FirstOrDefault(x => x.GetClass() == type);
if (!script) continue; if (script == null) continue;
var path = type.GetCustomAttribute<IconAttribute>()?._path; var path = type.GetCustomAttribute<IconAttribute>()?._path;
var icon = AssetDatabase.LoadAssetAtPath<Texture2D>(path); var icon = AssetDatabase.LoadAssetAtPath<Texture2D>(path);
if (!icon) continue; if (icon == null) continue;
s_SetIconForObject(script, icon); s_SetIconForObject(script, icon);
} }

View File

@@ -34,7 +34,7 @@ namespace Coffee.UIParticleInternal
} }
// If there are no instances in the pool, create a new one. // If there are no instances in the pool, create a new one.
Logging.Log(this, $"A new instance is created (pooled: {_pool.CountInactive}, created: {_pool.CountAll})."); Logger.Log(this, $"A new instance is created (pooled: {_pool.CountInactive}, created: {_pool.CountAll}).");
return _pool.Get(); return _pool.Get();
} }
@@ -47,7 +47,7 @@ namespace Coffee.UIParticleInternal
if (instance == null) return; // Ignore if already pooled or null. if (instance == null) return; // Ignore if already pooled or null.
_pool.Release(instance); _pool.Release(instance);
Logging.Log(this, $"An instance is released (pooled: {_pool.CountInactive}, created: {_pool.CountAll})."); Logger.Log(this, $"An instance is released (pooled: {_pool.CountInactive}, created: {_pool.CountAll}).");
instance = default; // Set the reference to null. instance = default; // Set the reference to null.
} }
#else #else
@@ -80,7 +80,7 @@ namespace Coffee.UIParticleInternal
} }
// If there are no instances in the pool, create a new one. // If there are no instances in the pool, create a new one.
Logging.Log(this, $"A new instance is created (pooled: {_pool.Count}, created: {++_count})."); Logger.Log(this, $"A new instance is created (pooled: {_pool.Count}, created: {++_count}).");
return _onCreate(); return _onCreate();
} }
@@ -94,7 +94,7 @@ namespace Coffee.UIParticleInternal
_onReturn(instance); // Return the instance to the pool. _onReturn(instance); // Return the instance to the pool.
_pool.Push(instance); _pool.Push(instance);
Logging.Log(this, $"An instance is released (pooled: {_pool.Count}, created: {_count})."); Logger.Log(this, $"An instance is released (pooled: {_pool.Count}, created: {_count}).");
instance = default; // Set the reference to null. instance = default; // Set the reference to null.
} }
#endif #endif

View File

@@ -90,7 +90,7 @@ namespace Coffee.UIParticleInternal
Profiler.BeginSample("(COF)[ObjectRepository] GetFromCache"); Profiler.BeginSample("(COF)[ObjectRepository] GetFromCache");
if (_cache.TryGetValue(hash, out var entry)) if (_cache.TryGetValue(hash, out var entry))
{ {
if (!entry.storedObject) if (entry.storedObject == null)
{ {
Release(ref entry.storedObject); Release(ref entry.storedObject);
Profiler.EndSample(); Profiler.EndSample();
@@ -103,7 +103,7 @@ namespace Coffee.UIParticleInternal
Release(ref obj); Release(ref obj);
++entry.reference; ++entry.reference;
obj = entry.storedObject; obj = entry.storedObject;
Logging.Log(_name, $"Get(total#{count}): {entry}"); Logger.Log(_name, $"Get(total#{count}): {entry}");
} }
Profiler.EndSample(); Profiler.EndSample();
@@ -116,7 +116,7 @@ namespace Coffee.UIParticleInternal
private void Add(Hash128 hash, ref T obj, T newObject) private void Add(Hash128 hash, ref T obj, T newObject)
{ {
if (!newObject) if (newObject == null)
{ {
Release(ref obj); Release(ref obj);
obj = newObject; obj = newObject;
@@ -130,8 +130,8 @@ namespace Coffee.UIParticleInternal
newEntry.hash = hash; newEntry.hash = hash;
newEntry.reference = 1; newEntry.reference = 1;
_cache[hash] = newEntry; _cache[hash] = newEntry;
_objectKey[newObject.GetInstanceID()] = hash; _objectKey[newObject.GetHashCode()] = hash;
Logging.Log(_name, $"<color=#03c700>Add</color>(total#{count}): {newEntry}"); Logger.Log(_name, $"<color=#03c700>Add</color>(total#{count}): {newEntry}");
Release(ref obj); Release(ref obj);
obj = newObject; obj = newObject;
Profiler.EndSample(); Profiler.EndSample();
@@ -146,23 +146,23 @@ namespace Coffee.UIParticleInternal
// Find and release the entry. // Find and release the entry.
Profiler.BeginSample("(COF)[ObjectRepository] Release"); Profiler.BeginSample("(COF)[ObjectRepository] Release");
var id = obj.GetInstanceID(); var id = obj.GetHashCode();
if (_objectKey.TryGetValue(id, out var hash) if (_objectKey.TryGetValue(id, out var hash)
&& _cache.TryGetValue(hash, out var entry)) && _cache.TryGetValue(hash, out var entry))
{ {
entry.reference--; entry.reference--;
if (entry.reference <= 0 || !entry.storedObject) if (entry.reference <= 0 || entry.storedObject == null)
{ {
Remove(entry); Remove(entry);
} }
else else
{ {
Logging.Log(_name, $"Release(total#{_cache.Count}): {entry}"); Logger.Log(_name, $"Release(total#{_cache.Count}): {entry}");
} }
} }
else else
{ {
Logging.Log(_name, $"Release(total#{_cache.Count}): <color=red>Already released: {obj}</color>"); Logger.Log(_name, $"Release(total#{_cache.Count}): <color=red>Already released: {obj}</color>");
} }
obj = null; obj = null;
@@ -175,10 +175,10 @@ namespace Coffee.UIParticleInternal
Profiler.BeginSample("(COF)[ObjectRepository] Remove"); Profiler.BeginSample("(COF)[ObjectRepository] Remove");
_cache.Remove(entry.hash); _cache.Remove(entry.hash);
_objectKey.Remove(entry.storedObject.GetInstanceID()); _objectKey.Remove(entry.storedObject.GetHashCode());
_pool.Push(entry); _pool.Push(entry);
entry.reference = 0; entry.reference = 0;
Logging.Log(_name, $"<color=#f29e03>Remove</color>(total#{_cache.Count}): {entry}"); Logger.Log(_name, $"<color=#f29e03>Remove</color>(total#{_cache.Count}): {entry}");
entry.Release(_onRelease); entry.Release(_onRelease);
Profiler.EndSample(); Profiler.EndSample();
} }
@@ -192,7 +192,7 @@ namespace Coffee.UIParticleInternal
public void Release(Action<T> onRelease) public void Release(Action<T> onRelease)
{ {
reference = 0; reference = 0;
if (storedObject) if (storedObject != null)
{ {
onRelease?.Invoke(storedObject); onRelease?.Invoke(storedObject);
} }

View File

@@ -1,4 +1,5 @@
using System; using System;
using System.Reflection;
using UnityEditor; using UnityEditor;
using UnityEngine; using UnityEngine;
using UnityEngine.UI; using UnityEngine.UI;
@@ -20,7 +21,7 @@ namespace Coffee.UIParticleInternal
static UIExtraCallbacks() static UIExtraCallbacks()
{ {
Canvas.willRenderCanvases += OnBeforeCanvasRebuild; Canvas.willRenderCanvases += OnBeforeCanvasRebuild;
Logging.LogMulticast(typeof(Canvas), "willRenderCanvases", message: "ctor"); Logger.LogMulticast(typeof(Canvas), "willRenderCanvases", message: "ctor");
} }
/// <summary> /// <summary>
@@ -67,9 +68,17 @@ namespace Coffee.UIParticleInternal
if (s_IsInitializedAfterCanvasRebuild) return; if (s_IsInitializedAfterCanvasRebuild) return;
s_IsInitializedAfterCanvasRebuild = true; s_IsInitializedAfterCanvasRebuild = true;
// Explicitly set `Canvas.willRenderCanvases += CanvasUpdateRegistry.PerformUpdate`.
CanvasUpdateRegistry.IsRebuildingLayout(); CanvasUpdateRegistry.IsRebuildingLayout();
#if TMP_ENABLE
// Explicitly set `Canvas.willRenderCanvases += TMP_UpdateManager.DoRebuilds`.
typeof(TMPro.TMP_UpdateManager)
.GetProperty("instance", BindingFlags.NonPublic | BindingFlags.Static)
.GetValue(null);
#endif
Canvas.willRenderCanvases -= OnAfterCanvasRebuild;
Canvas.willRenderCanvases += OnAfterCanvasRebuild; Canvas.willRenderCanvases += OnAfterCanvasRebuild;
Logging.LogMulticast(typeof(Canvas), "willRenderCanvases", Logger.LogMulticast(typeof(Canvas), "willRenderCanvases",
message: "InitializeAfterCanvasRebuild"); message: "InitializeAfterCanvasRebuild");
} }

View File

@@ -358,6 +358,7 @@ namespace Coffee.UIExtensions
_isScaleStored = false; _isScaleStored = false;
UIParticleUpdater.Unregister(this); UIParticleUpdater.Unregister(this);
_renderers.RemoveAll(r => r == null);
_renderers.ForEach(r => r.Reset()); _renderers.ForEach(r => r.Reset());
UnregisterDirtyMaterialCallback(UpdateRendererMaterial); UnregisterDirtyMaterialCallback(UpdateRendererMaterial);
@@ -471,7 +472,7 @@ 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 || !r.material) continue; if (r == null || r.material == null) continue;
result.Add(r.material); result.Add(r.material);
} }
} }
@@ -489,7 +490,7 @@ namespace Coffee.UIExtensions
/// </summary> /// </summary>
public void SetParticleSystemInstance(GameObject instance, bool destroyOldParticles) public void SetParticleSystemInstance(GameObject instance, bool destroyOldParticles)
{ {
if (!instance) return; if (instance == null) return;
var childCount = transform.childCount; var childCount = transform.childCount;
for (var i = 0; i < childCount; i++) for (var i = 0; i < childCount; i++)
@@ -518,7 +519,7 @@ namespace Coffee.UIExtensions
/// </summary> /// </summary>
public void SetParticleSystemPrefab(GameObject prefab) public void SetParticleSystemPrefab(GameObject prefab)
{ {
if (!prefab) return; if (prefab == null) return;
SetParticleSystemInstance(Instantiate(prefab.gameObject), true); SetParticleSystemInstance(Instantiate(prefab.gameObject), true);
} }
@@ -538,12 +539,14 @@ namespace Coffee.UIExtensions
/// </summary> /// </summary>
private void RefreshParticles(GameObject root) private void RefreshParticles(GameObject root)
{ {
if (!root) return; if (root == null) return;
root.GetComponentsInChildren(true, particles); root.GetComponentsInChildren(true, particles);
for (var i = particles.Count - 1; 0 <= i; i--) for (var i = particles.Count - 1; 0 <= i; i--)
{ {
var ps = particles[i]; var ps = particles[i];
if (!ps || ps.GetComponentInParent<UIParticle>(true) != this) if (!ps
|| ps.gameObject.CompareTag("EditorOnly") // Ignore "EditorOnly" tagged ParticleSystems.
|| ps.GetComponentInParent<UIParticle>(true) != this) // Ignore ParticleSystems that are not under this UIParticle.
{ {
particles.RemoveAt(i); particles.RemoveAt(i);
} }
@@ -591,7 +594,7 @@ namespace Coffee.UIExtensions
for (var i = 0; i < particleSystems.Count; i++) for (var i = 0; i < particleSystems.Count; i++)
{ {
var ps = particleSystems[i]; var ps = particleSystems[i];
if (!ps) continue; if (ps == null) continue;
var mainEmitter = ps.GetMainEmitter(particleSystems); var mainEmitter = ps.GetMainEmitter(particleSystems);
GetRenderer(j++).Set(this, ps, false, mainEmitter); GetRenderer(j++).Set(this, ps, false, mainEmitter);
@@ -642,7 +645,7 @@ 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) continue; if (r != null) continue;
RefreshParticles(particles); RefreshParticles(particles);
break; break;
@@ -652,7 +655,7 @@ 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) continue; if (r == null) continue;
r.UpdateMesh(bakeCamera); r.UpdateMesh(bakeCamera);
} }
@@ -681,7 +684,7 @@ 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) continue; if (r == null) continue;
r.maskable = maskable; r.maskable = maskable;
r.SetMaterialDirty(); r.SetMaterialDirty();
} }
@@ -694,7 +697,7 @@ namespace Coffee.UIExtensions
_renderers.Add(UIParticleRenderer.AddRenderer(this, index)); _renderers.Add(UIParticleRenderer.AddRenderer(this, index));
} }
if (!_renderers[index]) if (_renderers[index] == null)
{ {
_renderers[index] = UIParticleRenderer.AddRenderer(this, index); _renderers[index] = UIParticleRenderer.AddRenderer(this, index);
} }
@@ -704,13 +707,13 @@ namespace Coffee.UIExtensions
private Camera GetBakeCamera() private Camera GetBakeCamera()
{ {
if (!canvas) return Camera.main; if (canvas == null) return Camera.main;
if (!useCustomView && canvas.renderMode != RenderMode.ScreenSpaceOverlay && canvas.rootCanvas.worldCamera) if (!useCustomView && canvas.renderMode != RenderMode.ScreenSpaceOverlay && canvas.rootCanvas.worldCamera)
{ {
return canvas.rootCanvas.worldCamera; return canvas.rootCanvas.worldCamera;
} }
if (_bakeCamera) if (_bakeCamera != null)
{ {
_bakeCamera.orthographicSize = useCustomView ? customViewSize : 10; _bakeCamera.orthographicSize = useCustomView ? customViewSize : 10;
return _bakeCamera; return _bakeCamera;
@@ -729,7 +732,7 @@ namespace Coffee.UIExtensions
} }
// Create baking camera. // Create baking camera.
if (!_bakeCamera) if (_bakeCamera == null)
{ {
var go = new GameObject("[generated] UIParticle BakingCamera"); var go = new GameObject("[generated] UIParticle BakingCamera");
go.SetActive(false); go.SetActive(false);

View File

@@ -208,7 +208,7 @@ namespace Coffee.UIExtensions
private Vector3 GetDestinationPosition(UIParticle uiParticle, ParticleSystem particleSystem) private Vector3 GetDestinationPosition(UIParticle uiParticle, ParticleSystem particleSystem)
{ {
var isUI = uiParticle && uiParticle.enabled; var isUI = uiParticle != null && uiParticle.enabled;
var psPos = particleSystem.transform.position; var psPos = particleSystem.transform.position;
var attractorPos = transform.position; var attractorPos = transform.position;
var dstPos = attractorPos; var dstPos = attractorPos;

View File

@@ -30,6 +30,7 @@ namespace Coffee.UIExtensions
private int _index; private int _index;
private bool _isPrevStored; private bool _isPrevStored;
private bool _isTrail; private bool _isTrail;
private bool _meshCleared;
private Bounds _lastBounds; private Bounds _lastBounds;
private Material _materialForRendering; private Material _materialForRendering;
private Material _modifiedMaterial; private Material _modifiedMaterial;
@@ -55,7 +56,7 @@ namespace Coffee.UIExtensions
s_Corners[1] = transform.TransformPoint(_lastBounds.min.x, _lastBounds.max.y, 0); s_Corners[1] = transform.TransformPoint(_lastBounds.min.x, _lastBounds.max.y, 0);
s_Corners[2] = transform.TransformPoint(_lastBounds.max.x, _lastBounds.max.y, 0); s_Corners[2] = transform.TransformPoint(_lastBounds.max.x, _lastBounds.max.y, 0);
s_Corners[3] = transform.TransformPoint(_lastBounds.max.x, _lastBounds.min.y, 0); s_Corners[3] = transform.TransformPoint(_lastBounds.max.x, _lastBounds.min.y, 0);
if (canvas) if (canvas != null)
{ {
var worldToLocalMatrix = canvas.rootCanvas.transform.worldToLocalMatrix; var worldToLocalMatrix = canvas.rootCanvas.transform.worldToLocalMatrix;
for (var i = 0; i < 4; ++i) for (var i = 0; i < 4; ++i)
@@ -95,7 +96,7 @@ namespace Coffee.UIExtensions
{ {
get get
{ {
if (!_materialForRendering) if (_materialForRendering == null)
{ {
_materialForRendering = base.materialForRendering; _materialForRendering = base.materialForRendering;
} }
@@ -106,7 +107,7 @@ namespace Coffee.UIExtensions
public void Reset(int index = -1) public void Reset(int index = -1)
{ {
if (_renderer) if (_renderer != null)
{ {
_renderer.enabled = true; _renderer.enabled = true;
} }
@@ -121,7 +122,7 @@ namespace Coffee.UIExtensions
} }
//_emitter = null; //_emitter = null;
if (this && isActiveAndEnabled) if (isActiveAndEnabled)
{ {
material = null; material = null;
canvasRenderer.Clear(); canvasRenderer.Clear();
@@ -140,7 +141,7 @@ namespace Coffee.UIExtensions
base.OnEnable(); base.OnEnable();
hideFlags = UIParticleProjectSettings.globalHideFlags; hideFlags = UIParticleProjectSettings.globalHideFlags;
if (!s_CombineInstances[0].mesh) if (s_CombineInstances[0].mesh == null)
{ {
s_CombineInstances[0].mesh = new Mesh s_CombineInstances[0].mesh = new Mesh
{ {
@@ -205,9 +206,9 @@ namespace Coffee.UIExtensions
} }
var hash = new Hash128( var hash = new Hash128(
modifiedMaterial ? (uint)modifiedMaterial.GetInstanceID() : 0, modifiedMaterial ? (uint)modifiedMaterial.GetHashCode() : 0,
texture ? (uint)texture.GetInstanceID() : 0, texture ? (uint)texture.GetHashCode() : 0,
0 < _parent.m_AnimatableProperties.Length ? (uint)GetInstanceID() : 0, 0 < _parent.m_AnimatableProperties.Length ? (uint)GetHashCode() : 0,
#if UNITY_EDITOR #if UNITY_EDITOR
(uint)EditorJsonUtility.ToJson(modifiedMaterial).GetHashCode() (uint)EditorJsonUtility.ToJson(modifiedMaterial).GetHashCode()
#else #else
@@ -285,15 +286,38 @@ namespace Coffee.UIExtensions
|| (_isTrail && !_particleSystem.trails.enabled) // Trail, but it is not enabled. || (_isTrail && !_particleSystem.trails.enabled) // Trail, but it is not enabled.
) )
{ {
// Skip clearing the mesh if it's already cleared.
if (_meshCleared) return;
Profiler.BeginSample("[UIParticleRenderer] Clear Mesh"); Profiler.BeginSample("[UIParticleRenderer] Clear Mesh");
workerMesh.Clear(); workerMesh.Clear();
canvasRenderer.SetMesh(workerMesh); canvasRenderer.SetMesh(workerMesh);
_lastBounds = new Bounds(); _lastBounds = new Bounds();
_meshCleared = true;
Profiler.EndSample(); Profiler.EndSample();
return; return;
} }
// Reset custom data.
// var customData = _particleSystem.customData;
// if (!customData.enabled || customData.GetMode(ParticleSystemCustomData.Custom1) == ParticleSystemCustomDataMode.Disabled)
// {
// customData.SetVector(ParticleSystemCustomData.Custom1, 0, 0);
// customData.SetVector(ParticleSystemCustomData.Custom1, 1, 0);
// customData.SetVector(ParticleSystemCustomData.Custom1, 2, 0);
// customData.SetVector(ParticleSystemCustomData.Custom1, 3, 0);
// }
//
// if (!customData.enabled || customData.GetMode(ParticleSystemCustomData.Custom2) == ParticleSystemCustomDataMode.Disabled)
// {
// customData.SetVector(ParticleSystemCustomData.Custom2, 0, 0);
// customData.SetVector(ParticleSystemCustomData.Custom2, 1, 0);
// customData.SetVector(ParticleSystemCustomData.Custom2, 2, 0);
// customData.SetVector(ParticleSystemCustomData.Custom2, 3, 0);
// }
_meshCleared = false;
var main = _particleSystem.main; var main = _particleSystem.main;
var scale = GetWorldScale(); var scale = GetWorldScale();
var psPos = _particleSystem.transform.position; var psPos = _particleSystem.transform.position;
@@ -713,7 +737,7 @@ namespace Coffee.UIExtensions
if (s_Mpb.isEmpty) return; if (s_Mpb.isEmpty) return;
// #41: Copy the value from MaterialPropertyBlock to CanvasRenderer // #41: Copy the value from MaterialPropertyBlock to CanvasRenderer
if (!materialForRendering) return; if (materialForRendering == null) return;
for (var i = 0; i < _parent.m_AnimatableProperties.Length; i++) for (var i = 0; i < _parent.m_AnimatableProperties.Length; i++)
{ {

View File

@@ -16,25 +16,25 @@ namespace Coffee.UIExtensions
public static void Register(UIParticle particle) public static void Register(UIParticle particle)
{ {
if (!particle) return; if (particle == null) return;
s_ActiveParticles.Add(particle); s_ActiveParticles.Add(particle);
} }
public static void Unregister(UIParticle particle) public static void Unregister(UIParticle particle)
{ {
if (!particle) return; if (particle == null) return;
s_ActiveParticles.Remove(particle); s_ActiveParticles.Remove(particle);
} }
public static void Register(UIParticleAttractor attractor) public static void Register(UIParticleAttractor attractor)
{ {
if (!attractor) return; if (attractor == null) return;
s_ActiveAttractors.Add(attractor); s_ActiveAttractors.Add(attractor);
} }
public static void Unregister(UIParticleAttractor attractor) public static void Unregister(UIParticleAttractor attractor)
{ {
if (!attractor) return; if (attractor == null) return;
s_ActiveAttractors.Remove(attractor); s_ActiveAttractors.Remove(attractor);
} }
@@ -71,7 +71,7 @@ namespace Coffee.UIExtensions
for (var i = 0; i < s_ActiveParticles.Count; i++) for (var i = 0; i < s_ActiveParticles.Count; i++)
{ {
var uip = s_ActiveParticles[i]; var uip = s_ActiveParticles[i];
if (!uip || !uip.canvas || !uip.isPrimary || !s_UpdatedGroupIds.Add(uip.groupId)) continue; if (uip == null || uip.canvas == null || !uip.isPrimary || !s_UpdatedGroupIds.Add(uip.groupId)) continue;
uip.UpdateTransformScale(); uip.UpdateTransformScale();
uip.UpdateRenderers(); uip.UpdateRenderers();
@@ -81,7 +81,7 @@ namespace Coffee.UIExtensions
for (var i = 0; i < s_ActiveParticles.Count; i++) for (var i = 0; i < s_ActiveParticles.Count; i++)
{ {
var uip = s_ActiveParticles[i]; var uip = s_ActiveParticles[i];
if (!uip || !uip.canvas) continue; if (uip == null || uip.canvas == null) continue;
uip.UpdateTransformScale(); uip.UpdateTransformScale();
@@ -125,7 +125,7 @@ namespace Coffee.UIExtensions
var uip = s_ActiveParticles[i]; var uip = s_ActiveParticles[i];
if (!uip.useMeshSharing || uip.groupId != groupId) continue; if (!uip.useMeshSharing || uip.groupId != groupId) continue;
if (uip.isPrimary) return uip; if (uip.isPrimary) return uip;
if (!primary && uip.canSimulate) primary = uip; if (primary == null && uip.canSimulate) primary = uip;
} }
return primary; return primary;

View File

@@ -84,15 +84,15 @@ namespace Coffee.UIParticleInternal
var bRenderer = b.GetComponent<ParticleSystemRenderer>(); var bRenderer = b.GetComponent<ParticleSystemRenderer>();
// Render queue: ascending // Render queue: ascending
var aMat = aRenderer.sharedMaterial ? aRenderer.sharedMaterial : aRenderer.trailMaterial; var aMat = aRenderer.sharedMaterial != null ? aRenderer.sharedMaterial : aRenderer.trailMaterial;
var bMat = bRenderer.sharedMaterial ? bRenderer.sharedMaterial : bRenderer.trailMaterial; var bMat = bRenderer.sharedMaterial != null ? bRenderer.sharedMaterial : bRenderer.trailMaterial;
if (!aMat && !bMat) return 0; if (aMat == null && bMat == null) return 0;
if (!aMat) return -1; if (aMat == null) return -1;
if (!bMat) return 1; if (bMat == null) return 1;
if (sortByMaterial) if (sortByMaterial)
{ {
return aMat.GetInstanceID() - bMat.GetInstanceID(); return aMat.GetHashCode() - bMat.GetHashCode();
} }
if (aMat.renderQueue != bMat.renderQueue) if (aMat.renderQueue != bMat.renderQueue)
@@ -131,7 +131,7 @@ namespace Coffee.UIParticleInternal
{ {
for (var i = 0; i < list.Count; i++) for (var i = 0; i < list.Count; i++)
{ {
if (list[i].GetInstanceID() == ps.GetInstanceID()) if (list[i].GetHashCode() == ps.GetHashCode())
{ {
return i; return i;
} }
@@ -142,7 +142,7 @@ namespace Coffee.UIParticleInternal
public static Texture2D GetTextureForSprite(this ParticleSystem self) public static Texture2D GetTextureForSprite(this ParticleSystem self)
{ {
if (!self) return null; if (self == null) return null;
// Get sprite's texture. // Get sprite's texture.
var tsaModule = self.textureSheetAnimation; var tsaModule = self.textureSheetAnimation;
@@ -151,7 +151,7 @@ namespace Coffee.UIParticleInternal
for (var i = 0; i < tsaModule.spriteCount; i++) for (var i = 0; i < tsaModule.spriteCount; i++)
{ {
var sprite = tsaModule.GetSprite(i); var sprite = tsaModule.GetSprite(i);
if (!sprite) continue; if (sprite == null) continue;
return sprite.GetActualTexture(); return sprite.GetActualTexture();
} }
@@ -163,14 +163,14 @@ namespace Coffee.UIParticleInternal
{ {
foreach (var p in self) foreach (var p in self)
{ {
if (!p) continue; if (p == null) continue;
action.Invoke(p); action.Invoke(p);
} }
} }
public static ParticleSystem GetMainEmitter(this ParticleSystem self, List<ParticleSystem> list) public static ParticleSystem GetMainEmitter(this ParticleSystem self, List<ParticleSystem> list)
{ {
if (!self || list == null || list.Count == 0) return null; if (self == null || list == null || list.Count == 0) return null;
for (var i = 0; i < list.Count; i++) for (var i = 0; i < list.Count; i++)
{ {
@@ -183,7 +183,7 @@ namespace Coffee.UIParticleInternal
public static bool IsSubEmitterOf(this ParticleSystem self, ParticleSystem parent) public static bool IsSubEmitterOf(this ParticleSystem self, ParticleSystem parent)
{ {
if (!self || !parent) return false; if (self == null || parent == null) return false;
var subEmitters = parent.subEmitters; var subEmitters = parent.subEmitters;
if (!subEmitters.enabled) return false; // No sub emitters. if (!subEmitters.enabled) return false; // No sub emitters.

View File

@@ -15,7 +15,7 @@ namespace Coffee.UIExtensions.Demo
private void Start() private void Start()
{ {
if (!m_Origin) return; if (m_Origin == null) return;
m_Origin.SetActive(false); m_Origin.SetActive(false);
var parent = m_Origin.transform.parent; var parent = m_Origin.transform.parent;

View File

@@ -42,7 +42,7 @@ public class UIElementDragger : MonoBehaviour, IBeginDragHandler, IDragHandler,
break; break;
case Target.Custom: case Target.Custom:
_rectTransform.localPosition += delta; _rectTransform.localPosition += delta;
if (m_CustomTarget) if (m_CustomTarget != null)
{ {
if (m_UseCanvasScale) if (m_UseCanvasScale)
{ {

View File

@@ -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.11.4", "version": "4.12.2",
"unity": "2018.2", "unity": "2018.2",
"license": "MIT", "license": "MIT",
"repository": { "repository": {