Compare commits

..

11 Commits

Author SHA1 Message Date
semantic-release-bot
73d208e9b8 chore(release): 5.0.0-preview.15 [skip ci]
# [5.0.0-preview.15](https://github.com/mob-sakai/ParticleEffectForUGUI/compare/5.0.0-preview.14...5.0.0-preview.15) (2025-02-21)

### Bug Fixes

* component icons will no longer be displayed in the scene view ([6dfbdae](6dfbdae38d))
* editor crashed on exit play mode (editor, windows) ([47ee45c](47ee45cbbe)), closes [#351](https://github.com/mob-sakai/ParticleEffectForUGUI/issues/351)

### Features

* add 'TimeScaleMultiplier' option ([925af0b](925af0b604))
2025-02-21 09:45:26 +00:00
mob-sakai
bfac4d4e2f Merge remote-tracking branch 'origin/develop' into develop-preview
# Conflicts:
#	Packages/src/CHANGELOG.md
#	Packages/src/Runtime/UIParticle.cs
#	Packages/src/package.json
2025-02-21 18:38:11 +09:00
semantic-release-bot
88d956ece8 chore(release): 5.0.0-preview.14 [skip ci]
# [5.0.0-preview.14](https://github.com/mob-sakai/ParticleEffectForUGUI/compare/5.0.0-preview.13...5.0.0-preview.14) (2025-01-03)

### Bug Fixes

* sub-emitter particles may not render correctly in certain scenarios ([8276684](8276684c3b)), closes [#348](https://github.com/mob-sakai/ParticleEffectForUGUI/issues/348)
* sub-emitter's `inherit velocity` module doubles at runtime ([67de3d1](67de3d1bd3)), closes [#349](https://github.com/mob-sakai/ParticleEffectForUGUI/issues/349)
2025-01-03 14:26:44 +00:00
mob-sakai
2842b3db7d Merge branch 'develop' into develop-preview 2025-01-03 23:14:17 +09:00
semantic-release-bot
c2958d5d7d chore(release): 5.0.0-preview.13 [skip ci]
# [5.0.0-preview.13](https://github.com/mob-sakai/ParticleEffectForUGUI/compare/5.0.0-preview.12...5.0.0-preview.13) (2025-01-03)

### Features

* change the default value of `UIParticle.scale` from `10` to `1` ([9955eef](9955eefdc2))
* UIParticle no longer inherits from MaskableGraphic ([c09bfb8](c09bfb81ab))

### BREAKING CHANGES

* Some members inherited from MaskableGraphic will no longer be available.
2025-01-03 14:12:36 +00:00
mob-sakai
7456b5d555 docs: update documents 2025-01-03 23:08:20 +09:00
mob-sakai
9955eefdc2 feat: change the default value of UIParticle.scale from 10 to 1 2025-01-03 23:02:15 +09:00
mob-sakai
c09bfb81ab feat: UIParticle no longer inherits from MaskableGraphic
BREAKING CHANGE: Some members inherited from MaskableGraphic will no longer be available.
2025-01-03 23:02:15 +09:00
mob-sakai
fab2ed1697 chore: update coffee.internal 2025-01-03 22:58:23 +09:00
mob-sakai
ef4dbc3cba fix: sub-emitter particles may not render correctly in certain scenarios
close #248
2025-01-03 22:50:36 +09:00
mob-sakai
27551a4d47 fix: sub-emitter's inherit velocity module doubles at runtime
close #249
2025-01-03 22:29:07 +09:00
48 changed files with 2866 additions and 972 deletions

28
.github/workflows/deploy.yml vendored Normal file
View File

@@ -0,0 +1,28 @@
name: 🚀 Deploy with Zip
on:
workflow_dispatch:
inputs:
zip:
description: "The url to the zip file"
required: true
jobs:
deploy:
name: 🚀 Deploy
runs-on: ubuntu-latest
permissions:
pages: write
id-token: write
steps:
- name: 📦 Download zip file To '_site'
run: |
curl -L ${{ github.event.inputs.zip }} -o _site.zip
unzip _site.zip -d _site
find _site -name __MACOSX | xargs rm -rf
- name: 📦 Upload '_site'
uses: actions/upload-pages-artifact@v3
- name: 🚀 Deploy To GitHub Pages
uses: actions/deploy-pages@v4

View File

@@ -5,8 +5,9 @@ on:
workflow_dispatch:
push:
branches:
- release
- release-*
- preview
- main
- v*.x
tags-ignore:
- "**"
@@ -22,15 +23,12 @@ jobs:
channel: ${{ steps.release.outputs.new_release_channel }}
released: ${{ steps.release.outputs.new_release_published }}
tag: ${{ steps.release.outputs.new_release_git_tag }}
version: ${{ steps.release.outputs.new_release_version }}
merge_to: ${{ steps.summary.outputs.merge_to }}
split_to: ${{ steps.summary.outputs.split_to }}
steps:
- name: 🚚 Checkout (${{ github.ref_name }})
uses: actions/checkout@v6
uses: actions/checkout@v4
- name: 🔖 Run semantic release
uses: cycjimmy/semantic-release-action@v6
uses: cycjimmy/semantic-release-action@v4
id: release
with:
working_directory: Packages/src
@@ -38,64 +36,9 @@ jobs:
@semantic-release/changelog
@semantic-release/git
env:
GITHUB_TOKEN: ${{ github.token }}
GITHUB_TOKEN: ${{ secrets.GH_TOKEN }}
- id: summary
run: |
- run: |
echo "🔖 New release published: '${{ steps.release.outputs.new_release_published }}'" | tee -a $GITHUB_STEP_SUMMARY
echo "🔖 New release version: '${{ steps.release.outputs.new_release_version }}'" | tee -a $GITHUB_STEP_SUMMARY
echo "🔖 New release channel: '${{ steps.release.outputs.new_release_channel }}'" | tee -a $GITHUB_STEP_SUMMARY
echo "🔖 New release git tag: '${{ steps.release.outputs.new_release_git_tag }}'" | tee -a $GITHUB_STEP_SUMMARY
if [ '${{ steps.release.outputs.new_release_published }}' = 'false' ]; then
echo "No new release published." | tee -a $GITHUB_STEP_SUMMARY
elif [ '${{ github.ref_name }}' = 'release' ]; then
echo "merge_to=develop" | tee -a $GITHUB_OUTPUT $GITHUB_STEP_SUMMARY
echo "split_to=main" | tee -a $GITHUB_OUTPUT $GITHUB_STEP_SUMMARY
else
channel=$(echo ${{ github.ref_name }} | sed 's/^release-//')
echo "merge_to=develop-${channel}" | tee -a $GITHUB_OUTPUT $GITHUB_STEP_SUMMARY
echo "split_to=${channel}" | tee -a $GITHUB_OUTPUT $GITHUB_STEP_SUMMARY
fi
merge-to:
if: needs.release.outputs.merge_to != ''
needs: release
name: 🔀 Merge to ${{ needs.release.outputs.merge_to }}
runs-on: ubuntu-latest
permissions:
contents: write
steps:
- name: 🚚 Checkout (${{ needs.release.outputs.merge_to }})
uses: actions/checkout@v5
with:
ref: ${{ needs.release.outputs.merge_to }}
fetch-depth: 0
- name: 🔀 Merge '${{ needs.release.outputs.tag }}' into '${{ needs.release.outputs.merge_to }}'
run: |
git config --local user.email "github-actions[bot]@users.noreply.github.com"
git config --local user.name "github-actions[bot]"
git merge ${{ needs.release.outputs.tag }}
git push origin ${{ needs.release.outputs.merge_to }}
split-to:
if: needs.release.outputs.split_to != ''
needs: release
name: 🔀 Split package to ${{ needs.release.outputs.split_to }}
runs-on: ubuntu-latest
permissions:
contents: write
steps:
- name: 🚚 Checkout (${{ needs.release.outputs.tag }})
uses: actions/checkout@v5
with:
ref: ${{ needs.release.outputs.tag }}
fetch-depth: 0
- name: 🔀 Split subtree 'Packages/src' to '${{ needs.release.outputs.split_to }}'
run: |
split_to=${{ needs.release.outputs.split_to }}
git branch $split_to origin/$split_to
git subtree split --prefix=Packages/src --branch $split_to
git tag ${{ needs.release.outputs.version }} $split_to
git push origin ${{ needs.release.outputs.version }} $split_to:$split_to

View File

@@ -7,10 +7,9 @@ run-name: 🧪 Test (${{ github.event.pull_request.title || github.ref_name }})
env:
# MINIMUM_VERSION: The minimum version of Unity.
MINIMUM_VERSION: 2020.3
MINIMUM_VERSION: 2019.4
# EXCLUDE_FILTER: The excluded versions of Unity.
EXCLUDE_FILTER: "(2017|2018|2023.3)"
PROJECT_PATH: .
EXCLUDE_FILTER: "(2020.2.0|2021.1|2023.3)"
on:
workflow_dispatch:
@@ -22,12 +21,12 @@ on:
push:
branches:
- develop
- "develop-*"
- develop-preview
tags:
- "!*"
paths-ignore:
- "**.md"
pull_request:
pull_request_target:
types:
- opened
- reopened
@@ -39,29 +38,16 @@ jobs:
setup:
name: ⚙️ Setup
runs-on: ubuntu-latest
permissions: {} # No permissions needed for setup job
outputs:
unityVersions: ${{ steps.setup.outputs.unityVersions }}
steps:
- name: 🔑 Secrets check
run: |
if [ -z "$UNITY_EMAIL" ] || [ -z "$UNITY_PASSWORD" ] || [ -z "UNITY_LICENSE" ]; then
echo "Error: UNITY_EMAIL, UNITY_PASSWORD, and UNITY_LICENSE secrets must be set." | tee -a $GITHUB_STEP_SUMMARY >&2
echo "Error: See https://game.ci/docs/github/test-runner#basic-setup" | tee -a $GITHUB_STEP_SUMMARY >&2
echo "Error: Set the secrets at ${{ github.server_url }}/${{ github.repository }}/settings/secrets/actions" | tee -a $GITHUB_STEP_SUMMARY >&2
exit 1
fi
env:
UNITY_EMAIL: ${{ secrets.UNITY_EMAIL }}
UNITY_PASSWORD: ${{ secrets.UNITY_PASSWORD }}
UNITY_LICENSE: ${{ secrets.UNITY_LICENSE }}
- name: ⚙️ Find target Unity versions
id: setup
run: |
echo "==== Target Unity Versions ===="
LATEST_VERSIONS=`npx -y unity-changeset@latest list --json --versions --all --latest-patch --ignore-alpha --min ${MINIMUM_VERSION}`
LATEST_VERSIONS=`npx unity-changeset@latest list --versions --latest-patch --min ${MINIMUM_VERSION} --json --all`
if [ "${{ inputs.usePeriodVersions }}" = "true" ]; then
ADDITIONAL_VERSIONS=`npx -y unity-changeset@latest list --json --versions --ignore-alpha --min ${MINIMUM_VERSION} --grep '0f'`
ADDITIONAL_VERSIONS=`npx unity-changeset list --versions --grep '0f' --min ${MINIMUM_VERSION} --json`
else
ADDITIONAL_VERSIONS=[]
fi
@@ -79,31 +65,45 @@ jobs:
needs: setup
strategy:
fail-fast: false
max-parallel: 8
max-parallel: 6
matrix:
unityVersion: ${{ fromJson(needs.setup.outputs.unityVersions) }}
steps:
- name: 🚚 Checkout ($${{ github.ref }})
uses: actions/checkout@v6
if: github.event_name == 'push'
uses: actions/checkout@v4
- name: 🚚 Checkout pull request (pull_request_target)
if: github.event_name == 'pull_request_target'
uses: actions/checkout@v4
with:
ref: ${{ github.event.pull_request.head.sha }}
fetch-depth: 0
- name: 🚚 Marge pull request (pull_request_target)
if: github.event_name == 'pull_request_target'
run: |
git config user.name "GitHub Actions"
git config user.email "actions@github.com"
git merge origin/${{ github.event.pull_request.base.ref }} --no-edit
- name: 📥 Cache library
uses: actions/cache@v5
uses: actions/cache@v4
with:
path: ${{ env.PROJECT_PATH }}/Library
key: ${{ env.PROJECT_PATH }}-Library-${{ matrix.unityVersion }}-${{ github.event.pull_request.head.sha || github.sha }}
path: Library
key: Library-${{ matrix.unityVersion }}-${{ github.event.pull_request.head.sha || github.sha }}
restore-keys: |
${{ env.PROJECT_PATH }}-Library-${{ matrix.unityVersion }}-
${{ env.PROJECT_PATH }}-Library-
Library-${{ matrix.unityVersion }}-
Library-
- name: 🛠️ Build Unity Project (Test)
uses: game-ci/unity-builder@v5
uses: game-ci/unity-builder@v4
timeout-minutes: 45
with:
customImage: ghcr.io/mob-sakai/unity3d:${{ matrix.unityVersion }}
targetPlatform: StandaloneLinux64
allowDirtyBuild: true
customParameters: -nographics
projectPath: ${{ env.PROJECT_PATH }}
env:
UNITY_EMAIL: ${{ secrets.UNITY_EMAIL }}
UNITY_PASSWORD: ${{ secrets.UNITY_PASSWORD }}
@@ -118,7 +118,6 @@ jobs:
customParameters: -nographics
checkName: ${{ matrix.unityVersion }} Test Results
githubToken: ${{ github.token }}
projectPath: ${{ env.PROJECT_PATH }}
env:
UNITY_EMAIL: ${{ secrets.UNITY_EMAIL }}
UNITY_PASSWORD: ${{ secrets.UNITY_PASSWORD }}

View File

@@ -18,12 +18,11 @@ MonoBehaviour:
m_EnabledInEditor: 1
m_AlwaysIncludeAssembly: 1
m_InstantiateOnLoad: 1
m_Prefab: {fileID: 4567906826058368312, guid: 7cebff2d255b9433cbe23b243c193329,
m_Prefab: {fileID: 7211429669315726685, guid: b73940fc30a2f4eb9a73783e9c1f8da6,
type: 3}
m_Interval: 0.5
m_Anchor: 0
m_Width: 750
m_HelpUrl: https://github.com/mob-sakai/ParticleEffectForUGUI
m_CustomMonitorItems:
- m_Format: Screen:{0}x{1}
m_Arg0:

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: b73940fc30a2f4eb9a73783e9c1f8da6
PrefabImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -10,7 +10,7 @@ MonoBehaviour:
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: f22a23b9d98e440478697f4adf30e61c, type: 3}
m_Name: UIParticleProjectSettings
m_Name: UIParticle
m_EditorClassIdentifier:
m_EnableLinearToGamma: 1
m_HideGeneratedObjects: 1

View File

@@ -1,5 +1,5 @@
fileFormatVersion: 2
guid: a5b9278dfbd194d04b1c6ae7031928c1
guid: 4b9df7b8a4193489299b8f477348ae0c
NativeFormatImporter:
externalObjects: {}
mainObjectFileID: 11400000

View File

@@ -1,21 +1,16 @@
using System.Collections;
using Coffee.UIParticleInternal;
using NUnit.Framework;
using UnityEngine;
using UnityEngine.TestTools;
namespace Coffee.UIParticle.Editor.Tests
{
public class NewTestScript
{
[TestCase(-1)]
[TestCase(0)]
[TestCase(2048)]
[TestCase(3000)]
public void GetParticleArray(int requiredSize)
// A Test behaves as an ordinary method
[Test]
public void NewTestScriptSimplePasses()
{
var array = ParticleSystemExtensions.GetParticleArray(requiredSize);
Debug.Log($"requiredSize: {requiredSize}, array.Length: {array.Length}");
// Use the Assert class to test conditions
}
// A UnityTest behaves like a coroutine in Play Mode. In Edit Mode you can use

View File

@@ -3,7 +3,7 @@
"com.coffee.development": "https://github.com/mob-sakai/Coffee.Internal.git?path=Packages/Development",
"com.coffee.minimal-resource": "https://github.com/mob-sakai/Coffee.Internal.git?path=Packages/MinimalResource",
"com.coffee.nano-monitor": "https://github.com/mob-sakai/Coffee.Internal.git?path=Packages/NanoMonitor",
"com.unity.ide.rider": "3.0.36",
"com.unity.ide.rider": "3.0.31",
"com.unity.test-framework": "1.1.33",
"com.unity.modules.animation": "1.0.0",
"com.unity.modules.physics": "1.0.0"

View File

@@ -5,14 +5,14 @@
"depth": 0,
"source": "git",
"dependencies": {},
"hash": "3c280f1a8f4db5038b881ff07f270efd9638fa31"
"hash": "52987fb6e66e7fc48498d8d164c3c8808de4de6b"
},
"com.coffee.minimal-resource": {
"version": "https://github.com/mob-sakai/Coffee.Internal.git?path=Packages/MinimalResource",
"depth": 0,
"source": "git",
"dependencies": {},
"hash": "3c280f1a8f4db5038b881ff07f270efd9638fa31"
"hash": "52987fb6e66e7fc48498d8d164c3c8808de4de6b"
},
"com.coffee.nano-monitor": {
"version": "https://github.com/mob-sakai/Coffee.Internal.git?path=Packages/NanoMonitor",
@@ -21,7 +21,7 @@
"dependencies": {
"com.unity.ugui": "1.0.0"
},
"hash": "3c280f1a8f4db5038b881ff07f270efd9638fa31"
"hash": "52987fb6e66e7fc48498d8d164c3c8808de4de6b"
},
"com.coffee.ui-particle": {
"version": "file:src",
@@ -40,7 +40,7 @@
"url": "https://packages.unity.com"
},
"com.unity.ide.rider": {
"version": "3.0.36",
"version": "3.0.31",
"depth": 0,
"source": "registry",
"dependencies": {

View File

@@ -1,12 +1,13 @@
{
"branches": [
"release",
"release-4.x",
"main",
"[0-9]+.x",
{
"name": "release-preview",
"prerelease": "preview"
"name": "preview",
"prerelease": true
}
],
"tagFormat": "${version}",
"plugins": [
"@semantic-release/commit-analyzer",
"@semantic-release/release-notes-generator",

View File

@@ -1,75 +1,17 @@
## [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)
### Bug Fixes
* add early return for case where subEmitter module is disabled ([d1386a1](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/d1386a12216743a6e09f1b9b87bea1dfcf7702e4))
* avoid endless loop ([eb2e862](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/eb2e862e80e549c8cf16ddfed776c101c2413bac)), closes [#392](https://github.com/mob-sakai/ParticleEffectForUGUI/issues/392)
## [4.11.3](https://github.com/mob-sakai/ParticleEffectForUGUI/compare/v4.11.2...v4.11.3) (2025-10-14)
### Bug Fixes
* fix icon ([a9461ec](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/a9461ecb4d40d7fe878e12465d6e38faae7ae65b))
* fix URL link in README ([1c8c65d](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/1c8c65d25e7f6fe7b1d20da4461333df8fc7578e)), closes [#376](https://github.com/mob-sakai/ParticleEffectForUGUI/issues/376)
* fix: second and subsequent bursts not displayed when world simulation and non-looping ([df2f3ca](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/df2f3caafbe279f1457d74f8183cb561ac14aa17)), closes [#326](https://github.com/mob-sakai/ParticleEffectForUGUI/issues/326)
* UIParticle in canvas with 0f-0.01f alpha value does not start to play until alpha value is greater than 0.01f, causes play calls to be delayed unintentionally if canvas alpha value is set to mentioned value range ([38aec2e](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/38aec2ea1afd77677d629c86665a3342d92e49d9))
## [4.11.2](https://github.com/mob-sakai/ParticleEffectForUGUI/compare/v4.11.1...v4.11.2) (2025-03-15)
### Bug Fixes
* IL2CPP build fails on older versions of Unity ([0da6525](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/0da652520cd165b43de7404c0b0ab1fbcf9349d1))
* NRE on enable ([0cff50e](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/0cff50ef696aa53fb7c46a9a737b7cf3a05b7b9b)), closes [#359](https://github.com/mob-sakai/ParticleEffectForUGUI/issues/359)
## [4.11.1](https://github.com/mob-sakai/ParticleEffectForUGUI/compare/v4.11.0...v4.11.1) (2025-02-21)
# [5.0.0-preview.15](https://github.com/mob-sakai/ParticleEffectForUGUI/compare/5.0.0-preview.14...5.0.0-preview.15) (2025-02-21)
### Bug Fixes
* component icons will no longer be displayed in the scene view ([6dfbdae](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/6dfbdae38d3822ab9c2c6f0e4ca1ca32ee98a239))
# [4.11.0](https://github.com/mob-sakai/ParticleEffectForUGUI/compare/v4.10.7...v4.11.0) (2025-02-21)
* editor crashed on exit play mode (editor, windows) ([47ee45c](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/47ee45cbbe651a8f87ca2b8a3948f8b88db8211e)), closes [#351](https://github.com/mob-sakai/ParticleEffectForUGUI/issues/351)
### Features
* add 'TimeScaleMultiplier' option ([925af0b](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/925af0b6046f65f23a778f67cefa8ff9cbedb513))
## [4.10.7](https://github.com/mob-sakai/ParticleEffectForUGUI/compare/v4.10.6...v4.10.7) (2025-01-14)
### Bug Fixes
* editor crashed on exit play mode (editor, windows) ([47ee45c](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/47ee45cbbe651a8f87ca2b8a3948f8b88db8211e)), closes [#351](https://github.com/mob-sakai/ParticleEffectForUGUI/issues/351)
## [4.10.6](https://github.com/mob-sakai/ParticleEffectForUGUI/compare/v4.10.5...v4.10.6) (2025-01-03)
# [5.0.0-preview.14](https://github.com/mob-sakai/ParticleEffectForUGUI/compare/5.0.0-preview.13...5.0.0-preview.14) (2025-01-03)
### Bug Fixes
@@ -77,6 +19,19 @@
* sub-emitter particles may not render correctly in certain scenarios ([8276684](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/8276684c3b1646f0490ed64557547ba15281664a)), closes [#348](https://github.com/mob-sakai/ParticleEffectForUGUI/issues/348)
* sub-emitter's `inherit velocity` module doubles at runtime ([67de3d1](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/67de3d1bd3e16dc9b564625cb990c53d75769506)), closes [#349](https://github.com/mob-sakai/ParticleEffectForUGUI/issues/349)
# [5.0.0-preview.13](https://github.com/mob-sakai/ParticleEffectForUGUI/compare/5.0.0-preview.12...5.0.0-preview.13) (2025-01-03)
### Features
* change the default value of `UIParticle.scale` from `10` to `1` ([9955eef](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/9955eefdc22cf565502f85c87cd2efd3a25fbe50))
* UIParticle no longer inherits from MaskableGraphic ([c09bfb8](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/c09bfb81abc9179bf5fc49d29eaf7fc4ed01a4dc))
### BREAKING CHANGES
* Some members inherited from MaskableGraphic will no longer be available.
## [4.10.5](https://github.com/mob-sakai/ParticleEffectForUGUI/compare/v4.10.4...v4.10.5) (2024-12-23)

View File

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

View File

@@ -1,19 +1,18 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text.RegularExpressions;
using UnityEditor;
using UnityEditor.UI;
using UnityEditorInternal;
using UnityEngine;
using UnityEngine.Profiling;
using UnityEngine.UI;
using Coffee.UIParticleInternal;
using Object = UnityEngine.Object;
#if UNITY_2021_2_OR_NEWER
using UnityEditor.Overlays;
#else
using System;
using System.Reflection;
using Object = UnityEngine.Object;
#endif
#if UNITY_2021_2_OR_NEWER
using UnityEditor.SceneManagement;
@@ -26,7 +25,7 @@ namespace Coffee.UIExtensions
{
[CustomEditor(typeof(UIParticle))]
[CanEditMultipleObjects]
internal class UIParticleEditor : GraphicEditor
internal class UIParticleEditor : Editor
{
internal class State : ScriptableSingleton<State>
{
@@ -49,7 +48,6 @@ namespace Coffee.UIExtensions
private static readonly GUIContent s_ContentRandom = new GUIContent("Random");
private static readonly GUIContent s_ContentScale = new GUIContent("Scale");
private static readonly GUIContent s_ContentPrimary = new GUIContent("Primary");
private static readonly GUIContent s_Remove = new GUIContent("Remove");
private static readonly Regex s_RegexBuiltInGuid = new Regex(@"^0{16}.0{15}$", RegexOptions.Compiled);
private static readonly List<Material> s_TempMaterials = new List<Material>();
@@ -67,7 +65,6 @@ namespace Coffee.UIExtensions
private ReorderableList _ro;
private bool _showMax;
private bool _is3DScaleMode;
private GameObject[] _gameObjects;
private static readonly HashSet<Shader> s_Shaders = new HashSet<Shader>();
#if UNITY_2018 || UNITY_2019
@@ -89,10 +86,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");
@@ -112,7 +107,7 @@ namespace Coffee.UIExtensions
{
var ps = sp.GetArrayElementAtIndex(index).objectReferenceValue as ParticleSystem;
var materialCount = 0;
if (ps != null && ps.TryGetComponent<ParticleSystemRenderer>(out var psr))
if (ps && ps.TryGetComponent<ParticleSystemRenderer>(out var psr))
{
materialCount = psr.sharedMaterials.Length;
}
@@ -126,7 +121,7 @@ namespace Coffee.UIExtensions
var p = sp.GetArrayElementAtIndex(index);
EditorGUI.ObjectField(rect, p, GUIContent.none);
var ps = p.objectReferenceValue as ParticleSystem;
if (ps == null || !ps.TryGetComponent<ParticleSystemRenderer>(out var psr)) return;
if (!ps || !ps.TryGetComponent<ParticleSystemRenderer>(out var psr)) return;
rect.x += 15;
rect.width -= 15;
@@ -185,13 +180,6 @@ namespace Coffee.UIExtensions
y.hasMultipleDifferentValues ||
z.hasMultipleDifferentValues;
}
// Add temporary ParticleSystem for preview if enabled.
if (UIParticleProjectSettings.s_PreviewOnSelectOnSelect)
{
_gameObjects = targets.OfType<UIParticle>().Select(x => x.gameObject).ToArray();
ParticleSystemPreviewSystem.Register(_gameObjects);
}
}
/// <summary>
@@ -200,16 +188,13 @@ namespace Coffee.UIExtensions
public override void OnInspectorGUI()
{
var current = target as UIParticle;
if (current == null) return;
if (!current) return;
Profiler.BeginSample("(UIP:E) OnInspectorGUI");
serializedObject.Update();
// Maskable
if (_maskable != null)
{
EditorGUILayout.PropertyField(_maskable);
}
// Scale
EditorGUI.BeginDisabledGroup(!_meshSharing.hasMultipleDifferentValues && _meshSharing.intValue == 4);
@@ -279,7 +264,7 @@ namespace Coffee.UIExtensions
Profiler.BeginSample("(UIP:E) Non-UI built-in shader is not supported.");
foreach (var mat in s_TempMaterials)
{
if (mat == null || mat.shader == null) continue;
if (!mat || !mat.shader) continue;
var shader = mat.shader;
if (IsBuiltInObject(shader) && !shader.name.StartsWith("UI/"))
{
@@ -298,7 +283,7 @@ namespace Coffee.UIExtensions
{
foreach (var mat in s_TempMaterials)
{
if (mat == null || mat.shader == null) continue;
if (!mat || !mat.shader) continue;
var shader = mat.shader;
if (!s_Shaders.Add(shader)) continue;
@@ -356,10 +341,6 @@ namespace Coffee.UIExtensions
}
}
#endif
// Remove the temporary ParticleSystem.
ParticleSystemPreviewSystem.DrawWarningForTemporary(_gameObjects);
Profiler.EndSample();
}
@@ -480,9 +461,11 @@ namespace Coffee.UIExtensions
{
if (!p || (ignoreCurrent && target == p)) return;
var cr = p.canvasRenderer;
DestroyImmediate(p);
DestroyImmediate(cr);
Misc.DestroyImmediate(p);
if (p.TryGetComponent<CanvasRenderer>(out var cr))
{
Misc.DestroyImmediate(cr);
}
#if UNITY_2018_3_OR_NEWER
var stage = PrefabStageUtility.GetCurrentPrefabStage();
@@ -498,7 +481,7 @@ namespace Coffee.UIExtensions
#endif
}
private static bool FixButton(bool show, string text, GUIContent buttonText = null)
private static bool FixButton(bool show, string text)
{
if (!show) return false;
using (new EditorGUILayout.HorizontalScope(GUILayout.ExpandWidth(true)))
@@ -506,7 +489,7 @@ namespace Coffee.UIExtensions
EditorGUILayout.HelpBox(text, MessageType.Warning, true);
using (new EditorGUILayout.VerticalScope())
{
return GUILayout.Button(buttonText ?? s_ContentFix, GUILayout.ExpandWidth(false));
return GUILayout.Button(s_ContentFix, GUILayout.Width(30));
}
}
}

View File

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

8
Packages/src/Icons.meta Normal file
View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 7a55e246f37df405bac88eac692e3a86
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

Before

Width:  |  Height:  |  Size: 418 B

After

Width:  |  Height:  |  Size: 418 B

View File

@@ -1,9 +1,9 @@
# <img alt="UIParticleIcon" src="https://github.com/mob-sakai/ParticleEffectForUGUI/assets/12690315/d76e105e-a840-4f61-a1f6-8cf311c0812d" width="26"/> Particle Effect For UGUI (UI Particle) <!-- omit in toc -->
# <img alt="UIParticleIcon" src="https://github.com/mob-sakai/ParticleEffectForUGUI/assets/12690315/d76e105e-a840-4f61-a1f6-8cf311c0812d" width="26"/> UI Particle v5 <!-- omit in toc -->
[![](https://img.shields.io/npm/v/com.coffee.ui-particle?label=openupm&registry_uri=https://package.openupm.com)](https://openupm.com/packages/com.coffee.ui-particle/)
[![](https://img.shields.io/github/v/release/mob-sakai/ParticleEffectForUGUI)](https://github.com/mob-sakai/ParticleEffectForUGUI/releases)
[![](https://img.shields.io/github/license/mob-sakai/ParticleEffectForUGUI.svg)](https://github.com/mob-sakai/ParticleEffectForUGUI/blob/main/LICENSE.md)
![](https://img.shields.io/badge/Unity-2018.2+-57b9d3.svg?style=flat&logo=unity)
![](https://img.shields.io/badge/Unity-2019.3+-57b9d3.svg?style=flat&logo=unity)
![](https://img.shields.io/badge/uGUI_2.0_Ready-57b9d3.svg?style=flat)
![](https://img.shields.io/badge/UPR%2FHDPR_Ready-57b9d3.svg?style=flat)
![](https://github.com/mob-sakai/ParticleEffectForUGUI/actions/workflows/test.yml/badge.svg?branch=develop)
@@ -11,7 +11,7 @@
[![](https://img.shields.io/github/watchers/mob-sakai/ParticleEffectForUGUI.svg?style=social&label=Watch)](https://github.com/mob-sakai/ParticleEffectForUGUI/subscription)
[![](https://img.shields.io/twitter/follow/mob_sakai.svg?label=Follow&style=social)](https://twitter.com/intent/follow?screen_name=mob_sakai)
<< [📝 Description](#-description-) | [📌 Key Features](#-key-features) | [🎮 Demo](#-demo) | [⚙ Installation](#-installation) | [🚀 Usage](#-usage) | [🛠 Development Note](#-development-note) | [🤝 Contributing](#-contributing) >>
<< [📝 Description](#-description-) | [📌 Key Features](#-key-features) | [🎮 Demo](#-demo) | [⚙ Installation](#-installation) | [🔄 Upgrading to 5.x](#-upgrading-from-3x4x-to-5x) | [🚀 Usage](#-usage) | [🛠 Development Note](#-development-note) | [🤝 Contributing](#-contributing) >>
## 📝 Description <!-- omit in toc -->
@@ -27,6 +27,8 @@ You can render, mask, and sort your `ParticleSystems` for UI without the need fo
- [Install via UPM (with Package Manager UI)](#install-via-upm-with-package-manager-ui)
- [Install via UPM (Manually)](#install-via-upm-manually)
- [Install as Embedded Package](#install-as-embedded-package)
- [🔄 Upgrading from v3/v4 to v5](#-upgrading-from-v3v4-to-v5)
- [Breaking Changes](#breaking-changes)
- [🚀 Usage](#-usage)
- [Component: UIParticle](#component-uiparticle)
- [Basic Usage](#basic-usage)
@@ -104,7 +106,7 @@ You can render, mask, and sort your `ParticleSystems` for UI without the need fo
## ⚙ Installation
_This package requires **Unity 2018.3 or later**._
_This package requires **Unity 2019.3 or later**._
#### Install via OpenUPM
@@ -116,16 +118,16 @@ _This package requires **Unity 2018.3 or later**._
```
- To update the package, use Package Manager UI (`Window > Package Manager`) or run the following command with `@{version}`:
```
openupm add com.coffee.ui-particle@4.9.0
openupm add com.coffee.ui-particle@5.0.0
```
#### Install via UPM (with Package Manager UI)
- Click `Window > Package Manager` to open Package Manager UI.
- Click `+ > Add package from git URL...` and input the repository URL: `https://github.com/mob-sakai/ParticleEffectForUGUI.git`
- Click `+ > Add package from git URL...` and input the repository URL: `https://github.com/mob-sakai/ParticleEffectForUGUI.git?path=Packages/src`
![](https://github.com/user-attachments/assets/f88f47ad-c606-44bd-9e86-ee3f72eac548)
- To update the package, change suffix `#{version}` to the target version.
- e.g. `https://github.com/mob-sakai/ParticleEffectForUGUI.git#4.9.0`
- e.g. `https://github.com/mob-sakai/ParticleEffectForUGUI.git?path=Packages/src#5.0.0`
#### Install via UPM (Manually)
@@ -133,22 +135,41 @@ _This package requires **Unity 2018.3 or later**._
```json
{
"dependencies": {
"com.coffee.ui-particle": "https://github.com/mob-sakai/ParticleEffectForUGUI.git",
"com.coffee.ui-particle": "https://github.com/mob-sakai/ParticleEffectForUGUI.git?path=Packages/src",
...
}
}
```
- To update the package, change suffix `#{version}` to the target version.
- e.g. `"com.coffee.ui-particle": "https://github.com/mob-sakai/ParticleEffectForUGUI.git#4.9.0",`
- e.g. `"com.coffee.ui-particle": "https://github.com/mob-sakai/ParticleEffectForUGUI.git?path=Packages/src#5.0.0",`
#### Install as Embedded Package
### Install as Embedded Package
1. Download a source code zip file from [Releases](https://github.com/mob-sakai/ParticleEffectForUGUI/releases) and extract it.
2. Place it in your project's `Packages` directory.
![](https://github.com/mob-sakai/mob-sakai/assets/12690315/0b7484b4-5fca-43b0-a9ef-e5dbd99bcdb4)
- If you want to fix bugs or add features, install it as an embedded package.
- To update the package, you need to re-download it and replace the contents.
1. Download the `Source code (zip)` file from [Releases](https://github.com/mob-sakai/SoftMaskForUGUI/releases) and
extract it.
2. Move the `<extracted_dir>/Packages/src` directory into your project's `Packages` directory.
![](https://github.com/user-attachments/assets/187cbcbe-5922-4ed5-acec-cf19aa17d208)
- You can rename the `src` directory if needed.
- If you intend to fix bugs or add features, installing it as an embedded package is recommended.
- To update the package, re-download it and replace the existing contents.
<br><br>
## 🔄 Upgrading from v3/v4 to v5
### Breaking Changes
- The default value of `UIParticle.scale` has been changed from `10` to `1`.
- `UIParticle` no longer inherits from `MaskableGraphic`.
- If you are installing via git URL, add `?path=Packages/src`.
```json
// v3/v4
"com.coffee.ui-particle": "https://github.com/mob-sakai/ParticleEffectForUGUI.git",
// v5
"com.coffee.ui-particle": "https://github.com/mob-sakai/ParticleEffectForUGUI.git?path=Packages/src",
```
<br><br>
@@ -183,14 +204,9 @@ _This package requires **Unity 2018.3 or later**._
- **Time Scale Multiplier:** Time scale multiplier.
- **Rendering Order**: The ParticleSystem list to be rendered. You can change the order and the materials.
> [!TIPS]
> Press the `Refresh` button to reconstruct the rendering order based on children ParticleSystem's sorting order
**NOTE:** Press the `Refresh` button to reconstruct the rendering order based on children ParticleSystem's sorting order
and z-position.
> [!TIPS]
> When a `GameObject` with this component is selected in the editor, a temporary `ParticleSystem` is added if needed so you can preview the effect in the Scene view.
> The generated `ParticleSystem` is marked with `HideFlags.DontSave`, so it is neither saved nor included in builds.
<br><br>
### Basic Usage
@@ -200,10 +216,6 @@ and z-position.
2. Adjust the ParticleSystem as you like.
![particle1](https://user-images.githubusercontent.com/12690315/95007359-ca385200-0649-11eb-8383-627c9750bda8.png)
> [!Tips]
> Adding a `UIParticle` to the parent is the recommended setup rather than attaching it directly to the `ParticleSystem`.
> When using `ParticleSystem.emission.rateOverDistance`, it is recommended to move the transform of `UIParticle` rather than the `ParticleSystem`.
<br>
### Usage with Your Existing ParticleSystem Prefab
@@ -265,34 +277,13 @@ uiParticle.Stop();
- **Unscaled Time:** Update with unscaled delta time.
- **OnAttracted**: An event called when attracting is complete (per particle).
<br><br>
### Component: ParticleSystemPreviewer
`ParticleSystemPreviewer` is used to preview a ParticleSystem in the editor.
- When a `GameObject` with this component is selected in the editor, a temporary `ParticleSystem` is added if needed so you can preview the effect in the Scene view.
- The generated `ParticleSystem` is marked with `HideFlags.DontSave`, so it is neither saved nor included in builds.
<br><br>
### Project Settings
You can adjust the project-wide settings for `UI Particle`. (`Edit > Project Settings > UI > UI Particle`)
![](https://github.com/user-attachments/assets/befc7f34-fb47-4006-831a-eba79fda11ca)
![](https://github.com/mob-sakai/mob-sakai/releases/download/docs/1782270746550.png)
#### Settings
- **Enable Linear To Gamma**: Automatically correct the color space of the mesh.
#### Editor
- **Hide Generated Component**: Automatically hide the generated `UIParticleRenderer` component and `UIParticle BakingCamera`.
- **Preview On Select**: When selecting UIParticle, a temporary ParticleSystem is generated for preview.
- Click `Edit > Project Settings` to open the Project Settings window and then select `UI > UI Particle` category.
<br><br>

View File

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

View File

@@ -12,33 +12,6 @@ namespace Coffee.UIParticleInternal
/// </summary>
internal static class ComponentExtensions
{
#if !UNITY_2019_2_OR_NEWER
public static bool TryGetComponent<T>(this GameObject self, out T component)
where T : Component
{
if (self == null)
{
component = null;
return false;
}
component = self.GetComponent<T>();
return component != null;
}
public static bool TryGetComponent<T>(this Component self, out T component)
where T : Component
{
if (self == null)
{
component = null;
return false;
}
return self.gameObject.TryGetComponent(out component);
}
#endif
/// <summary>
/// Get components in children of a specific type in the hierarchy of a GameObject.
/// </summary>
@@ -65,7 +38,7 @@ namespace Coffee.UIParticleInternal
private static void GetComponentsInChildren_Internal<T>(this Component self, List<T> results, int depth)
where T : Component
{
if (self == null || results == null || depth < 0) return;
if (!self || results == null || depth < 0) return;
var tr = self.transform;
if (tr.TryGetComponent<T>(out var t))
@@ -86,7 +59,7 @@ namespace Coffee.UIParticleInternal
/// </summary>
public static T GetOrAddComponent<T>(this Component self) where T : Component
{
if (self == null) return null;
if (!self) return null;
return self.TryGetComponent<T>(out var component)
? component
: self.gameObject.AddComponent<T>();
@@ -193,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
public static T GetComponentInParent<T>(this Component self, bool includeInactive) where T : Component
{
if (self == null) return null;
if (!self) return null;
if (!includeInactive) return self.GetComponentInParent<T>();
var current = self.transform;
@@ -213,7 +186,7 @@ namespace Coffee.UIParticleInternal
/// </summary>
internal static bool CanConvertTo<T>(this Object context) where T : MonoBehaviour
{
return context != null && context.GetType() != typeof(T);
return context && context.GetType() != typeof(T);
}
/// <summary>

View File

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

View File

@@ -14,15 +14,6 @@ namespace Coffee.UIParticleInternal
public abstract class PreloadedProjectSettings : ScriptableObject
#if UNITY_EDITOR
{
[Tooltip("When enabled, this settings asset will be added to PlayerSettings.preloadedAssets in build.\n\n" +
"When disable, you should load this settings via Resources, AssetBundles or Addressables to use.")]
[SerializeField]
[Header("Advanced")]
[HideInInspector]
private bool m_PreLoadSettingsInBuild = true;
protected static bool s_BuildingPlayer;
private class Postprocessor : AssetPostprocessor
{
private static void OnPostprocessAllAssets(string[] _, string[] __, string[] ___, string[] ____)
@@ -31,35 +22,12 @@ namespace Coffee.UIParticleInternal
}
}
private class ExcludeFromBuild : IPreprocessBuildWithReport, IPostprocessBuildWithReport
private class PreprocessBuildWithReport : IPreprocessBuildWithReport
{
int IOrderedCallback.callbackOrder => 0;
void IPreprocessBuildWithReport.OnPreprocessBuild(BuildReport report)
{
AssetDatabase.Refresh();
Initialize();
s_BuildingPlayer = true;
foreach (var t in TypeCache.GetTypesDerivedFrom(typeof(PreloadedProjectSettings<>)))
{
var settings = GetDefaultSettings(t);
if (!settings || settings.m_PreLoadSettingsInBuild) continue;
PlayerSettings.SetPreloadedAssets(
PlayerSettings.GetPreloadedAssets()
.Where(x => x && x.GetType() != t)
.ToArray());
Debug.Log($"[PreloadedProjectSettings] Build started: removed '{settings.name}' " +
$"({t.Name}) from PreloadedAssets. " +
$"It will be restored after build completes.");
}
}
void IPostprocessBuildWithReport.OnPostprocessBuild(BuildReport report)
{
s_BuildingPlayer = false;
Initialize();
}
}
@@ -69,21 +37,18 @@ namespace Coffee.UIParticleInternal
foreach (var t in TypeCache.GetTypesDerivedFrom(typeof(PreloadedProjectSettings<>)))
{
var defaultSettings = GetDefaultSettings(t);
if (defaultSettings == null)
{
if (!s_BuildingPlayer)
if (!defaultSettings)
{
// When create a new instance, automatically set it as default settings.
defaultSettings = CreateInstance(t) as PreloadedProjectSettings;
SetDefaultSettings(defaultSettings);
}
}
else if (GetPreloadedSettings(t).Length != 1)
{
if (!s_BuildingPlayer) SetDefaultSettings(defaultSettings);
SetDefaultSettings(defaultSettings);
}
if (defaultSettings != null)
if (defaultSettings)
{
defaultSettings.OnInitialize();
}
@@ -101,22 +66,22 @@ namespace Coffee.UIParticleInternal
private static Object[] GetPreloadedSettings(Type type)
{
return PlayerSettings.GetPreloadedAssets()
.Where(x => x != null && x.GetType() == type)
.Where(x => x && x.GetType() == type)
.ToArray();
}
protected static PreloadedProjectSettings GetDefaultSettings(Type type)
{
return GetPreloadedSettings(type).FirstOrDefault() as PreloadedProjectSettings
?? AssetDatabase.FindAssets($"t:{type.Name}")
?? AssetDatabase.FindAssets($"t:{nameof(PreloadedProjectSettings)}")
.Select(AssetDatabase.GUIDToAssetPath)
.Select(AssetDatabase.LoadAssetAtPath<PreloadedProjectSettings>)
.FirstOrDefault(x => x != null && x.GetType() == type);
.FirstOrDefault(x => x && x.GetType() == type);
}
protected static void SetDefaultSettings(PreloadedProjectSettings asset)
{
if (asset == null) return;
if (!asset) return;
var type = asset.GetType();
if (string.IsNullOrEmpty(AssetDatabase.GetAssetPath(asset)))
@@ -138,7 +103,7 @@ namespace Coffee.UIParticleInternal
var preloadedAssets = PlayerSettings.GetPreloadedAssets();
var projectSettings = GetPreloadedSettings(type);
PlayerSettings.SetPreloadedAssets(preloadedAssets
.Where(x => x != null)
.Where(x => x)
.Except(projectSettings.Except(new[] { asset }))
.Append(asset)
.Distinct()
@@ -155,35 +120,6 @@ namespace Coffee.UIParticleInternal
{
}
}
internal abstract class PreloadedProjectSettingsEditor : Editor
{
private SerializedProperty _preLoadSettingsInBuild;
protected virtual void OnEnable()
{
_preLoadSettingsInBuild = serializedObject.FindProperty("m_PreLoadSettingsInBuild");
}
protected void DrawPreLoadSettingsInBuild(string packageName)
{
EditorGUILayout.PropertyField(_preLoadSettingsInBuild);
if (!_preLoadSettingsInBuild.boolValue)
{
EditorGUILayout.BeginHorizontal();
EditorGUILayout.HelpBox(
$"{target.GetType().Name} asset will not be built in.\n" +
$"please load manually from Resources, AssetBundle, or Addressables before using {packageName}.",
MessageType.Warning);
if (GUILayout.Button("Ping"))
{
EditorGUIUtility.PingObject(target);
}
EditorGUILayout.EndHorizontal();
}
}
}
#else
{
}
@@ -197,33 +133,31 @@ namespace Coffee.UIParticleInternal
#if UNITY_EDITOR
private string _jsonText;
public static bool hasInstance => s_Instance != null;
public static bool hasInstance => s_Instance;
public static T instance
{
get
{
if (s_Instance != null) return s_Instance;
if (s_Instance) return s_Instance;
s_Instance = GetDefaultSettings(typeof(T)) as T;
if (s_Instance != null) return s_Instance;
if (s_Instance) return s_Instance;
s_Instance = CreateInstance<T>();
if (s_Instance == null)
if (!s_Instance)
{
s_Instance = null;
return s_Instance;
}
if (!s_BuildingPlayer) SetDefaultSettings(s_Instance);
SetDefaultSettings(s_Instance);
return s_Instance;
}
}
private void OnPlayModeStateChanged(PlayModeStateChange state)
{
if (!this) return;
switch (state)
{
case PlayModeStateChange.ExitingEditMode:
@@ -240,7 +174,7 @@ namespace Coffee.UIParticleInternal
}
}
#else
public static T instance => s_Instance != null ? s_Instance : s_Instance = CreateInstance<T>();
public static T instance => s_Instance ? s_Instance : s_Instance = CreateInstance<T>();
#endif
/// <summary>
@@ -249,7 +183,7 @@ namespace Coffee.UIParticleInternal
protected virtual void OnEnable()
{
#if UNITY_EDITOR
var isDefaultSettings = s_Instance == null || s_Instance == this || GetDefaultSettings(typeof(T)) == this;
var isDefaultSettings = !s_Instance || s_Instance == this || GetDefaultSettings(typeof(T)) == this;
if (!isDefaultSettings)
{
DestroyImmediate(this, true);
@@ -257,12 +191,9 @@ namespace Coffee.UIParticleInternal
}
EditorApplication.playModeStateChanged += OnPlayModeStateChanged;
#else
if (s_Instance && s_Instance != this)
{
Destroy(s_Instance);
}
#endif
if (s_Instance) return;
s_Instance = this as T;
}
@@ -291,7 +222,7 @@ namespace Coffee.UIParticleInternal
public override void OnGUI(string searchContext)
{
if (_target == null)
if (!_target)
{
if (_editor)
{

View File

@@ -14,7 +14,7 @@ namespace Coffee.UIParticleInternal
UIExtraCallbacks.onLateAfterCanvasRebuild += ClearAllCache;
}
#if UNITY_EDITOR && UNITY_2019_2_OR_NEWER
#if UNITY_EDITOR
[RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.SubsystemRegistration)]
private static void Clear()
{

View File

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

View File

@@ -11,7 +11,7 @@ using Conditional = System.Diagnostics.ConditionalAttribute;
namespace Coffee.UIParticleInternal
{
internal static class Logger
internal static class Logging
{
#if !ENABLE_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)
{
if (!enable) return;
Log_Internal(LogType.Log, tag, message, context != null ? context : tag as Object);
Log_Internal(LogType.Log, tag, message, context ? context : tag as Object);
}
#if !ENABLE_COFFEE_LOGGER
@@ -56,7 +56,7 @@ namespace Coffee.UIParticleInternal
#endif
public static void Log(object tag, object message, Object context = null)
{
Log_Internal(LogType.Log, tag, message, context != null ? context : tag as Object);
Log_Internal(LogType.Log, tag, message, context ? context : tag as Object);
}
#if !ENABLE_COFFEE_LOGGER
@@ -64,13 +64,13 @@ namespace Coffee.UIParticleInternal
#endif
public static void LogWarning(object tag, object message, Object context = null)
{
Log_Internal(LogType.Warning, tag, message, context != null ? context : tag as Object);
Log_Internal(LogType.Warning, tag, message, context ? context : tag as Object);
}
public static void LogError(object tag, object message, Object context = null)
{
#if ENABLE_COFFEE_LOGGER
Log_Internal(LogType.Error, tag, message, context != null ? context : tag as Object);
Log_Internal(LogType.Error, tag, message, context ? context : tag as Object);
#else
Debug.LogError($"{tag}: {message}", context);
#endif

View File

@@ -1,5 +1,5 @@
fileFormatVersion: 2
guid: bc1207b657ed74ec19e459664d06925f
guid: 8255313895da84e7cbdc876be3795334
MonoImporter:
externalObjects: {}
serializedVersion: 2

View File

@@ -13,9 +13,7 @@ namespace Coffee.UIParticleInternal
public static int count => s_Repository.count;
public static Func<string, Shader> onShaderFind = Shader.Find;
#if UNITY_EDITOR && UNITY_2019_2_OR_NEWER
#if UNITY_EDITOR
[RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.SubsystemRegistration)]
public static void Clear()
{
@@ -50,7 +48,7 @@ namespace Coffee.UIParticleInternal
public static void Get(Hash128 hash, ref Material material, string shaderName)
{
Profiler.BeginSample("(COF)[MaterialRepository] Get");
s_Repository.Get(hash, ref material, x => new Material(onShaderFind(x))
s_Repository.Get(hash, ref material, x => new Material(Shader.Find(x))
{
hideFlags = HideFlags.DontSave | HideFlags.NotEditable
}, shaderName);
@@ -63,7 +61,7 @@ namespace Coffee.UIParticleInternal
public static void Get(Hash128 hash, ref Material material, string shaderName, string[] keywords)
{
Profiler.BeginSample("(COF)[MaterialRepository] Get");
s_Repository.Get(hash, ref material, x => new Material(onShaderFind(x.shaderName))
s_Repository.Get(hash, ref material, x => new Material(Shader.Find(x.shaderName))
{
hideFlags = HideFlags.DontSave | HideFlags.NotEditable,
shaderKeywords = x.keywords

View File

@@ -20,9 +20,7 @@ namespace Coffee.UIParticleInternal
{
public static T[] FindObjectsOfType<T>() where T : Object
{
#if UNITY_6000_4_OR_NEWER
return Object.FindObjectsByType<T>(FindObjectsInactive.Include);
#elif UNITY_2023_1_OR_NEWER
#if UNITY_2023_1_OR_NEWER
return Object.FindObjectsByType<T>(FindObjectsInactive.Include, FindObjectsSortMode.None);
#else
return Object.FindObjectsOfType<T>();
@@ -31,7 +29,7 @@ namespace Coffee.UIParticleInternal
public static void Destroy(Object obj)
{
if (obj == null) return;
if (!obj) return;
#if UNITY_EDITOR
if (!Application.isPlaying)
{
@@ -46,19 +44,24 @@ namespace Coffee.UIParticleInternal
public static void DestroyImmediate(Object obj)
{
if (obj == null) return;
if (!obj) return;
#if UNITY_EDITOR
Object.DestroyImmediate(obj, true);
#else
Object.Destroy(obj);
if (Application.isEditor)
{
Object.DestroyImmediate(obj);
}
else
#endif
{
Object.Destroy(obj);
}
}
[Conditional("UNITY_EDITOR")]
public static void SetDirty(Object obj)
{
#if UNITY_EDITOR
if (obj == null) return;
if (!obj) return;
EditorUtility.SetDirty(obj);
#endif
}
@@ -109,16 +112,16 @@ namespace Coffee.UIParticleInternal
{
if (Misc.isBatchOrBuilding) return;
var types = TypeCache.GetTypesWithAttribute(typeof(IconAttribute));
var types = TypeCache.GetTypesWithAttribute<IconAttribute>();
var scripts = MonoImporter.GetAllRuntimeMonoScripts();
foreach (var type in types)
{
var script = scripts.FirstOrDefault(x => x.GetClass() == type);
if (script == null) continue;
if (!script) continue;
var path = type.GetCustomAttribute<IconAttribute>()?._path;
var icon = AssetDatabase.LoadAssetAtPath<Texture2D>(path);
if (icon == null) continue;
if (!icon) continue;
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.
Logger.Log(this, $"A new instance is created (pooled: {_pool.CountInactive}, created: {_pool.CountAll}).");
Logging.Log(this, $"A new instance is created (pooled: {_pool.CountInactive}, created: {_pool.CountAll}).");
return _pool.Get();
}
@@ -47,7 +47,7 @@ namespace Coffee.UIParticleInternal
if (instance == null) return; // Ignore if already pooled or null.
_pool.Release(instance);
Logger.Log(this, $"An instance is released (pooled: {_pool.CountInactive}, created: {_pool.CountAll}).");
Logging.Log(this, $"An instance is released (pooled: {_pool.CountInactive}, created: {_pool.CountAll}).");
instance = default; // Set the reference to null.
}
#else
@@ -80,7 +80,7 @@ namespace Coffee.UIParticleInternal
}
// If there are no instances in the pool, create a new one.
Logger.Log(this, $"A new instance is created (pooled: {_pool.Count}, created: {++_count}).");
Logging.Log(this, $"A new instance is created (pooled: {_pool.Count}, created: {++_count}).");
return _onCreate();
}
@@ -94,7 +94,7 @@ namespace Coffee.UIParticleInternal
_onReturn(instance); // Return the instance to the pool.
_pool.Push(instance);
Logger.Log(this, $"An instance is released (pooled: {_pool.Count}, created: {_count}).");
Logging.Log(this, $"An instance is released (pooled: {_pool.Count}, created: {_count}).");
instance = default; // Set the reference to null.
}
#endif

View File

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

View File

@@ -1,88 +0,0 @@
#if !UNITY_2019_2_OR_NEWER
using System;
using System.Collections.Generic;
using System.Reflection;
namespace Coffee.UIParticleInternal
{
public static class TypeCache
{
private static readonly object s_Lock = new object();
private static readonly Dictionary<Type, Type[]> s_DerivedTypesCache = new Dictionary<Type, Type[]>();
private static readonly Dictionary<Type, Type[]> s_AttributeTypesCache = new Dictionary<Type, Type[]>();
public static IEnumerable<Type> GetTypesDerivedFrom(Type baseType)
{
lock (s_Lock)
{
if (s_DerivedTypesCache.TryGetValue(baseType, out var cached))
{
return cached;
}
var types = new List<Type>();
foreach (var t in GetAllLoadableTypes())
{
if (t != baseType && baseType.IsAssignableFrom(t))
{
types.Add(t);
}
}
return s_DerivedTypesCache[baseType] = types.ToArray();
}
}
public static IEnumerable<Type> GetTypesWithAttribute(Type attr)
{
lock (s_Lock)
{
if (s_AttributeTypesCache.TryGetValue(attr, out var cached))
{
return cached;
}
var types = new List<Type>();
foreach (var t in GetAllLoadableTypes())
{
if (t.GetCustomAttributes(attr, inherit: true).Length > 0)
{
types.Add(t);
}
}
return s_AttributeTypesCache[attr] = types.ToArray();
}
}
private static IEnumerable<Type> GetAllLoadableTypes()
{
foreach (var assembly in AppDomain.CurrentDomain.GetAssemblies())
{
Type[] types;
try
{
types = assembly.GetTypes();
}
catch (ReflectionTypeLoadException ex)
{
types = ex.Types;
}
if (types == null)
{
continue;
}
foreach (var t in types)
{
if (t != null)
{
yield return t;
}
}
}
}
}
}
#endif

View File

@@ -1,5 +1,4 @@
using System;
using System.Reflection;
using UnityEditor;
using UnityEngine;
using UnityEngine.UI;
@@ -21,7 +20,7 @@ namespace Coffee.UIParticleInternal
static UIExtraCallbacks()
{
Canvas.willRenderCanvases += OnBeforeCanvasRebuild;
Logger.LogMulticast(typeof(Canvas), "willRenderCanvases", message: "ctor");
Logging.LogMulticast(typeof(Canvas), "willRenderCanvases", message: "ctor");
}
/// <summary>
@@ -68,17 +67,9 @@ namespace Coffee.UIParticleInternal
if (s_IsInitializedAfterCanvasRebuild) return;
s_IsInitializedAfterCanvasRebuild = true;
// Explicitly set `Canvas.willRenderCanvases += CanvasUpdateRegistry.PerformUpdate`.
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;
Logger.LogMulticast(typeof(Canvas), "willRenderCanvases",
Logging.LogMulticast(typeof(Canvas), "willRenderCanvases",
message: "InitializeAfterCanvasRebuild");
}

View File

@@ -1,222 +0,0 @@
using System.Collections.Generic;
using System.Linq;
using Coffee.UIParticleInternal;
using UnityEditor;
using UnityEngine;
namespace Coffee.UIExtensions
{
[Icon("Packages/com.coffee.ui-particle/Editor/UIParticleIcon.png")]
[ExecuteAlways]
internal class ParticleSystemPreviewer : MonoBehaviour
{
// Do nothing.
}
#if UNITY_EDITOR
[CustomEditor(typeof(ParticleSystemPreviewer))]
[CanEditMultipleObjects]
internal class ParticleSystemPreviewerEditor : Editor
{
private GameObject[] _gameObjects;
private void OnEnable()
{
_gameObjects = targets.OfType<ParticleSystemPreviewer>().Select(x => x.gameObject).ToArray();
ParticleSystemPreviewSystem.Register(_gameObjects);
}
public override void OnInspectorGUI()
{
base.OnInspectorGUI();
ParticleSystemPreviewSystem.DrawWarningForTemporary(_gameObjects);
ParticleSystemPreviewSystem.DrawWarningForPermanent(_gameObjects);
}
}
/// <summary>
/// This class manages temporary ParticleSystems for preview purposes.
/// When previewing in the editor, it is common to place an empty ParticleSystem as the root, but it consumes memory at runtime if included in the build.
/// The temporary ParticleSystems created by this class only exist when the specified GameObject is selected, and are automatically deleted when the selection is cleared.
/// </summary>
internal class ParticleSystemPreviewSystem : ScriptableSingleton<ParticleSystemPreviewSystem>
{
private const HideFlags k_TemporaryHideFlags = HideFlags.DontSave | HideFlags.NotEditable;
[SerializeField]
private List<GameObject> m_PreviewObjects = new List<GameObject>();
/// <summary>
/// Adds a temporary ParticleSystem to the specified GameObject for preview purposes.
/// </summary>
public static void Register(GameObject[] targets)
{
foreach (var target in targets)
{
Register(target);
}
}
/// <summary>
/// Adds a temporary ParticleSystem to the specified GameObject for preview purposes.
/// </summary>
public static void Register(GameObject target)
{
if (!target) return;
if (EditorApplication.isPlaying) return;
if (instance.m_PreviewObjects.Contains(target)) return;
if (target.TryGetComponent<ParticleSystem>(out var _)) return;
// Create temporary ParticleSystem for preview.
var ps = target.AddComponent<ParticleSystem>();
ps.hideFlags = k_TemporaryHideFlags;
var emission = ps.emission;
emission.enabled = false;
var shape = ps.shape;
shape.enabled = false;
if (target.TryGetComponent<ParticleSystemRenderer>(out var psr))
{
psr.enabled = false;
psr.hideFlags = k_TemporaryHideFlags;
}
instance.m_PreviewObjects.Add(target);
EditorUtility.SetDirty(target);
}
/// <summary>
/// Removes the temporary ParticleSystem associated with the specified GameObject.
/// </summary>
/// <param name="target"></param>
public static void Unregister(GameObject target)
{
if (!target) return;
var index = instance.m_PreviewObjects.IndexOf(target);
if (index < 0) return;
instance.m_PreviewObjects.RemoveAt(index);
if (HasTemporaryParticleSystem(target))
{
RemoveParticleSystem(target);
}
}
/// <summary>
/// Removes the temporary ParticleSystem associated with the specified GameObject.
/// </summary>
/// <param name="target"></param>
private static void RemoveParticleSystem(GameObject target)
{
if (target.TryGetComponent<ParticleSystem>(out var ps))
{
Misc.DestroyImmediate(ps);
EditorUtility.SetDirty(target);
}
if (target.TryGetComponent<ParticleSystem>(out var psr))
{
Misc.DestroyImmediate(psr);
EditorUtility.SetDirty(target);
}
}
/// <summary>
/// Checks if the specified GameObject has a temporary ParticleSystem.
/// </summary>
private static bool HasTemporaryParticleSystem(GameObject target)
{
return target
&& instance.m_PreviewObjects.Contains(target)
&& target.TryGetComponent<ParticleSystem>(out var ps)
&& ps.hideFlags == k_TemporaryHideFlags;
}
/// <summary>
/// Checks if the specified GameObject has a permanent ParticleSystem.
/// </summary>
private static bool HasPermanentParticleSystem(GameObject target)
{
return target
&& target.TryGetComponent<ParticleSystem>(out var ps)
&& ps.hideFlags != k_TemporaryHideFlags;
}
private void OnEnable()
{
Selection.selectionChanged -= OnSelectionChanged;
Selection.selectionChanged += OnSelectionChanged;
}
private void OnDisable()
{
Selection.selectionChanged -= OnSelectionChanged;
}
private void OnSelectionChanged()
{
var selectedGameObjects = Selection.gameObjects;
for (var i = m_PreviewObjects.Count - 1; 0 <= i; i--)
{
var go = m_PreviewObjects[i];
if (!go)
{
m_PreviewObjects.RemoveAt(i);
}
else if (!selectedGameObjects.Contains(go))
{
Unregister(go);
}
}
}
public static void DrawWarningForTemporary(GameObject[] gameObjects)
{
if (gameObjects == null || gameObjects.Length == 0 || !gameObjects.Any(HasTemporaryParticleSystem)) return;
if (WarningButton("The temporary ParticleSystem for preview is attached.\n" +
"It will be removed when exiting edit mode.", "Remove"))
{
foreach (var go in gameObjects)
{
if (HasTemporaryParticleSystem(go))
{
RemoveParticleSystem(go);
}
}
}
}
public static void DrawWarningForPermanent(GameObject[] gameObjects)
{
if (gameObjects == null || gameObjects.Length == 0 || !gameObjects.Any(HasPermanentParticleSystem)) return;
if (WarningButton("The permanent ParticleSystem is attached.\n" +
"It will be included in build.", "Remove"))
{
foreach (var go in gameObjects)
{
if (HasPermanentParticleSystem(go))
{
RemoveParticleSystem(go);
Unregister(go);
Register(go);
}
}
}
}
private static bool WarningButton(string message, string buttonText)
{
EditorGUILayout.BeginHorizontal();
EditorGUILayout.HelpBox(message, MessageType.Warning, true);
var clicked = GUILayout.Button(EditorGUIUtility.TrTempContent(buttonText));
EditorGUILayout.EndHorizontal();
return clicked;
}
}
#endif
}

View File

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

View File

@@ -3,13 +3,12 @@ using System.Collections.Generic;
using System.Runtime.CompilerServices;
using Coffee.UIParticleInternal;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.Rendering;
using UnityEngine.Serialization;
using UnityEngine.UI;
using Random = UnityEngine.Random;
[assembly: InternalsVisibleTo("Coffee.UIParticle.Editor")]
[assembly: InternalsVisibleTo("Coffee.UIParticle.Editor.Tests")]
[assembly: InternalsVisibleTo("Coffee.UIParticle.PerformanceDemo")]
[assembly: InternalsVisibleTo("Coffee.UIParticle.Demo")]
@@ -18,11 +17,11 @@ namespace Coffee.UIExtensions
/// <summary>
/// Render maskable and sortable particle effect ,without Camera, RenderTexture or Canvas.
/// </summary>
[Icon("Packages/com.coffee.ui-particle/Editor/UIParticleIcon.png")]
[Icon("Packages/com.coffee.ui-particle/Icons/UIParticleIcon.png")]
[ExecuteAlways]
[RequireComponent(typeof(RectTransform))]
[RequireComponent(typeof(CanvasRenderer))]
public class UIParticle : MaskableGraphic, ISerializationCallbackReceiver
public class UIParticle : UIBehaviour, ISerializationCallbackReceiver
{
public enum AutoScalingMode
{
@@ -64,7 +63,7 @@ namespace Coffee.UIExtensions
[Tooltip("Scale the rendering particles. When the `3D` toggle is enabled, 3D scale (x, y, z) is supported.")]
[SerializeField]
private Vector3 m_Scale3D = new Vector3(10, 10, 10);
private Vector3 m_Scale3D = new Vector3(1, 1, 1);
[Tooltip("If you want to update material properties (e.g. _MainTex_ST, _Color) in AnimationClip, " +
"use this to mark as animatable.")]
@@ -125,20 +124,48 @@ namespace Coffee.UIExtensions
[Tooltip("Time scale multiplier.")]
private float m_TimeScaleMultiplier = 1;
[SerializeField]
private bool m_Maskable = true;
private readonly List<UIParticleRenderer> _renderers = new List<UIParticleRenderer>();
private Camera _bakeCamera;
private Canvas _canvas;
private int _groupId;
private bool _isScaleStored;
private Vector3 _storedScale;
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>
@@ -324,15 +351,15 @@ namespace Coffee.UIExtensions
public Vector3 parentScale { get; private set; }
public Vector3 canvasScale { get; private set; }
private Vector3 canvasScale { get; set; }
protected override void OnEnable()
{
_isScaleStored = false;
ResetGroupId();
UIParticleUpdater.Register(this);
RegisterDirtyMaterialCallback(UpdateRendererMaterial);
//
if (0 < particles.Count)
{
RefreshParticles(particles);
@@ -342,7 +369,7 @@ namespace Coffee.UIExtensions
RefreshParticles();
}
base.OnEnable();
UpdateRendererMaterial();
}
/// <summary>
@@ -358,11 +385,16 @@ namespace Coffee.UIExtensions
_isScaleStored = false;
UIParticleUpdater.Unregister(this);
_renderers.RemoveAll(r => r == null);
_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>
@@ -372,6 +404,14 @@ 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;
}
void ISerializationCallbackReceiver.OnBeforeSerialize()
{
}
@@ -472,7 +512,7 @@ namespace Coffee.UIExtensions
for (var i = 0; i < _renderers.Count; i++)
{
var r = _renderers[i];
if (r == null || r.material == null) continue;
if (!r || !r.material) continue;
result.Add(r.material);
}
}
@@ -490,7 +530,7 @@ namespace Coffee.UIExtensions
/// </summary>
public void SetParticleSystemInstance(GameObject instance, bool destroyOldParticles)
{
if (instance == null) return;
if (!instance) return;
var childCount = transform.childCount;
for (var i = 0; i < childCount; i++)
@@ -519,7 +559,7 @@ namespace Coffee.UIExtensions
/// </summary>
public void SetParticleSystemPrefab(GameObject prefab)
{
if (prefab == null) return;
if (!prefab) return;
SetParticleSystemInstance(Instantiate(prefab.gameObject), true);
}
@@ -539,17 +579,12 @@ namespace Coffee.UIExtensions
/// </summary>
private void RefreshParticles(GameObject root)
{
if (root == null) return;
if (!root) return;
root.GetComponentsInChildren(true, particles);
for (var i = particles.Count - 1; 0 <= i; i--)
{
var ps = particles[i];
if (!ps
#if UNITY_EDITOR
|| ps.hideFlags == HideFlags.HideAndDontSave // Dummy ParticleSystems for preview.
|| ps.gameObject.CompareTag("EditorOnly") // Ignore "EditorOnly" tagged ParticleSystems.
#endif
|| ps.GetComponentInParent<UIParticle>(true) != this) // Ignore ParticleSystems that are not under this UIParticle.
if (!ps || ps.GetComponentInParent<UIParticle>(true) != this)
{
particles.RemoveAt(i);
}
@@ -597,7 +632,7 @@ namespace Coffee.UIExtensions
for (var i = 0; i < particleSystems.Count; i++)
{
var ps = particleSystems[i];
if (ps == null) continue;
if (!ps) continue;
var mainEmitter = ps.GetMainEmitter(particleSystems);
GetRenderer(j++).Set(this, ps, false, mainEmitter);
@@ -648,7 +683,7 @@ namespace Coffee.UIExtensions
for (var i = 0; i < _renderers.Count; i++)
{
var r = _renderers[i];
if (r != null) continue;
if (r) continue;
RefreshParticles(particles);
break;
@@ -658,7 +693,7 @@ namespace Coffee.UIExtensions
for (var i = 0; i < _renderers.Count; i++)
{
var r = _renderers[i];
if (r == null) continue;
if (!r) continue;
r.UpdateMesh(bakeCamera);
}
@@ -671,23 +706,12 @@ 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++)
{
var r = _renderers[i];
if (r == null) continue;
if (!r) continue;
r.maskable = maskable;
r.SetMaterialDirty();
}
@@ -700,7 +724,7 @@ namespace Coffee.UIExtensions
_renderers.Add(UIParticleRenderer.AddRenderer(this, index));
}
if (_renderers[index] == null)
if (!_renderers[index])
{
_renderers[index] = UIParticleRenderer.AddRenderer(this, index);
}
@@ -710,13 +734,13 @@ namespace Coffee.UIExtensions
private Camera GetBakeCamera()
{
if (canvas == null) return Camera.main;
if (!canvas) return Camera.main;
if (!useCustomView && canvas.renderMode != RenderMode.ScreenSpaceOverlay && canvas.rootCanvas.worldCamera)
{
return canvas.rootCanvas.worldCamera;
}
if (_bakeCamera != null)
if (_bakeCamera)
{
_bakeCamera.orthographicSize = useCustomView ? customViewSize : 10;
return _bakeCamera;
@@ -735,7 +759,7 @@ namespace Coffee.UIExtensions
}
// Create baking camera.
if (_bakeCamera == null)
if (!_bakeCamera)
{
var go = new GameObject("[generated] UIParticle BakingCamera");
go.SetActive(false);

View File

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

View File

@@ -2,22 +2,20 @@
using Coffee.UIParticleInternal;
using UnityEditor;
using UnityEngine;
using UnityEngine.Serialization;
namespace Coffee.UIExtensions
{
[Icon("Packages/com.coffee.ui-particle/Icons/UIParticleIcon.png")]
public class UIParticleProjectSettings : PreloadedProjectSettings<UIParticleProjectSettings>
{
[Header("Setting")]
[SerializeField]
[Tooltip("Automatically correct the color space of the mesh.")]
[FormerlySerializedAs("m_EnableLinearToGamma")]
internal bool m_AutoColorCorrection = true;
internal bool m_EnableLinearToGamma = true;
public static bool autoColorCorrection
public static bool enableLinearToGamma
{
get => instance.m_AutoColorCorrection;
set => instance.m_AutoColorCorrection = value;
get => instance.m_EnableLinearToGamma;
set => instance.m_EnableLinearToGamma = value;
}
@@ -28,16 +26,10 @@ namespace Coffee.UIExtensions
[SerializeField]
private bool m_HideGeneratedObjects = true;
[Tooltip("When selecting UIParticle, a temporary ParticleSystem is generated for preview.")]
[SerializeField]
private bool m_PreviewOnSelect = true;
internal static HideFlags globalHideFlags => instance.m_HideGeneratedObjects
public static HideFlags globalHideFlags => instance.m_HideGeneratedObjects
? HideFlags.DontSave | HideFlags.NotEditable | HideFlags.HideInHierarchy | HideFlags.HideInInspector
: HideFlags.DontSave | HideFlags.NotEditable;
internal static bool s_PreviewOnSelectOnSelect => instance.m_PreviewOnSelect;
#if UNITY_EDITOR
[SettingsProvider]
private static SettingsProvider CreateSettingsProvider()

View File

@@ -5,7 +5,7 @@ MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {fileID: 2800000, guid: 5f0675613942149309588d556e33d990, type: 3}
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -15,7 +15,7 @@ using UnityEngine.UI;
namespace Coffee.UIExtensions
{
[Icon("Packages/com.coffee.ui-particle/Editor/UIParticleIcon.png")]
[Icon("Packages/com.coffee.ui-particle/Icons/UIParticleIcon.png")]
[ExecuteAlways]
[RequireComponent(typeof(RectTransform))]
[RequireComponent(typeof(CanvasRenderer))]
@@ -30,7 +30,6 @@ namespace Coffee.UIExtensions
private int _index;
private bool _isPrevStored;
private bool _isTrail;
private bool _meshCleared;
private Bounds _lastBounds;
private Material _materialForRendering;
private Material _modifiedMaterial;
@@ -56,7 +55,7 @@ namespace Coffee.UIExtensions
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[3] = transform.TransformPoint(_lastBounds.max.x, _lastBounds.min.y, 0);
if (canvas != null)
if (canvas)
{
var worldToLocalMatrix = canvas.rootCanvas.transform.worldToLocalMatrix;
for (var i = 0; i < 4; ++i)
@@ -96,7 +95,7 @@ namespace Coffee.UIExtensions
{
get
{
if (_materialForRendering == null)
if (!_materialForRendering)
{
_materialForRendering = base.materialForRendering;
}
@@ -107,7 +106,7 @@ namespace Coffee.UIExtensions
public void Reset(int index = -1)
{
if (_renderer != null)
if (_renderer)
{
_renderer.enabled = true;
}
@@ -122,7 +121,7 @@ namespace Coffee.UIExtensions
}
//_emitter = null;
if (isActiveAndEnabled)
if (this && isActiveAndEnabled)
{
material = null;
canvasRenderer.Clear();
@@ -141,7 +140,7 @@ namespace Coffee.UIExtensions
base.OnEnable();
hideFlags = UIParticleProjectSettings.globalHideFlags;
if (s_CombineInstances[0].mesh == null)
if (!s_CombineInstances[0].mesh)
{
s_CombineInstances[0].mesh = new Mesh
{
@@ -206,9 +205,9 @@ namespace Coffee.UIExtensions
}
var hash = new Hash128(
modifiedMaterial ? (uint)modifiedMaterial.GetHashCode() : 0,
texture ? (uint)texture.GetHashCode() : 0,
0 < _parent.m_AnimatableProperties.Length ? (uint)GetHashCode() : 0,
modifiedMaterial ? (uint)modifiedMaterial.GetInstanceID() : 0,
texture ? (uint)texture.GetInstanceID() : 0,
0 < _parent.m_AnimatableProperties.Length ? (uint)GetInstanceID() : 0,
#if UNITY_EDITOR
(uint)EditorJsonUtility.ToJson(modifiedMaterial).GetHashCode()
#else
@@ -284,40 +283,21 @@ namespace Coffee.UIExtensions
|| !transform.lossyScale.GetScaled(_parent.scale3DForCalc).IsVisible() // Scale is not visible.
|| (!_particleSystem.IsAlive() && !_particleSystem.isPlaying) // No particle.
|| (_isTrail && !_particleSystem.trails.enabled) // Trail, but it is not enabled.
#if UNITY_2018_3_OR_NEWER
|| canvasRenderer.GetInheritedAlpha() <
0.01f // #102: Do not bake particle system to mesh when the alpha is zero.
#endif
)
{
// Skip clearing the mesh if it's already cleared.
if (_meshCleared) return;
Profiler.BeginSample("[UIParticleRenderer] Clear Mesh");
workerMesh.Clear();
canvasRenderer.SetMesh(workerMesh);
_lastBounds = new Bounds();
_meshCleared = true;
Profiler.EndSample();
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 scale = GetWorldScale();
var psPos = _particleSystem.transform.position;
@@ -335,13 +315,6 @@ namespace Coffee.UIExtensions
#endif
{
ResolveResolutionChange(psPos, scale);
// fix: second and subsequent bursts not displayed when world simulation and non-looping. (#326)
if (!_particleSystem.IsLocalSpace() && !main.loop && _particleSystem.time == 0)
{
_delay = true;
}
Simulate(scale, _parent.isPaused || _delay);
if (_delay && !_parent.isPaused)
@@ -444,7 +417,7 @@ namespace Coffee.UIExtensions
_lastBounds = bounds;
// Convert linear color to gamma color.
if (UIParticleProjectSettings.autoColorCorrection && canvas.ShouldGammaToLinearInMesh())
if (UIParticleProjectSettings.enableLinearToGamma && canvas.ShouldGammaToLinearInMesh())
{
workerMesh.LinearToGamma();
}
@@ -737,7 +710,7 @@ namespace Coffee.UIExtensions
if (s_Mpb.isEmpty) return;
// #41: Copy the value from MaterialPropertyBlock to CanvasRenderer
if (materialForRendering == null) return;
if (!materialForRendering) return;
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)
{
if (particle == null) return;
if (!particle) return;
s_ActiveParticles.Add(particle);
}
public static void Unregister(UIParticle particle)
{
if (particle == null) return;
if (!particle) return;
s_ActiveParticles.Remove(particle);
}
public static void Register(UIParticleAttractor attractor)
{
if (attractor == null) return;
if (!attractor) return;
s_ActiveAttractors.Add(attractor);
}
public static void Unregister(UIParticleAttractor attractor)
{
if (attractor == null) return;
if (!attractor) return;
s_ActiveAttractors.Remove(attractor);
}
@@ -71,7 +71,7 @@ namespace Coffee.UIExtensions
for (var i = 0; i < s_ActiveParticles.Count; i++)
{
var uip = s_ActiveParticles[i];
if (uip == null || uip.canvas == null || !uip.isPrimary || !s_UpdatedGroupIds.Add(uip.groupId)) continue;
if (!uip || !uip.canvas || !uip.isPrimary || !s_UpdatedGroupIds.Add(uip.groupId)) continue;
uip.UpdateTransformScale();
uip.UpdateRenderers();
@@ -81,7 +81,7 @@ namespace Coffee.UIExtensions
for (var i = 0; i < s_ActiveParticles.Count; i++)
{
var uip = s_ActiveParticles[i];
if (uip == null || uip.canvas == null) continue;
if (!uip || !uip.canvas) continue;
uip.UpdateTransformScale();
@@ -125,7 +125,7 @@ namespace Coffee.UIExtensions
var uip = s_ActiveParticles[i];
if (!uip.useMeshSharing || uip.groupId != groupId) continue;
if (uip.isPrimary) return uip;
if (primary == null && uip.canSimulate) primary = uip;
if (!primary && uip.canSimulate) primary = uip;
}
return primary;

View File

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

View File

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

View File

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

View File

@@ -40,8 +40,12 @@
Lighting Off
ZWrite Off
ZTest [unity_GUIZTestMode]
Fog { Mode Off }
Fog
{
Mode Off
}
Blend One One
ColorMask [_ColorMask]
Pass
@@ -72,7 +76,6 @@
fixed4 color : COLOR;
float2 texcoord : TEXCOORD0;
float4 worldPosition : TEXCOORD1;
float4 mask : TEXCOORD2;
UNITY_VERTEX_OUTPUT_STEREO
};
@@ -81,43 +84,16 @@
float4 _MainTex_ST;
fixed4 _TextureSampleAdd;
float4 _ClipRect;
float _UIMaskSoftnessX;
float _UIMaskSoftnessY;
int _UIVertexColorAlwaysGammaSpace;
half3 _UIGammaToLinear(half3 value)
{
half3 low = 0.0849710 * value - 0.000163029;
half3 high = value * (value * (value * 0.265885 + 0.736584) - 0.00980184) + 0.00319697;
// We should be 0.5 away from any actual gamma value stored in an 8 bit channel
const half3 split = (half3)0.0725490; // Equals 18.5 / 255
return (value < split) ? low : high;
}
v2f vert(appdata_t v)
{
v2f OUT;
UNITY_SETUP_INSTANCE_ID(v);
UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(OUT);
float4 vPosition = UnityObjectToClipPos(v.vertex);
OUT.worldPosition = v.vertex;
OUT.vertex = vPosition;
OUT.vertex = UnityObjectToClipPos(OUT.worldPosition);
float2 pixelSize = vPosition.w;
pixelSize /= float2(1, 1) * abs(mul((float2x2)UNITY_MATRIX_P, _ScreenParams.xy));
float4 clampedRect = clamp(_ClipRect, -2e10, 2e10);
float2 maskUV = (v.vertex.xy - clampedRect.xy) / (clampedRect.zw - clampedRect.xy);
OUT.texcoord = TRANSFORM_TEX(v.texcoord.xy, _MainTex);
OUT.mask = float4(v.vertex.xy * 2 - clampedRect.xy - clampedRect.zw, 0.25 / (0.25 * half2(_UIMaskSoftnessX, _UIMaskSoftnessY) + abs(pixelSize.xy)));
if (_UIVertexColorAlwaysGammaSpace)
{
#ifndef UNITY_COLORSPACE_GAMMA
v.color.rgb = _UIGammaToLinear(v.color.rgb);
#endif
}
OUT.texcoord = TRANSFORM_TEX(v.texcoord, _MainTex);
OUT.color = v.color * _Color;
return OUT;
@@ -125,26 +101,17 @@
fixed4 frag(v2f IN) : SV_Target
{
//Round up the alpha color coming from the interpolator (to 1.0/256.0 steps)
//The incoming alpha could have numerical instability, which makes it very sensible to
//HDR color transparency blend, when it blends with the world's texture.
const half alphaPrecision = half(0xff);
const half invAlphaPrecision = half(1.0 / alphaPrecision);
IN.color.a = round(IN.color.a * alphaPrecision) * invAlphaPrecision;
half4 color = IN.color * (tex2D(_MainTex, IN.texcoord) + _TextureSampleAdd);
half4 color = (tex2D(_MainTex, IN.texcoord) + _TextureSampleAdd) * IN.color;
#ifdef UNITY_UI_CLIP_RECT
half2 m = saturate((_ClipRect.zw - _ClipRect.xy - abs(IN.mask.xy)) * IN.mask.zw);
color.a *= m.x * m.y;
color.a *= UnityGet2DClipping(IN.worldPosition.xy, _ClipRect);
#endif
#ifdef UNITY_UI_ALPHACLIP
clip(color.a - 0.001);
clip (color.a - 0.001);
#endif
color.rgb *= color.a;
return color;
}
ENDCG

View File

@@ -2,8 +2,8 @@
"name": "com.coffee.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.",
"version": "4.12.2",
"unity": "2018.2",
"version": "5.0.0-preview.15",
"unity": "2019.3",
"license": "MIT",
"repository": {
"type": "git",