Compare commits

..

5 Commits

Author SHA1 Message Date
semantic-release-bot
6394eee4de chore(release): 3.3.14 [skip ci]
## [3.3.14](https://github.com/mob-sakai/ParticleEffectForUGUI/compare/3.3.13...3.3.14) (2023-08-15)

### Bug Fixes

* error on InitializeIfNeeded ([1f1fb2a](1f1fb2a62a)), closes [#264](https://github.com/mob-sakai/ParticleEffectForUGUI/issues/264)
2023-08-15 02:04:46 +00:00
mob-sakai
1f1fb2a62a fix: error on InitializeIfNeeded
close #264
2023-08-15 11:02:19 +09:00
semantic-release-bot
640cee9e34 chore(release): 3.3.13 [skip ci]
## [3.3.13](https://github.com/mob-sakai/ParticleEffectForUGUI/compare/3.3.12...3.3.13) (2023-05-18)

### Bug Fixes

* memory leak when using AnimatableProperty ([3849a9f](3849a9f697))
2023-05-18 12:38:06 +00:00
mob-sakai
9dedbfb48f build: update release workflow 2023-05-18 21:37:23 +09:00
mob-sakai
3849a9f697 fix: memory leak when using AnimatableProperty 2023-05-18 21:29:36 +09:00
121 changed files with 27291 additions and 70574 deletions

View File

@@ -26,9 +26,9 @@ A clear and concise description of what you expected to happen.
If applicable, add screenshots to help explain your problem.
**Environment (please complete the following information):**
- Version [e.g. 4.0.0]
- Version [e.g. 1.0.0]
- Platform: [e.g. Editor(Windows/Mac), Standalone(Windows/Mac), iOS, Android, WebGL]
- Unity version: [e.g. 2022.3.0f1]
- Unity version: [e.g. 2018.2.8f1]
- Build options: [e.g. IL2CPP, .Net 4.x, LWRP]
**Additional context**

View File

@@ -1,9 +0,0 @@
---
name: Pull Request
about: Create a pull request
title: ''
assignees: mob-sakai
---
**NOTE: Create a pull request to merge into `develop` branch**

24
.github/workflows/release.yml vendored Normal file
View File

@@ -0,0 +1,24 @@
name: release
on:
push:
branches:
- preview
- main
- "*.x"
tags-ignore:
- "**"
jobs:
release:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: cycjimmy/semantic-release-action@v3
with:
extra_plugins: |
@semantic-release/changelog
@semantic-release/git
env:
GITHUB_TOKEN: ${{ github.token }}

94
.github/workflows/test.yml vendored Normal file
View File

@@ -0,0 +1,94 @@
# Secrets
# UNITY_LICENSE:
name: test
on:
push:
branches:
- develop
tags:
- "!*"
pull_request:
types:
- opened
- synchronize
jobs:
unity-test:
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
unityVersion: [
"2018.3.14f1",
"2018.4.30f1",
"2019.1.14f1",
"2019.2.21f1",
"2019.3.15f1",
"2019.4.16f1",
"2020.1.17f1",
"2020.2.1f1",
]
steps:
# Checkout sandbox project
- uses: actions/checkout@v2
with:
ref: sandbox
submodules: true
fetch-depth: 0
# Update package submodule
- name: "Update package submodule"
working-directory: Packages/dev
run: git checkout ${{ github.sha }}
- uses: actions/cache@v2
with:
path: Library
key: Library-${{ matrix.unityVersion }}-${{ github.sha }}
restore-keys: |
Library-${{ matrix.unityVersion }}-
Library-
# Install codecoverage package
- name: "Install codecoverage package"
if: startsWith(matrix.unityVersion, '2019.4.')
run: |
npx openupm-cli add -f com.unity.testtools.codecoverage@0.4.0-preview
# Run tests
- name: "Run tests"
uses: game-ci/unity-test-runner@main
with:
unityVersion: ${{ matrix.unityVersion }}
customParameters: -nographics -enableCodeCoverage -coverageOptions assemblyFilters:+Coffee.UIParticle.*Tests
env:
UNITY_LICENSE: ${{ secrets.UNITY_LICENSE }}
- uses: actions/upload-artifact@v2
if: always()
with:
name: TestResults-${{ matrix.unityVersion }}
path: |
artifacts/*.xml
CodeCoverage/**/TestCoverageResults_*.xml
publish:
needs: unity-test
runs-on: ubuntu-latest
if: always()
steps:
- uses: actions/download-artifact@v2
with:
path: artifacts
- uses: testspace-com/setup-testspace@v1
with:
domain: ${{github.repository_owner}}
- name: Push test results
if: always()
run: |
testspace `find . -name '*.xml' | tr '\n' ' '`

View File

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

View File

@@ -1,356 +1,16 @@
## [4.8.1](https://github.com/mob-sakai/ParticleEffectForUGUI/compare/v4.8.0...v4.8.1) (2024-06-27)
## [3.3.14](https://github.com/mob-sakai/ParticleEffectForUGUI/compare/3.3.13...3.3.14) (2023-08-15)
### Bug Fixes
* remove debug code ([669deb4](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/669deb41d4ac589d9db93b29bc8e95383e7f28a5))
* error on InitializeIfNeeded ([1f1fb2a](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/1f1fb2a62a9d2ca6562e1b1e70d528aaf52bfc82)), closes [#264](https://github.com/mob-sakai/ParticleEffectForUGUI/issues/264)
# [4.8.0](https://github.com/mob-sakai/ParticleEffectForUGUI/compare/v4.7.2...v4.8.0) (2024-06-27)
## [3.3.13](https://github.com/mob-sakai/ParticleEffectForUGUI/compare/3.3.12...3.3.13) (2023-05-18)
### Bug Fixes
* generated baking-camera object remains in the prefab or scene (again) ([de35cba](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/de35cba34c6312c1405ed522e9927c620c78e72d))
* SetParticleSystemInstance/Prefab APIs destroy generated objects ([ae3f3a8](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/ae3f3a8e62cc733420354d237ab765ac777127c8))
### Features
* add 'custom view' option. ([a703c29](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/a703c2921ca08c2280d0c8fde01e4c0b33b5c69e))
* remove overlay window (editor) ([8358170](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/835817049f4fcf00dd2bf98dbada14f041ad3544))
* restore `Transform.localScale` when setting `autoScalingMode` to something other than `Transform` (again) ([88a970d](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/88a970d93a2b69cf011d86bd1807569e90538e0e))
* the rendering order list in inspector is now more compact ([be90172](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/be901724e064befacf617f4940b0331e1d31e1ca))
## [4.7.2](https://github.com/mob-sakai/ParticleEffectForUGUI/compare/v4.7.1...v4.7.2) (2024-06-21)
### Bug Fixes
* generated baking-camera object remains in the prefab or scene ([0bb8438](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/0bb843830197d8c1252232928becc211c0ada08d))
## [4.7.1](https://github.com/mob-sakai/ParticleEffectForUGUI/compare/v4.7.0...v4.7.1) (2024-06-20)
### Bug Fixes
* despite not using the size module, particles become smaller based on their z position ([a8ed6e6](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/a8ed6e68584e1d9e45ed852eefcc03979ea7e0e1)), closes [#316](https://github.com/mob-sakai/ParticleEffectForUGUI/issues/316)
# [4.7.0](https://github.com/mob-sakai/ParticleEffectForUGUI/compare/v4.6.8...v4.7.0) (2024-06-19)
### Bug Fixes
* `UIParticle.transform.localScale` does not scale particles ([1d40e24](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/1d40e24c742741e97f03c55468ccb1e505341133)), closes [#313](https://github.com/mob-sakai/ParticleEffectForUGUI/issues/313)
* UIParticle is scaled by canvas size even when `AutoScalingMode.None` and `ScalingMode.Local` ([54a4b1c](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/54a4b1cdfd06400c7be89c1ee704bb42a659c7c2)), closes [#313](https://github.com/mob-sakai/ParticleEffectForUGUI/issues/313)
* UIParticle is scaled incorrectly with nested canvases ([f26920f](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/f26920f9825547222a4afbb31cc5dc5a002c3e9b)), closes [#313](https://github.com/mob-sakai/ParticleEffectForUGUI/issues/313)
### Features
* reset previous position on start play for world space simulation ([3880484](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/3880484ce5190c42fc79c81d0b69e3fbeda09dd0)), closes [#303](https://github.com/mob-sakai/ParticleEffectForUGUI/issues/303)
* restore `Transform.localScale` when setting `autoScalingMode` to something other than `Transform` ([5505247](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/5505247a94a929ff89635fde512a9b95691e0043))
## [4.6.8](https://github.com/mob-sakai/ParticleEffectForUGUI/compare/v4.6.7...v4.6.8) (2024-06-14)
### Bug Fixes
* 'Resource ID out of range in GetResource' error in overlay rendering mode ([05286ce](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/05286cedfd17b1a0cb90a5e918513644f47cd831)), closes [#308](https://github.com/mob-sakai/ParticleEffectForUGUI/issues/308)
## [4.6.7](https://github.com/mob-sakai/ParticleEffectForUGUI/compare/v4.6.6...v4.6.7) (2024-05-24)
### Bug Fixes
* the ParticleSystem's localPosition drifts at certain scales due to floating-point precision issues ([e924eb4](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/e924eb45968a112347471cabaeabc274e4c37ce4)), closes [#299](https://github.com/mob-sakai/ParticleEffectForUGUI/issues/299) [#312](https://github.com/mob-sakai/ParticleEffectForUGUI/issues/312)
## [4.6.6](https://github.com/mob-sakai/ParticleEffectForUGUI/compare/v4.6.5...v4.6.6) (2024-05-23)
### Bug Fixes
* fix release workflow ([30b0076](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/30b00762f6da166c043587798b1552f27b4cc604))
## [4.6.5](https://github.com/mob-sakai/ParticleEffectForUGUI/compare/v4.6.4...v4.6.5) (2024-05-23)
### Bug Fixes
* update workflows (for preview and v4) ([3eab097](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/3eab0979b9b85919b804442ab05735b7120eade5))
## [4.6.4](https://github.com/mob-sakai/ParticleEffectForUGUI/compare/v4.6.3...v4.6.4) (2024-05-22)
### Bug Fixes
* assertion failed on expression: 'ps->array_size()' ([1b5c359](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/1b5c359058289895caf5f245fe09abb643bc38eb)), closes [#278](https://github.com/mob-sakai/ParticleEffectForUGUI/issues/278)
* lost Material.mainTexture when using AnimatableProperties ([ea04352](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/ea043524c0b00f67cba26a1f9ea537ee4a56d6ff)), closes [#311](https://github.com/mob-sakai/ParticleEffectForUGUI/issues/311)
* remove unnecessary code ([c37c014](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/c37c01486499773e3d7e8296c95bb4c3fae94abb))
## [4.6.3](https://github.com/mob-sakai/ParticleEffectForUGUI/compare/v4.6.2...v4.6.3) (2024-04-04)
### Bug Fixes
* if only Trail Material is used, it will not be displayed ([2eff411](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/2eff411bd97eb4e6947d29a02b85b414bfdaee3a)), closes [#294](https://github.com/mob-sakai/ParticleEffectForUGUI/issues/294)
* if the UIParticle parents do not have Canvas, an exception is thrown in OnEnable ([e82c833](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/e82c833d04b819f103984931ba29a3616ef50908)), closes [#300](https://github.com/mob-sakai/ParticleEffectForUGUI/issues/300)
* particle size too small due to auto scaling ([2ec3748](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/2ec374833614d64406e7c3207ca5fe234a749dcb)), closes [#295](https://github.com/mob-sakai/ParticleEffectForUGUI/issues/295)
## [4.6.2](https://github.com/mob-sakai/ParticleEffectForUGUI/compare/v4.6.1...v4.6.2) (2024-02-01)
### Bug Fixes
* fix compile error in Unity 2021.1 or older ([fcae60b](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/fcae60bf29079bac07463bd3a86f8644151d72ba))
* fix demos ([ad20d12](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/ad20d128a2ad033d9f30b98f0a0dab6091f5aa19))
* fix warning ([7fd4a8e](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/7fd4a8e343ce587dffa9db5ff186061b3ebb38a6))
## [4.6.1](https://github.com/mob-sakai/ParticleEffectForUGUI/compare/v4.6.0...v4.6.1) (2024-01-26)
### Bug Fixes
* unintended scaling occurs when `AutoScalingMode=UIParticle` and `ScalingMode=Local` ([1627de1](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/1627de10eb1e742a015603ae9939071665a5bd89)), closes [#292](https://github.com/mob-sakai/ParticleEffectForUGUI/issues/292)
# [4.6.0](https://github.com/mob-sakai/ParticleEffectForUGUI/compare/v4.5.2...v4.6.0) (2024-01-26)
### Bug Fixes
* fix abnormal mesh bounds error ([772bf50](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/772bf50d168982bd401c30e58172e0a60fbafe46)), closes [#213](https://github.com/mob-sakai/ParticleEffectForUGUI/issues/213)
* fix warning ([93d3919](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/93d3919b6fb6ac186b3e99f8baaef9a044f583f2))
* fix warning ([8a78ec1](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/8a78ec13ad2aad9138a22b67c332871e064a38cc))
### Features
* "[generated]" GameObjects on the hierarchy is disturbing ([7c42421](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/7c4242150b591daf64390588afa27efa27368af3)), closes [#288](https://github.com/mob-sakai/ParticleEffectForUGUI/issues/288)
* add explicit dependencies ([9a0187a](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/9a0187a72a35d378ff7be965bfcb7475f423fe0f))
* add icon ([0c1022c](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/0c1022c6224394713f62b41e5e4ef0c289610ae1))
* remove samples ([f53a7fa](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/f53a7faed3ee73ac22d745a778284e818624b510))
# [4.6.0-preview.1](https://github.com/mob-sakai/ParticleEffectForUGUI/compare/v4.5.2...v4.6.0-preview.1) (2024-01-24)
### Bug Fixes
* fix abnormal mesh bounds error ([772bf50](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/772bf50d168982bd401c30e58172e0a60fbafe46)), closes [#213](https://github.com/mob-sakai/ParticleEffectForUGUI/issues/213)
* fix warning ([93d3919](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/93d3919b6fb6ac186b3e99f8baaef9a044f583f2))
* fix warning ([8a78ec1](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/8a78ec13ad2aad9138a22b67c332871e064a38cc))
### Features
* "[generated]" GameObjects on the hierarchy is disturbing ([7c42421](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/7c4242150b591daf64390588afa27efa27368af3)), closes [#288](https://github.com/mob-sakai/ParticleEffectForUGUI/issues/288)
* add explicit dependencies ([9a0187a](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/9a0187a72a35d378ff7be965bfcb7475f423fe0f))
* add icon ([0c1022c](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/0c1022c6224394713f62b41e5e4ef0c289610ae1))
* remove samples ([f53a7fa](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/f53a7faed3ee73ac22d745a778284e818624b510))
## [4.5.2](https://github.com/mob-sakai/ParticleEffectForUGUI/compare/4.5.1...4.5.2) (2024-01-18)
### Bug Fixes
* (editor) sometimes crashes when entering play mode ([b80c3e6](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/b80c3e6c9fdd2a8fb72ff233edb85df2e3dbba3d))
## [4.5.1](https://github.com/mob-sakai/ParticleEffectForUGUI/compare/4.5.0...4.5.1) (2023-12-23)
### Bug Fixes
* fix material for mesh sharing group ([6126af9](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/6126af9f376dd4c100a1b9d19d9499bdef7d5566))
* the changes made to the material used by the ParticleSystem are not immediately reflected ([3184ba9](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/3184ba94ae08264223c0c71443ad70acc1a1ccb2)), closes [#280](https://github.com/mob-sakai/ParticleEffectForUGUI/issues/280)
# [4.5.0](https://github.com/mob-sakai/ParticleEffectForUGUI/compare/4.4.0...4.5.0) (2023-12-23)
### Bug Fixes
* incorrect rendering of world-space simulated particles while animating scale ([ac58475](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/ac584755393d87bda2e80d9653370b7e4c68912f)), closes [#285](https://github.com/mob-sakai/ParticleEffectForUGUI/issues/285)
* remove obsolete warning ([5d5eb34](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/5d5eb34590b7cefb0e4ac26c0441e104176ce522))
### Features
* Automatically generated objects are no longer editable (NotEditable). ([5607dc4](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/5607dc4eed0c086b4651941953df6c7d535712e0))
* support IMeshModifier ([5c3232f](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/5c3232faf3d2cfad1e3e1a9349b8346c7982a608)), closes [#282](https://github.com/mob-sakai/ParticleEffectForUGUI/issues/282)
# [4.4.0](https://github.com/mob-sakai/ParticleEffectForUGUI/compare/4.3.0...4.4.0) (2023-11-08)
### Features
* support 'Active Apply Color Space' for linear color space ([45c56bb](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/45c56bbd850202365751ea019baf5131b2eb9fbe))
# [4.3.0](https://github.com/mob-sakai/ParticleEffectForUGUI/compare/4.2.2...4.3.0) (2023-11-08)
### Features
* added 'autoScalingMode (None, Transform.localScale, UIParticle.scale)' instead of 'autoScaling' ([107f901](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/107f901fe3232223322681edc4bf908642474298))
* reset transform.localScale on upgrading v3.x to v4.x ([c710787](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/c710787b5ba496cf73e7eb43458bb3958139baa9)), closes [#277](https://github.com/mob-sakai/ParticleEffectForUGUI/issues/277)
## [4.2.2](https://github.com/mob-sakai/ParticleEffectForUGUI/compare/4.2.1...4.2.2) (2023-10-25)
### Bug Fixes
* il2cpp code stripping bug ([73f6dad](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/73f6dad0f33641a76ddd05ffc6812ced3f8a276d)), closes [#269](https://github.com/mob-sakai/ParticleEffectForUGUI/issues/269)
## [4.2.1](https://github.com/mob-sakai/ParticleEffectForUGUI/compare/4.2.0...4.2.1) (2023-08-18)
### Bug Fixes
* autoScaling and PositionMode may be locked ([3f2f12d](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/3f2f12d2cf7541118c02830ec9fdea8183357487))
# [4.2.0](https://github.com/mob-sakai/ParticleEffectForUGUI/compare/4.1.7...4.2.0) (2023-08-18)
### Bug Fixes
* assertion 'ps->array_size()' in UpdateMesh() when using trails of type ribbon ([f75fcce](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/f75fcce0dae0bc166bd01d36a150aded1fd721f3)), closes [#241](https://github.com/mob-sakai/ParticleEffectForUGUI/issues/241)
* built-in shaders are no longer supported ([c2119c1](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/c2119c171a1262431eac7fea6bf3125db2bcaaca)), closes [#233](https://github.com/mob-sakai/ParticleEffectForUGUI/issues/233) [#257](https://github.com/mob-sakai/ParticleEffectForUGUI/issues/257)
* crash occurs when too many vertices are rendered ([723a04d](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/723a04d0cfd156715a3c92b6d6bd75fdc1862c28))
* error: SerializedObject target has been destroyed ([e930516](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/e93051603e121732c92bcd89ded48087c2b0d7fb)), closes [#267](https://github.com/mob-sakai/ParticleEffectForUGUI/issues/267)
* excessive particle emitted on move ParticleSystem for local space simulation and emission over distance ([2fe0bde](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/2fe0bde422f9769dfedaf6b053ea07f773646679)), closes [#265](https://github.com/mob-sakai/ParticleEffectForUGUI/issues/265)
* fix typos ([52f2ef1](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/52f2ef1f2471a2e1c29fca96255c04b222d9c848))
* generated GameObject will be named '[generated] *' ([9b2e5c1](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/9b2e5c1d1024e091de6d18a4578cd18b43563e48))
* inactive ParticleSystems are removed from the list on refresh ([4851a18](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/4851a1880eef9f385dd9db644ea7e544f95da4fc))
* mesh sharing not working ([8b4ca1a](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/8b4ca1add5c409601e840253e1c0dbcdbf536da8)), closes [#236](https://github.com/mob-sakai/ParticleEffectForUGUI/issues/236)
* nullptr exceptions when using nested UIParticle components in hierarchy ([e67e948](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/e67e9482e2cb840b16e2cfe76e04f7423fcbd3a3)), closes [#246](https://github.com/mob-sakai/ParticleEffectForUGUI/issues/246)
* nullReferenceException after copy-n-paste ([425aad0](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/425aad0cbab475635c72bee84ecbf3f2acedccc2)), closes [#258](https://github.com/mob-sakai/ParticleEffectForUGUI/issues/258)
* remove unnecessary per-frame allocation. ([e92b514](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/e92b514624cc362e53ddeae5ade20fa732f94c7c))
* scaling ParticleSystem puts prewarmed particles in wrong location ([fb31db4](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/fb31db47f2debb3aadbdc4d1b88d0efd9c4ad7bd)), closes [#235](https://github.com/mob-sakai/ParticleEffectForUGUI/issues/235)
* sub-emitters option is not work in editor playing ([b308b26](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/b308b2683372662bb834b6f6d23ea3435a68d1b3)), closes [#231](https://github.com/mob-sakai/ParticleEffectForUGUI/issues/231)
* the camera under UIParticle will be assigned as _orthoCamera ([c42f8c8](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/c42f8c8ab0ff033689349a81e02a4808e071a8a2))
* UIParticleAttractor attracts the particles at wrong position when in RelativeMode ([68d9925](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/68d9925a16237df3c7b07b4781172cbd03425421)), closes [#262](https://github.com/mob-sakai/ParticleEffectForUGUI/issues/262)
### Features
* 'AbsoluteMode' option is renamed to 'PositionMode' ([67eff61](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/67eff610736344ba0122163ff5ee63b25c43f555))
* 'AutoScaling' option will be imported from 'IgnoreCanvasScale' (for v3.x) ([4103041](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/410304125f3f25f3f543c7bc01dcc661eab00609))
* add 'AutoScaling' option for UIParticle ([35325c8](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/35325c88996fa6aea19a6dd1395c05884e1f84ae))
* add 'UpdateMode' option for UIParticleAttractor ([903f702](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/903f702d7be38228841a5a693e3afdceb4a59d9f)), closes [#250](https://github.com/mob-sakai/ParticleEffectForUGUI/issues/250)
* add particle system getter and setter for attractor ([a4bcf93](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/a4bcf93022d2729f3d2a74a2cac4f52e68641b18)), closes [#253](https://github.com/mob-sakai/ParticleEffectForUGUI/issues/253)
* add public properties for UIParticleAttractor ([392ab6d](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/392ab6dd76c36e815320d3a50744d19faa631260)), closes [#253](https://github.com/mob-sakai/ParticleEffectForUGUI/issues/253)
* add Start/StopEmission API for UIParticle ([e499836](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/e4998365c9825fa385e0a317768ce073a1f15b48)), closes [#240](https://github.com/mob-sakai/ParticleEffectForUGUI/issues/240)
## [4.1.7](https://github.com/mob-sakai/ParticleEffectForUGUI/compare/4.1.6...4.1.7) (2022-08-30)
### Bug Fixes
* the annoying empty black scene overlay box shown even when nothing is selected ([bdeeabb](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/bdeeabbbe140b0ba80fac7ac477874c2467d3a16))
## [4.1.6](https://github.com/mob-sakai/ParticleEffectForUGUI/compare/4.1.5...4.1.6) (2022-08-10)
### Bug Fixes
* fix abnormal mesh bounds error ([f60d6df](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/f60d6dfe6030ac89527a4265e414e9a0a20d56db)), closes [#213](https://github.com/mob-sakai/ParticleEffectForUGUI/issues/213) [#218](https://github.com/mob-sakai/ParticleEffectForUGUI/issues/218)
## [4.1.5](https://github.com/mob-sakai/ParticleEffectForUGUI/compare/4.1.4...4.1.5) (2022-08-10)
### Bug Fixes
* fix culling for RectMask2D ([9e2dbe7](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/9e2dbe7758eb28a4f6a7c11113d9169847880f96)), closes [#220](https://github.com/mob-sakai/ParticleEffectForUGUI/issues/220)
## [4.1.4](https://github.com/mob-sakai/ParticleEffectForUGUI/compare/4.1.3...4.1.4) (2022-07-01)
### Bug Fixes
* add `Enabled` toggle in overlay window ([f97e619](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/f97e6195e62b5acfa8f3e97bfe3bc4a7dcadf38a))
* if `m_Particles` contains null, an error will occur ([550d0c4](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/550d0c43be35cd07e390ffd5749557c89fee0332)), closes [#214](https://github.com/mob-sakai/ParticleEffectForUGUI/issues/214)
* ParticleSystem reordering and refreshing in inspector does not work for prefab asset ([7eb4112](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/7eb41124db06ea794db76788b35ce82a0af2c402))
* refresh button does not works in prefab edit mode ([c1538a8](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/c1538a83998608a30dc90944b05f8b75e165cf05)), closes [#214](https://github.com/mob-sakai/ParticleEffectForUGUI/issues/214)
* when `UIParticlrRenderer` destroy manually, an error will occur ([a11d2d0](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/a11d2d01ce5f67e3f430bcb0bfdee1ad9abf7cfe))
## [4.1.3](https://github.com/mob-sakai/ParticleEffectForUGUI/compare/4.1.2...4.1.3) (2022-06-28)
### Bug Fixes
* error on drag prefab to scene ([fa2f867](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/fa2f867bcaff437bb9420da1abcef970cdb09ade)), closes [#211](https://github.com/mob-sakai/ParticleEffectForUGUI/issues/211)
## [4.1.2](https://github.com/mob-sakai/ParticleEffectForUGUI/compare/4.1.1...4.1.2) (2022-06-27)
### Bug Fixes
* error on editor ([8034228](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/80342287137c07d58a7492875a401d80cb134073)), closes [#210](https://github.com/mob-sakai/ParticleEffectForUGUI/issues/210)
* incorrect position of world space trail particles ([fb7f308](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/fb7f308f092db8a1512383857b80110cd626ecf9)), closes [#209](https://github.com/mob-sakai/ParticleEffectForUGUI/issues/209)
## [4.1.1](https://github.com/mob-sakai/ParticleEffectForUGUI/compare/4.1.0...4.1.1) (2022-06-25)
### Bug Fixes
* add absolute mode toggle to overlay window ([48d1994](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/48d1994f5f8751b707b6ef7695b552df731bece9))
# [4.1.0](https://github.com/mob-sakai/ParticleEffectForUGUI/compare/4.0.1...4.1.0) (2022-06-25)
### Features
* add relative/absolute particle position mode ([1879ac8](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/1879ac8c538778e386e68cfc989a6f4f974043ca)), closes [#205](https://github.com/mob-sakai/ParticleEffectForUGUI/issues/205)
## [4.0.1](https://github.com/mob-sakai/ParticleEffectForUGUI/compare/4.0.0...4.0.1) (2022-06-24)
### Bug Fixes
* overlays do not exist in Unity 2019.2-2021.1 ([cd8e037](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/cd8e0372b63bb6feaaf053518013a641bc7e65ac)), closes [#207](https://github.com/mob-sakai/ParticleEffectForUGUI/issues/207) [#208](https://github.com/mob-sakai/ParticleEffectForUGUI/issues/208)
# [4.0.0](https://github.com/mob-sakai/ParticleEffectForUGUI/compare/3.3.12...4.0.0) (2022-06-21)
### Bug Fixes
* correct world space particle position when changing screen size ([c6644a2](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/c6644a213263375c7a35b5082ef4b71cc58964e6))
* keep properly canvas batches ([d8e96e6](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/d8e96e69a62dff7a451eaed32c7a814e7e62dbb9))
### Features
* adaptive scaling for UI ([aa0d56f](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/aa0d56f9faa05e9679d4b476bcf135eafb1b8af9))
* add overlay window for UIParticle ([7b21c50](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/7b21c500ef78103b605fdca71051d2357b09602f))
* add particle attractor component ([386170c](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/386170cbf68ebf59d4510fe0a45cf83925ec9ba4))
* display warning in inspector if using 'TEXCOORD*.zw' components as custom vertex stream ([59221d5](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/59221d58217a440b77d504e6428bf99f10246260))
* mesh sharing group ([9afeebf](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/9afeebf67212cdf4d3ac9e9a3b78a7ced5c7ecfe))
* random mesh sharing group ([4fa43ed](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/4fa43eda4bc70c9c827c4fad9d5ae1327bfbc322))
* support 8+ materials ([b76bf5a](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/b76bf5a5ad378c3c4b16bcf08d21337757557101)), closes [#122](https://github.com/mob-sakai/ParticleEffectForUGUI/issues/122) [#152](https://github.com/mob-sakai/ParticleEffectForUGUI/issues/152) [#186](https://github.com/mob-sakai/ParticleEffectForUGUI/issues/186)
### BREAKING CHANGES
* If you update to v4, you may be required to adjust your UIParticle.scale.
# [4.0.0-preview.1](https://github.com/mob-sakai/ParticleEffectForUGUI/compare/3.3.12...4.0.0-preview.1) (2022-06-18)
### Bug Fixes
* correct world space particle position when changing screen size ([c6644a2](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/c6644a213263375c7a35b5082ef4b71cc58964e6))
* keep properly canvas batches ([d8e96e6](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/d8e96e69a62dff7a451eaed32c7a814e7e62dbb9))
### Features
* adaptive scaling for UI ([aa0d56f](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/aa0d56f9faa05e9679d4b476bcf135eafb1b8af9))
* add overlay window for UIParticle ([7b21c50](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/7b21c500ef78103b605fdca71051d2357b09602f))
* add particle attractor component ([386170c](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/386170cbf68ebf59d4510fe0a45cf83925ec9ba4))
* mesh sharing group ([9afeebf](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/9afeebf67212cdf4d3ac9e9a3b78a7ced5c7ecfe))
* random mesh sharing group ([4fa43ed](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/4fa43eda4bc70c9c827c4fad9d5ae1327bfbc322))
* support 8+ materials ([b76bf5a](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/b76bf5a5ad378c3c4b16bcf08d21337757557101)), closes [#122](https://github.com/mob-sakai/ParticleEffectForUGUI/issues/122) [#152](https://github.com/mob-sakai/ParticleEffectForUGUI/issues/152) [#186](https://github.com/mob-sakai/ParticleEffectForUGUI/issues/186)
### BREAKING CHANGES
* If you update to v4, you may be required to adjust your UIParticle.scale.
* memory leak when using AnimatableProperty ([3849a9f](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/3849a9f6977bc6d2474001c8154a8e201f7e8b7b))
## [3.3.12](https://github.com/mob-sakai/ParticleEffectForUGUI/compare/3.3.11...3.3.12) (2022-06-10)

View File

@@ -81,4 +81,4 @@ Community Impact Guidelines were inspired by [Mozilla's code of conduct enforcem
[homepage]: https://www.contributor-covenant.org
For answers to common questions about this code of conduct, see the FAQ at
https://www.contributor-covenant.org/faq. Translations are available at https://www.contributor-covenant.org/translations.
https://www.contributor-covenant.org/faq. Translations are available at https://www.contributor-covenant.org/translations.

View File

@@ -19,24 +19,11 @@ When fixing a bug it is fine to submit a pull request right away.
Steps to be performed to submit a pull request:
1. Fork the repository.
2. Clone the repository.
3. Checkout `develop` branch.
4. Develop the package.
5. Test the package with the test runner (`Window > Generals > Test Runner`).
6. Commit with a message based
on [Angular Commit Message Conventions](https://gist.github.com/stephenparish/9941e89d80e2bc58a153) as follows:
- `fix:` fix a bug
- `feat:` new feature
- `docs:` changes only in documentation
- `style:` changes only in formatting, white-space, etc
- `refactor:` changes only in code structure (extract method, rename variable, move method, etc)
- `perf:` changes only in code performance
- `test:` add or update tests
- `chore:` changes to the build process or auxiliary tools and libraries such as documentation generation
7. Create a pull request on GitHub. Fill out the description, link any related issues and submit your pull request.
1. Fork the repository and create your branch from `develop`.
2. If you have fixed a bug or added code that should be tested, add tests.
3. Click `Window > Generals > Test Runner` to test
4. Commit with a massage based on [Angular Commit Message Conventions](https://gist.github.com/stephenparish/9941e89d80e2bc58a153).
5. Fill out the description, link any related issues and submit your pull request.
#### License

View File

@@ -1,142 +0,0 @@
using System.Collections.Generic;
using System.Linq;
using System.Text;
using UnityEditor;
using UnityEngine;
namespace Coffee.UIExtensions
{
internal static class AnimatablePropertyEditor
{
private static readonly GUIContent s_ContentNothing = new GUIContent("Nothing");
private static readonly List<string> s_ActiveNames = new List<string>();
private static readonly StringBuilder s_Sb = new StringBuilder();
private static readonly HashSet<string> s_Names = new HashSet<string>();
private static string CollectActiveNames(SerializedProperty sp, List<string> result)
{
result.Clear();
for (var i = 0; i < sp.arraySize; i++)
{
var spName = sp.GetArrayElementAtIndex(i).FindPropertyRelative("m_Name");
if (spName == null) continue;
result.Add(spName.stringValue);
}
s_Sb.Length = 0;
if (result.Count == 0)
{
s_Sb.Append("Nothing");
}
else
{
result.Aggregate(s_Sb, (a, b) =>
{
s_Sb.Append(b);
return s_Sb.Append(", ");
});
s_Sb.Length -= 2;
}
return s_Sb.ToString();
}
public static void Draw(SerializedProperty sp, List<Material> mats)
{
var pos = EditorGUILayout.GetControlRect(true);
var label = new GUIContent(sp.displayName, sp.tooltip);
var rect = EditorGUI.PrefixLabel(pos, label);
var text = sp.hasMultipleDifferentValues
? "-"
: CollectActiveNames(sp, s_ActiveNames);
if (!GUI.Button(rect, text, EditorStyles.popup)) return;
var gm = new GenericMenu();
gm.AddItem(s_ContentNothing, s_ActiveNames.Count == 0, x =>
{
var current = (SerializedProperty)x;
current.ClearArray();
current.serializedObject.ApplyModifiedProperties();
}, sp);
if (!sp.hasMultipleDifferentValues)
{
for (var i = 0; i < sp.arraySize; i++)
{
var p = sp.GetArrayElementAtIndex(i);
var name = p.FindPropertyRelative("m_Name").stringValue;
var type = (AnimatableProperty.ShaderPropertyType)p.FindPropertyRelative("m_Type").intValue;
AddMenu(gm, sp, new ShaderProperty(name, type), false);
}
}
s_Names.Clear();
for (var j = 0; j < mats.Count; j++)
{
var mat = mats[j];
if (!mat || !mat.shader) continue;
for (var i = 0; i < ShaderUtil.GetPropertyCount(mat.shader); i++)
{
var name = ShaderUtil.GetPropertyName(mat.shader, i);
var type = (AnimatableProperty.ShaderPropertyType)ShaderUtil.GetPropertyType(mat.shader, i);
if (!s_Names.Add(name)) continue;
AddMenu(gm, sp, new ShaderProperty(name, type), true);
if (type != AnimatableProperty.ShaderPropertyType.Texture) continue;
AddMenu(gm, sp, new ShaderProperty($"{name}_ST"), true);
AddMenu(gm, sp, new ShaderProperty($"{name}_HDR"), true);
AddMenu(gm, sp, new ShaderProperty($"{name}_TexelSize"), true);
}
}
gm.ShowAsContext();
}
private static void AddMenu(GenericMenu menu, SerializedProperty sp, ShaderProperty prop, bool add)
{
if (add && s_ActiveNames.Contains(prop.name)) return;
var label = new GUIContent($"{prop.name} ({prop.type})");
menu.AddItem(label, s_ActiveNames.Contains(prop.name), () =>
{
var index = s_ActiveNames.IndexOf(prop.name);
if (0 <= index)
{
sp.DeleteArrayElementAtIndex(index);
}
else
{
sp.InsertArrayElementAtIndex(sp.arraySize);
var p = sp.GetArrayElementAtIndex(sp.arraySize - 1);
p.FindPropertyRelative("m_Name").stringValue = prop.name;
p.FindPropertyRelative("m_Type").intValue = (int)prop.type;
}
sp.serializedObject.ApplyModifiedProperties();
});
}
private struct ShaderProperty
{
public readonly string name;
public readonly AnimatableProperty.ShaderPropertyType type;
public ShaderProperty(string name)
{
this.name = name;
type = AnimatableProperty.ShaderPropertyType.Vector;
}
public ShaderProperty(string name, AnimatableProperty.ShaderPropertyType type)
{
this.name = name;
this.type = type;
}
}
}
}

View File

@@ -1,508 +0,0 @@
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.UIParticleExtensions;
#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;
#elif UNITY_2018_3_OR_NEWER
using UnityEditor.Experimental.SceneManagement;
#endif
namespace Coffee.UIExtensions
{
[CustomEditor(typeof(UIParticle))]
[CanEditMultipleObjects]
internal class UIParticleEditor : GraphicEditor
{
//################################
// Constant or Static Members.
//################################
private static readonly GUIContent[] s_ContentMaterials = new[]
{
new GUIContent("Material"),
new GUIContent("Trail Material")
};
private static readonly GUIContent s_ContentRenderingOrder = new GUIContent("Rendering Order");
private static readonly GUIContent s_ContentRefresh = new GUIContent("Refresh");
private static readonly GUIContent s_ContentFix = new GUIContent("Fix");
private static readonly GUIContent s_Content3D = new GUIContent("3D");
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 Regex s_RegexBuiltInGuid = new Regex(@"^0{16}.0{15}$", RegexOptions.Compiled);
private static readonly List<Material> s_TempMaterials = new List<Material>();
private static bool s_XYZMode;
private SerializedProperty _maskable;
private SerializedProperty _scale3D;
private SerializedProperty _animatableProperties;
private SerializedProperty _meshSharing;
private SerializedProperty _groupId;
private SerializedProperty _groupMaxId;
private SerializedProperty _positionMode;
private SerializedProperty _autoScalingMode;
private SerializedProperty _useCustomView;
private SerializedProperty _customViewSize;
private ReorderableList _ro;
private bool _showMax;
private static readonly HashSet<Shader> s_Shaders = new HashSet<Shader>();
#if UNITY_2018 || UNITY_2019
private static readonly List<ParticleSystemVertexStream> s_Streams = new List<ParticleSystemVertexStream>();
#endif
private static readonly List<string> s_MaskablePropertyNames = new List<string>
{
"_Stencil",
"_StencilComp",
"_StencilOp",
"_StencilWriteMask",
"_StencilReadMask",
"_ColorMask"
};
//################################
// Public/Protected Members.
//################################
/// <summary>
/// This function is called when the object becomes enabled and active.
/// </summary>
protected override void OnEnable()
{
base.OnEnable();
_maskable = serializedObject.FindProperty("m_Maskable");
_scale3D = serializedObject.FindProperty("m_Scale3D");
_animatableProperties = serializedObject.FindProperty("m_AnimatableProperties");
_meshSharing = serializedObject.FindProperty("m_MeshSharing");
_groupId = serializedObject.FindProperty("m_GroupId");
_groupMaxId = serializedObject.FindProperty("m_GroupMaxId");
_positionMode = serializedObject.FindProperty("m_PositionMode");
_autoScalingMode = serializedObject.FindProperty("m_AutoScalingMode");
_useCustomView = serializedObject.FindProperty("m_UseCustomView");
_customViewSize = serializedObject.FindProperty("m_CustomViewSize");
var sp = serializedObject.FindProperty("m_Particles");
_ro = new ReorderableList(sp.serializedObject, sp, true, true, true, true)
{
elementHeightCallback = index =>
{
var ps = sp.GetArrayElementAtIndex(index).objectReferenceValue as ParticleSystem;
var materialCount = 0;
if (ps && ps.TryGetComponent<ParticleSystemRenderer>(out var psr))
{
materialCount = psr.sharedMaterials.Length;
}
return (materialCount + 1) * (EditorGUIUtility.singleLineHeight + 2);
},
drawElementCallback = (rect, index, _, __) =>
{
rect.y += 2;
rect.height = EditorGUIUtility.singleLineHeight;
var p = sp.GetArrayElementAtIndex(index);
EditorGUI.ObjectField(rect, p, GUIContent.none);
var ps = p.objectReferenceValue as ParticleSystem;
if (!ps || !ps.TryGetComponent<ParticleSystemRenderer>(out var psr)) return;
rect.x += 15;
rect.width -= 15;
var materials = new SerializedObject(psr).FindProperty("m_Materials");
var count = Mathf.Min(materials.arraySize, 2);
for (var i = 0; i < count; i++)
{
rect.y += rect.height + 2;
EditorGUI.PropertyField(rect, materials.GetArrayElementAtIndex(i), s_ContentMaterials[i]);
}
if (materials.serializedObject.hasModifiedProperties)
{
materials.serializedObject.ApplyModifiedProperties();
}
},
drawHeaderCallback = rect =>
{
#if !UNITY_2019_3_OR_NEWER
rect.y -= 1;
#endif
var pos = new Rect(rect.x, rect.y, 150, rect.height);
EditorGUI.LabelField(pos, s_ContentRenderingOrder);
pos = new Rect(rect.width - 35, rect.y, 60, rect.height);
if (GUI.Button(pos, s_ContentRefresh, EditorStyles.miniButton))
{
foreach (var uip in targets.OfType<UIParticle>())
{
uip.RefreshParticles();
EditorUtility.SetDirty(uip);
}
}
}
};
// On select UIParticle, refresh particles.
if (!Application.isPlaying)
{
foreach (var uip in targets.OfType<UIParticle>())
{
if (PrefabUtility.GetPrefabAssetType(uip) != PrefabAssetType.NotAPrefab) continue;
uip.RefreshParticles(uip.particles);
}
}
}
/// <summary>
/// Implement this function to make a custom inspector.
/// </summary>
public override void OnInspectorGUI()
{
var current = target as UIParticle;
if (!current) return;
Profiler.BeginSample("(UIP:E) OnInspectorGUI");
serializedObject.Update();
// Maskable
EditorGUILayout.PropertyField(_maskable);
// Scale
EditorGUI.BeginDisabledGroup(!_meshSharing.hasMultipleDifferentValues && _meshSharing.intValue == 4);
s_XYZMode = DrawFloatOrVector3Field(_scale3D, s_XYZMode);
EditorGUI.EndDisabledGroup();
// AnimatableProperties
current.GetMaterials(s_TempMaterials);
AnimatablePropertyEditor.Draw(_animatableProperties, s_TempMaterials);
// Mesh sharing
EditorGUI.BeginChangeCheck();
_showMax = DrawMeshSharing(_meshSharing, _groupId, _groupMaxId, _showMax);
if (EditorGUI.EndChangeCheck())
{
serializedObject.ApplyModifiedProperties();
foreach (var t in targets)
{
if (t is UIParticle uip)
{
uip.ResetGroupId();
}
}
}
// Position Mode
EditorGUILayout.PropertyField(_positionMode);
// Auto Scaling
EditorGUILayout.PropertyField(_autoScalingMode);
// Custom View Size
EditorGUILayout.PropertyField(_useCustomView);
EditorGUI.BeginChangeCheck();
EditorGUI.BeginDisabledGroup(!_useCustomView.boolValue);
EditorGUI.indentLevel++;
EditorGUILayout.PropertyField(_customViewSize);
EditorGUI.indentLevel--;
EditorGUI.EndDisabledGroup();
if (EditorGUI.EndChangeCheck())
{
_customViewSize.floatValue = Mathf.Max(0.1f, _customViewSize.floatValue);
}
// Target ParticleSystems.
EditorGUI.BeginChangeCheck();
_ro.DoLayoutList();
serializedObject.ApplyModifiedProperties();
if (EditorGUI.EndChangeCheck())
{
EditorApplication.QueuePlayerLoopUpdate();
foreach (var uip in targets.OfType<UIParticle>())
{
uip.RefreshParticles(uip.particles);
}
}
// 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)
{
if (!mat || !mat.shader) continue;
var shader = mat.shader;
if (IsBuiltInObject(shader) && !shader.name.StartsWith("UI/"))
{
EditorGUILayout.HelpBox(
$"Built-in shader '{shader.name}' in '{mat.name}' is not supported.\n" +
"Use UI shaders instead.",
MessageType.Error);
}
}
Profiler.EndSample();
// Does the shader support UI masks?
Profiler.BeginSample("(UIP:E) Does the shader support UI masks?");
if (current.maskable && current.GetComponentInParent<Mask>(false))
{
foreach (var mat in s_TempMaterials)
{
if (!mat || !mat.shader) continue;
var shader = mat.shader;
if (!s_Shaders.Add(shader)) continue;
foreach (var propName in s_MaskablePropertyNames)
{
if (mat.HasProperty(propName)) continue;
EditorGUILayout.HelpBox(
$"Shader '{shader.name}' doesn't have '{propName}' property." +
"\nThis graphic cannot be masked.",
MessageType.Warning);
break;
}
}
}
s_TempMaterials.Clear();
s_Shaders.Clear();
Profiler.EndSample();
// UIParticle for trail should be removed.
var label = "This UIParticle component should be removed. The UIParticle for trails is no longer needed.";
#pragma warning disable CS0612
if (FixButton(current.m_IsTrail, label))
#pragma warning restore CS0612
{
DestroyUIParticle(current);
}
#if UNITY_2018 || UNITY_2019
// (2018, 2019) Check to use 'TEXCOORD*.zw' components as custom vertex stream.
var allPsRenderers = targets.OfType<UIParticle>()
.SelectMany(x => x.particles)
.Where(x => x)
.Select(x => x.GetComponent<ParticleSystemRenderer>())
.ToArray();
if (0 < allPsRenderers.Length)
{
// Check to use 'TEXCOORD*.zw' components as custom vertex stream.
foreach (var psr in allPsRenderers)
{
if (!new SerializedObject(psr).FindProperty("m_UseCustomVertexStreams").boolValue) continue;
if (psr.activeVertexStreamsCount == 0) continue;
psr.GetActiveVertexStreams(s_Streams);
if (2 < s_Streams.Select(GetUsedComponentCount).Sum())
{
EditorGUILayout.HelpBox(
$"ParticleSystem '{psr.name}' uses 'TEXCOORD*.zw' components as custom vertex stream.\n" +
"UIParticle does not support it (See README.md).",
MessageType.Warning);
}
s_Streams.Clear();
}
}
#endif
Profiler.EndSample();
}
private static bool IsBuiltInObject(Object obj)
{
return AssetDatabase.IsMainAsset(obj)
&& AssetDatabase.TryGetGUIDAndLocalFileIdentifier(obj, out var guid, out long _)
&& s_RegexBuiltInGuid.IsMatch(guid);
}
#if UNITY_2018 || UNITY_2019
private static int GetUsedComponentCount(ParticleSystemVertexStream s)
{
switch (s)
{
case ParticleSystemVertexStream.Position:
case ParticleSystemVertexStream.Normal:
case ParticleSystemVertexStream.Tangent:
case ParticleSystemVertexStream.Color:
return 0;
case ParticleSystemVertexStream.UV:
case ParticleSystemVertexStream.UV2:
case ParticleSystemVertexStream.UV3:
case ParticleSystemVertexStream.UV4:
case ParticleSystemVertexStream.SizeXY:
case ParticleSystemVertexStream.StableRandomXY:
case ParticleSystemVertexStream.VaryingRandomXY:
case ParticleSystemVertexStream.Custom1XY:
case ParticleSystemVertexStream.Custom2XY:
case ParticleSystemVertexStream.NoiseSumXY:
case ParticleSystemVertexStream.NoiseImpulseXY:
return 2;
case ParticleSystemVertexStream.AnimBlend:
case ParticleSystemVertexStream.AnimFrame:
case ParticleSystemVertexStream.VertexID:
case ParticleSystemVertexStream.SizeX:
case ParticleSystemVertexStream.Rotation:
case ParticleSystemVertexStream.RotationSpeed:
case ParticleSystemVertexStream.Velocity:
case ParticleSystemVertexStream.Speed:
case ParticleSystemVertexStream.AgePercent:
case ParticleSystemVertexStream.InvStartLifetime:
case ParticleSystemVertexStream.StableRandomX:
case ParticleSystemVertexStream.VaryingRandomX:
case ParticleSystemVertexStream.Custom1X:
case ParticleSystemVertexStream.Custom2X:
case ParticleSystemVertexStream.NoiseSumX:
case ParticleSystemVertexStream.NoiseImpulseX:
return 1;
case ParticleSystemVertexStream.Center:
case ParticleSystemVertexStream.SizeXYZ:
case ParticleSystemVertexStream.Rotation3D:
case ParticleSystemVertexStream.RotationSpeed3D:
case ParticleSystemVertexStream.StableRandomXYZ:
case ParticleSystemVertexStream.VaryingRandomXYZ:
case ParticleSystemVertexStream.Custom1XYZ:
case ParticleSystemVertexStream.Custom2XYZ:
case ParticleSystemVertexStream.NoiseSumXYZ:
case ParticleSystemVertexStream.NoiseImpulseXYZ:
return 3;
case ParticleSystemVertexStream.StableRandomXYZW:
case ParticleSystemVertexStream.VaryingRandomXYZW:
case ParticleSystemVertexStream.Custom1XYZW:
case ParticleSystemVertexStream.Custom2XYZW:
return 4;
}
return 3;
}
#endif
private static bool DrawMeshSharing(SerializedProperty spMeshSharing, SerializedProperty spGroupId,
SerializedProperty spGroupMaxId, bool showMax)
{
showMax |= spGroupId.intValue != spGroupMaxId.intValue ||
spGroupId.hasMultipleDifferentValues ||
spGroupMaxId.hasMultipleDifferentValues;
EditorGUILayout.BeginHorizontal();
EditorGUILayout.PropertyField(spMeshSharing);
EditorGUI.BeginChangeCheck();
showMax = GUILayout.Toggle(showMax, s_ContentRandom, EditorStyles.miniButton, GUILayout.Width(60));
if (EditorGUI.EndChangeCheck() && !showMax)
{
spGroupMaxId.intValue = spGroupId.intValue;
}
EditorGUILayout.EndHorizontal();
EditorGUI.BeginDisabledGroup(spMeshSharing.intValue == 0);
EditorGUI.indentLevel++;
EditorGUILayout.PropertyField(spGroupId);
if (showMax)
{
EditorGUILayout.PropertyField(spGroupMaxId);
}
else if (spMeshSharing.intValue == 1 || spMeshSharing.intValue == 4)
{
EditorGUI.BeginDisabledGroup(true);
var obj = UIParticleUpdater.GetPrimary(spGroupId.intValue);
EditorGUILayout.ObjectField(s_ContentPrimary, obj, typeof(UIParticle), false);
EditorGUI.EndDisabledGroup();
}
EditorGUI.indentLevel--;
EditorGUI.EndDisabledGroup();
return showMax;
}
private static void DrawAutoScaling(SerializedProperty prop)
{
EditorGUILayout.PropertyField(prop);
}
private void DestroyUIParticle(UIParticle p, bool ignoreCurrent = false)
{
if (!p || (ignoreCurrent && target == p)) return;
var cr = p.canvasRenderer;
DestroyImmediate(p);
DestroyImmediate(cr);
#if UNITY_2018_3_OR_NEWER
var stage = PrefabStageUtility.GetCurrentPrefabStage();
if (stage != null && stage.scene.isLoaded)
{
#if UNITY_2020_1_OR_NEWER
var prefabAssetPath = stage.assetPath;
#else
var prefabAssetPath = stage.prefabAssetPath;
#endif
PrefabUtility.SaveAsPrefabAsset(stage.prefabContentsRoot, prefabAssetPath);
}
#endif
}
private static bool FixButton(bool show, string text)
{
if (!show) return false;
using (new EditorGUILayout.HorizontalScope(GUILayout.ExpandWidth(true)))
{
EditorGUILayout.HelpBox(text, MessageType.Warning, true);
using (new EditorGUILayout.VerticalScope())
{
return GUILayout.Button(s_ContentFix, GUILayout.Width(30));
}
}
}
private static bool DrawFloatOrVector3Field(SerializedProperty sp, bool showXyz)
{
var x = sp.FindPropertyRelative("x");
var y = sp.FindPropertyRelative("y");
var z = sp.FindPropertyRelative("z");
showXyz |= !Mathf.Approximately(x.floatValue, y.floatValue) ||
!Mathf.Approximately(y.floatValue, z.floatValue) ||
y.hasMultipleDifferentValues ||
z.hasMultipleDifferentValues;
EditorGUILayout.BeginHorizontal();
if (showXyz)
{
EditorGUILayout.PropertyField(sp);
}
else
{
EditorGUI.BeginChangeCheck();
EditorGUILayout.PropertyField(x, s_ContentScale);
if (EditorGUI.EndChangeCheck())
{
y.floatValue = z.floatValue = x.floatValue;
}
}
EditorGUI.BeginChangeCheck();
showXyz = GUILayout.Toggle(showXyz, s_Content3D, EditorStyles.miniButton, GUILayout.Width(30));
if (EditorGUI.EndChangeCheck() && !showXyz)
{
z.floatValue = y.floatValue = x.floatValue;
}
EditorGUILayout.EndHorizontal();
return showXyz;
}
}
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 418 B

View File

@@ -1,127 +0,0 @@
fileFormatVersion: 2
guid: 5f0675613942149309588d556e33d990
TextureImporter:
internalIDToNameTable: []
externalObjects: {}
serializedVersion: 12
mipmaps:
mipMapMode: 0
enableMipMap: 0
sRGBTexture: 1
linearTexture: 0
fadeOut: 0
borderMipMap: 0
mipMapsPreserveCoverage: 0
alphaTestReferenceValue: 0.5
mipMapFadeDistanceStart: 1
mipMapFadeDistanceEnd: 3
bumpmap:
convertToNormalMap: 0
externalNormalMap: 0
heightScale: 0.25
normalMapFilter: 0
flipGreenChannel: 0
isReadable: 0
streamingMipmaps: 0
streamingMipmapsPriority: 0
vTOnly: 0
ignoreMipmapLimit: 0
grayScaleToAlpha: 0
generateCubemap: 6
cubemapConvolution: 0
seamlessCubemap: 0
textureFormat: 1
maxTextureSize: 2048
textureSettings:
serializedVersion: 2
filterMode: 1
aniso: 1
mipBias: 0
wrapU: 1
wrapV: 1
wrapW: 0
nPOTScale: 0
lightmap: 0
compressionQuality: 50
spriteMode: 0
spriteExtrude: 1
spriteMeshType: 1
alignment: 0
spritePivot: {x: 0.5, y: 0.5}
spritePixelsToUnits: 100
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
spriteGenerateFallbackPhysicsShape: 1
alphaUsage: 1
alphaIsTransparency: 1
spriteTessellationDetail: -1
textureType: 2
textureShape: 1
singleChannelComponent: 0
flipbookRows: 1
flipbookColumns: 1
maxTextureSizeSet: 0
compressionQualitySet: 0
textureFormatSet: 0
ignorePngGamma: 0
applyGammaDecoding: 0
swizzle: 50462976
cookieLightType: 0
platformSettings:
- serializedVersion: 3
buildTarget: DefaultTexturePlatform
maxTextureSize: 64
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
- serializedVersion: 3
buildTarget: Standalone
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
- serializedVersion: 3
buildTarget: Server
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
spriteSheet:
serializedVersion: 2
sprites: []
outline: []
physicsShape: []
bones: []
spriteID:
internalID: 0
vertices: []
indices:
edges: []
weights: []
secondaryTextures: []
nameFileIdTable: {}
mipmapLimitGroupName:
pSDRemoveMatte: 0
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -1,7 +1,7 @@
Copyright 2018-2024 mob-sakai
Copyright 2018 mob-sakai
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

576
README.md
View File

@@ -1,495 +1,273 @@
# <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)
Particle Effect For UGUI (UI Particle)
===
This package provides a component to render particle effects for uGUI in Unity 2018.2 or later.
The particle rendering is maskable and sortable, without the need for an extra Camera, RenderTexture, or Canvas.
**:warning: NOTE: Do not use [the obsolete tags and branches](https://github.com/mob-sakai/ParticleEffectForUGUI/issues/108) to reference the package. They will be removed in near future. :warning:**
This plugin provide a component to render particle effect for uGUI in Unity 2018.2 or later.
The particle rendering is maskable and sortable, without Camera, RenderTexture or Canvas.
[![](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?include_prereleases)](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.txt)
![](https://img.shields.io/badge/Unity-2018.2+-57b9d3.svg?style=flat&logo=unity)
![](https://github.com/mob-sakai/ParticleEffectForUGUI/actions/workflows/test.yml/badge.svg?branch=develop)
[![PRs Welcome](https://img.shields.io/badge/PRs-welcome-orange.svg)](http://makeapullrequest.com)
[![](https://img.shields.io/twitter/follow/mob_sakai.svg?label=Follow&style=social)](https://twitter.com/intent/follow?screen_name=mob_sakai)
[![](https://img.shields.io/github/release-date/mob-sakai/ParticleEffectForUGUI.svg)](https://github.com/mob-sakai/ParticleEffectForUGUI/releases) [![](https://img.shields.io/github/license/mob-sakai/ParticleEffectForUGUI.svg)](https://github.com/mob-sakai/ParticleEffectForUGUI/blob/master/LICENSE.txt)
[![PRs Welcome](https://img.shields.io/badge/PRs-welcome-orange.svg)](http://makeapullrequest.com)
![](https://img.shields.io/badge/Unity%202018.2+-supported-blue.svg)
![](https://img.shields.io/badge/Unity%202019.x-supported-blue.svg)
![](https://img.shields.io/badge/Unity%202020.x-supported-blue.svg)
![](https://img.shields.io/badge/Universal%20Rendering%20Pipeline-supported-blue.svg)
<< [📝 Description](#-description) | [🎮 Demo](#-demo) | [⚙ Installation](#-installation) | [🚀 Usage](#-usage) | [🛠 Development Note](#-development-note) | [🤝 Contributing](#-contributing) >>
<br><br>
<< [Description](#Description) | [Demo](#demo) | [Installation](#installation) | [Usage](#usage) | [Development Note](#development-note) | [Change log](https://github.com/mob-sakai/ParticleEffectForUGUI/blob/upm/CHANGELOG.md) >>
## 📝 Description
![Demo](https://user-images.githubusercontent.com/12690315/41771577-8da4b968-7650-11e8-9524-cd162c422d9d.gif)
This package uses the new APIs `MeshBake/MeshTrailBake` (introduced in Unity 2018.2) to render particles through CanvasRenderer.
You can render, mask, and sort your ParticleSystems for UI without the need for an additional Camera, RenderTexture, or Canvas.
<br><br><br><br>
### Key Features
## Description
* **Easy to use:** The package is ready to use out of the box.
* **Sortable:** Sort particle effects and other UI elements by sibling index.
* **Maskable:** Supports `Mask` or `RectMask2D`.
* **No extra components required:** No need for an additional `Camera`, `RenderTexture`, or `Canvas`.
* **Trail module support:** Fully supports the Trail module.
* **CanvasGroup alpha support:** Integrates with `CanvasGroup` alpha.
* **No allocations:** Efficiently renders particles without allocations.
* **Any canvas render mode support:** Works with overlay, camera space, and world space.
* **Any Render pipeline support:** Compatible with Universal Render Pipeline (URP) and High Definition Render Pipeline (HDRP).
* **Disabling domain reload support:** Supports disabling `Enter Play Mode Options > Reload Domain`.
* **Animatable material properties:** Supports changing material properties with AnimationClip (AnimatableProperty).
![AnimatableProperty.gif](https://user-images.githubusercontent.com/12690315/53286323-2d94a980-37b0-11e9-8afb-c4a207805ff2.gif)
* **Multiple materials:** Supports 8+ materials.
* **Correct positioning:** Adjusts world space particle positions correctly when changing window size for standalone platforms (Windows, MacOSX, and Linux).
* **Adaptive scaling:** Provides adaptive scaling for UI (AutoScalingMode).
* **Performance optimization:** Mesh sharing group to improve performance.
<img alt="MeshSharing.gif" src="https://user-images.githubusercontent.com/12690315/174311048-c882df81-6c34-4eba-b0aa-5645457692f1.gif" width="450"/>
* **Particle attractor:** Includes a particle attractor component.
<img alt="ParticleAttractor.gif" src="https://user-images.githubusercontent.com/12690315/174311027-462929a4-13f0-4ec4-86ea-9c832f2eecf1.gif" width="450"/>
* **Emission position mode:** Supports relative/absolute particle emission position modes.
<img alt="AbsolutePosition.gif" src="https://user-images.githubusercontent.com/12690315/175751579-5a2357e8-2ecf-4afd-83c8-66e9771bde39.gif" width="450"/>
* **Custom view size:** Fixes min/max particle size mismatch.
![CustomViewSize.gif](https://github.com/mob-sakai/ParticleEffectForUGUI/assets/12690315/dd929959-1a37-420b-b13d-e849022b9c9d)
![](https://user-images.githubusercontent.com/12690315/41771577-8da4b968-7650-11e8-9524-cd162c422d9d.gif)
<br><br>
This plugin uses new APIs `MeshBake/MashTrailBake` (added with Unity 2018.2) to render particles by CanvasRenderer.
You can mask and sort particles for uGUI without Camera, RenderTexture, Canvas.
## 🎮 Demo
Compares this "Baking mesh" approach with the conventional approach:
(This scene is included in the package.)
* [WebGL Demo](https://mob-sakai.github.io/demos/UIParticle_Demo/index.html)
|Approach|Good|Bad|Screenshot|
|-|-|-|-|
|Baking mesh<br>**\(UIParticle\)**|Rendered as is.<br>Maskable.<br>Sortable.<br>Less objects.|**Requires Unity 2018.2 or later.**<br>Requires UI shaders to use Mask.|<img src="https://user-images.githubusercontent.com/12690315/41765089-0302b9a2-763e-11e8-88b3-b6ffa306bbb0.gif" width="500px">|
|Do nothing|Rendered as is.|**Looks like a glitch.**<br>Not maskable.<br>Not sortable.|<img src="https://user-images.githubusercontent.com/12690315/41765090-0329828a-763e-11e8-8d8a-f1d269ea3bc7.gif" width="500px">|
|Convert particle to UIVertex<br>[\(UIParticleSystem\)](https://forum.unity.com/threads/free-script-particle-systems-in-ui-screen-space-overlay.406862/)|Maskable.<br>Sortable.<br>Less objects.|**Adjustment is difficult.**<br>Requires UI shaders.<br>Difficult to adjust scale.<br>Force hierarchy scalling.<br>Simulation results are incorrect.<br>Trail, rotation of transform, time scaling are not supported.<br>Generate heavy GC every frame.|<img src="https://user-images.githubusercontent.com/12690315/41765088-02deb9c6-763e-11e8-98d0-9e0c1766ef39.gif" width="500px">|
|Use Canvas to sort|Rendered as is.<br>Sortable.|**You must to manage sorting orders.**<br>Not maskable.<br>More batches.|<img src="https://user-images.githubusercontent.com/12690315/41765087-02b866ea-763e-11e8-8c33-081c9ad852f8.gif" width="500px">|
|Use RenderTexture|Maskable.<br>Sortable.|**Requires Camera and RenderTexture.**<br>Difficult to adjust position and size.<br>Quality depends on the RenderTexture's setting.|<img src="https://user-images.githubusercontent.com/12690315/41765085-0291b3e2-763e-11e8-827b-72e5ee9bc556.gif" width="500px">|
> ![](https://user-images.githubusercontent.com/12690315/174311768-1843a5f2-f776-491b-aaa8-2a131a8b6a16.gif)
#### Features
* Easy to use: the package is out-of-the-box
* Sort particle effects with UI
* No Camera, RenderTexture or Canvas are required
* Masking with Mask or RectMask2D
* Support Trail module
* Change alpha with CanvasGroup
* No heavy allocation every frame
* Support overlay, camera space and world space
* Support changing material property with AnimationClip (AnimatableProperty)
![](https://user-images.githubusercontent.com/12690315/53286323-2d94a980-37b0-11e9-8afb-c4a207805ff2.gif)
<br><br><br><br>
## Demo
* [WebGL Demo](https://mob-sakai.github.io/Demos/ParticleEffectForUGUI)
* [WebGL Demo (Cartoon FX & War FX)](https://mob-sakai.github.io/Demos/ParticleEffectForUGUI_CFX)
* [Cartoon FX Free][CFX] & [War FX][WFX] (by [Jean Moreno (JMO)][JMO]) with UIParticle
> ![](https://user-images.githubusercontent.com/12690315/91664766-3e07ac00-eb2c-11ea-978b-ef723be80619.gif)
* [Cartoon FX Free][CFX] & [War FX][WFX] (by [Jean Moreno (JMO)][JMO]) with UIParticle
[CFX]: https://assetstore.unity.com/packages/vfx/particles/cartoon-fx-free-109565
[WFX]: https://assetstore.unity.com/packages/vfx/particles/war-fx-5669
[JMO]: https://assetstore.unity.com/publishers/1669
<br><br>
![](https://user-images.githubusercontent.com/12690315/91664766-3e07ac00-eb2c-11ea-978b-ef723be80619.gif)
## ⚙ Installation
_This package requires **Unity 2018.3 or later**._
#### Install via OpenUPM
<br><br><br><br>
- This package is available on [OpenUPM](https://openupm.com) package registry.
- This is the preferred method of installation, as you can easily receive updates as they're released.
- If you have [openupm-cli](https://github.com/openupm/openupm-cli) installed, then run the following command in your project's directory:
```
openupm add com.coffee.ui-particle
```
- 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.8.0
```
## Installation
#### Install via UPM (with Package Manager UI)
### Requirement
- 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`
![](https://gist.github.com/assets/12690315/24af63ed-8a2e-483d-9023-7aa53d913330)
- To update the package, change suffix `#{version}` to the target version.
- e.g. `https://github.com/mob-sakai/ParticleEffectForUGUI.git#4.8.0`
![](https://img.shields.io/badge/Unity%202018.2+-supported-blue.svg)
![](https://img.shields.io/badge/Unity%202019.x-supported-blue.svg)
![](https://img.shields.io/badge/Unity%202020.x-supported-blue.svg)
![](https://img.shields.io/badge/Universal%20Rendering%20Pipeline-supported-blue.svg)
#### Install via UPM (Manually)
### Using OpenUPM
- Open the `Packages/manifest.json` file in your project. Then add this package somewhere in the `dependencies` block:
```json
{
"dependencies": {
"com.coffee.ui-particle": "https://github.com/mob-sakai/ParticleEffectForUGUI.git",
...
}
}
```
This package is available on [OpenUPM](https://openupm.com).
You can install it via [openupm-cli](https://github.com/openupm/openupm-cli).
```
openupm add com.coffee.ui-particle
```
- 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.8.0",`
### Using Git
#### Install as Embedded Package
Find the manifest.json file in the Packages folder of your project and add a line to `dependencies` field.
1. Download a source code zip file from [Releases](https://github.com/mob-sakai/ParticleEffectForUGUI.git/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.
* `"com.coffee.ui-particle": "https://github.com/mob-sakai/ParticleEffectForUGUI.git"`
To update the package, change suffix `#{version}` to the target version.
* `"com.coffee.ui-particle": "https://github.com/mob-sakai/ParticleEffectForUGUI.git#3.3.0",`
Or, use [UpmGitExtension](https://github.com/mob-sakai/UpmGitExtension) to install and update the package.
### For Unity 2018.2
Unity 2018.2 supports embedded packages.
1. Download a source code zip file from [Releases](https://github.com/mob-sakai/ParticleEffectForUGUI/releases) page
2. Extract it
3. Import it under `Packages` directory in your Unity project
<br><br><br><br>
## How to play demo
### For Unity 2019.1 or later
1. Open `Package Manager` window
2. Select `UI Particle` package in package list
3. Click `Import Sample` button
![demo](https://user-images.githubusercontent.com/12690315/95017806-83bd1480-0696-11eb-8c24-c56f45ab1ac2.png)
4. The demo project is imported into `Assets/Samples/UI Particle/{version}/Demo`
5. Open `UIParticle_Demo` scene and play it
### For Unity 2018.4 or earlier
1. Select `Assets/Samples/UI Particle Demo` from menu
2. The demo project is imported into `Assets/Samples/UI Particle/{version}/Demo`
3. Open `UIParticle_Demo` scene and play it
### About `Cartoon FX & War Fx Demo`
* It requires free assets ([Cartoon FX Free][CFX] & [War FX][WFX])
* by [Jean Moreno (JMO)][JMO]
<br><br><br><br>
## Usage
### UIParticle component
`UIParticle` controls the ParticleSystems that is attached to its own game objects and child game objects.
![](https://user-images.githubusercontent.com/12690315/99765566-af129a80-2b42-11eb-88f6-661182d0b619.png)
| Properties | Description |
| -- | -- |
| Maskable | Does this graphic allow masking. |
| Ignore Canvas Scale | Ignore the scale of the root canvas.<br>This prevents it from displaying small even in hierarchy scaling mode of `ParticleSystem`. |
| Scale | Scale the rendering.<br>When the `3D` toggle is enabled, 3D scale (x,y,z) is supported. |
| Animatable Properties | If you want update material properties (e.g. `_MainTex_ST`, `_Color`) in AnimationClip, use this to mark the changes. |
| Shrink By Material | Shrink rendering by material.<br>Performance will be improved, but in some cases the rendering is not correct. |
| Rendering Order | The ParticleSystems to be rendered.<br>You can change the rendering order and the materials. |
NOTE: Press `Refresh` button to reconstruct rendering order based on children ParticleSystem's sorting order and z position.
<br><br>
## 🚀 Usage
### Basically usage
### UIParticle Component
`UIParticle` controls the ParticleSystems that are attached to its own game objects and child game objects.
![](https://github.com/mob-sakai/ParticleEffectForUGUI/assets/12690315/1cf5753b-33fc-4cef-91c3-413c515a954f)
- **Maskable**: Does this graphic allow maskable.
- **Scale**: Scale the rendering particles. When the `3D` toggle is enabled, 3D scale (x, y, z) is supported.
- **Animatable Properties**: If you want to update material properties (e.g., `_MainTex_ST`, `_Color`) in AnimationClip,
use this to mark as animatable.
- **Mesh Sharing**: Particle simulation results are shared within the same group. A large number of the same effects can
be displayed with a small load. When the `Random` toggle is enabled, it will be grouped randomly.
- **None:** Disable mesh sharing.
- **Auto:** Automatically select Primary/Replica.
- **Primary:** Provides particle simulation results to the same group.
- **Primary Simulator:** Primary, but do not render the particle (simulation only).
- **Replica:** Render simulation results provided by the primary.
- **Position Mode**: Emission position mode.
- **Absolute:** The particles will be emitted from the world position.
- **Relative:** The particles will be emitted from the scaled position.
- **Auto Scaling Mode**: How to automatically adjust when the Canvas scale is changed by the screen size or reference resolution.
- **None:** Do nothing.
- **Transform:** Transform.lossyScale (=world scale) will be set to (1, 1, 1).
- **UIParticle:** UIParticle.scale will be adjusted.
- **Use Custom View:** Use this if the particles are not displayed correctly due to min/max particle size.
- **Custom view size:** Change the bake view size.
- **Rendering Order**: The ParticleSystem list to be rendered. You can change the order and the materials.
**NOTE:** Press the `Refresh` button to reconstruct the rendering order based on children ParticleSystem's sorting order
and z-position.
1. Select `Game Object/UI/ParticleSystem` to create UIParticle with a ParticleSystem.
![particle](https://user-images.githubusercontent.com/12690315/95007361-cad0e880-0649-11eb-8835-f145d62c5977.png)
2. Adjust the ParticleSystem as you like.
![particle1](https://user-images.githubusercontent.com/12690315/95007359-ca385200-0649-11eb-8383-627c9750bda8.png)
<br><br>
#### Basic Usage
### With your ParticleSystem prefab
1. Select `GameObject/UI/ParticleSystem` to create UIParticle with a ParticleSystem.
![particle](https://user-images.githubusercontent.com/12690315/95007361-cad0e880-0649-11eb-8835-f145d62c5977.png)
2. Adjust the ParticleSystem as you like.
![particle1](https://user-images.githubusercontent.com/12690315/95007359-ca385200-0649-11eb-8383-627c9750bda8.png)
1. Select `Game Object/UI/ParticleSystem (Empty)` to create UIParticle.
![empty](https://user-images.githubusercontent.com/12690315/95007362-cb697f00-0649-11eb-8a09-29b0a13791e4.png)
2. Drag & drop your ParticleSystem prefab on UIParticle.
![particle3](https://user-images.githubusercontent.com/12690315/95007356-c6a4cb00-0649-11eb-9316-562f4bce3f31.png)
<br>
<br><br>
#### With Your Existing ParticleSystem Prefab
### With `Mask` or `MaskRect2D` component
1. Select `GameObject/UI/ParticleSystem (Empty)` to create UIParticle.
![empty](https://user-images.githubusercontent.com/12690315/95007362-cb697f00-0649-11eb-8a09-29b0a13791e4.png)
2. Drag and drop your ParticleSystem prefab onto UIParticle.
![particle3](https://user-images.githubusercontent.com/12690315/95007356-c6a4cb00-0649-11eb-9316-562f4bce3f31.png)
<br>
#### With `Mask` or `RectMask2D` Component
If you want to mask particles, set a stencil-supported shader (such as `UI/UIAdditive`) to the material for
ParticleSystem.
If you use some custom shaders, see
the [How to Make a Custom Shader to Support Mask/RectMask2D Component](#how-to-make-a-custom-shader-to-support-maskrectmask2d-component)
section.
If you want to mask particles, set a stencil supported shader (such as `UI/UIAdditive`) to material for ParticleSystem.
![](https://user-images.githubusercontent.com/12690315/95017591-3b512700-0695-11eb-864e-04166ea1809a.png)
<br><br>
### Script usage
```cs
// Instantiate ParticleSystem prefab with UIParticle on runtime.
// Instant ParticleSystem prefab with UIParticle on runtime.
var go = GameObject.Instantiate(prefab);
var uiParticle = go.AddComponent<UIParticle>();
uiParticle.scale = 100;
// Control by ParticleSystem.
particleSystem.Play();
particleSystem.Emit(10);
// Control by UIParticle.
// Play/Stop the controled ParticleSystems.
uiParticle.Play();
uiParticle.Stop();
```
<br><br>
<br><br><br><br>
### UIParticleAttractor component
## Development Note
`UIParticleAttractor` attracts particles generated by the specified ParticleSystem.
### Animatable material property
![](https://github.com/mob-sakai/ParticleEffectForUGUI/assets/12690315/5c20ad73-4b9a-4f38-9cdc-119df5cce077)
![](https://user-images.githubusercontent.com/12690315/174311027-462929a4-13f0-4ec4-86ea-9c832f2eecf1.gif)
![](https://user-images.githubusercontent.com/12690315/53286323-2d94a980-37b0-11e9-8afb-c4a207805ff2.gif)
- **Particle System**: Attracts particles generated by the specified particle system.
- **Destination Radius**: Once the particle is within the radius, the particle lifetime will become 0, and `OnAttracted`
will be called.
- **Delay Rate**: Delay to start attracting. It is a percentage of the particle's start lifetime.
- **Max Speed**: Maximum speed of attracting. If this value is too small, attracting may not be completed by the end of
the lifetime, and `OnAttracted` may not be called.
- **Movement**: Attracting movement type. (`Linear`, `Smooth`, `Sphere`)
- **Update Mode**: Update mode.
- **Normal:** Update with scaled delta time.
- **Unscaled Time:** Update with unscaled delta time.
- **OnAttracted**: An event called when attracting is complete (per particle).
Animation clips can change the material properties of the Renderer, such as ParticleSystemRenderer.
It uses MaterialPropertyBlock so it does not create new material instances.
Using material properties, you can change UV animation, scale and color etc.
<br><br>
Well, there is a component called CanvasRenderer.
It is used by all Graphic components for UI (Text, Image, Raw Image, etc.) including UIParticle.
However, It is **NOT** a Renderer.
Therefore, in UIParticle, changing ParticleSystemRenderer's MaterialPropertyBlock by animation clip is ignored.
## 🛠 Development Note
To prevent this, Use "Animatable Material Property".
"Animatable Material Property" gets the necessary properties from ParticleSystemRenderer's MaterialPropertyBlock and sets them to the CanvasRenderer's material.
### Compares the Baking mesh approach with the conventional approach
- **Baking mesh approach (=UIParticle)**
![](https://user-images.githubusercontent.com/12690315/41765089-0302b9a2-763e-11e8-88b3-b6ffa306bbb0.gif)
- ✅ Rendered as is.
- ✅ Maskable.
- ✅ Sortable.
- ✅ Less objects.
- **Do nothing (=Plain ParticleSystem)**
![](https://user-images.githubusercontent.com/12690315/41765090-0329828a-763e-11e8-8d8a-f1d269ea3bc7.gif)
- ✅ Rendered as is.
- ❌ Looks like a glitch.
- ❌ Not maskable.
- ❌ Not sortable.
<br><br><br><br>
- **Convert particle to UIVertex (=[UIParticleSystem][UIParticleSystem])**
![](https://user-images.githubusercontent.com/12690315/41765088-02deb9c6-763e-11e8-98d0-9e0c1766ef39.gif)
- ✅ Maskable.
- ✅ Sortable.
- ❌ Adjustment is difficult.
- ❌ Requires UI shaders.
- ❌ Difficult to adjust scale.
- ❌ Force hierarchy scalling.
- ❌ Simulation results are incorrect.
- ❌ Trail, rotation of transform, time scaling are not supported.
- ❌ Generate heavy GC every frame.
- **Use Canvas to sort (Sorting By Canvas )**
![](https://user-images.githubusercontent.com/12690315/41765087-02b866ea-763e-11e8-8c33-081c9ad852f8.gif)
- ✅ Rendered as is.
- ✅ Sortable.
- ❌ You must to manage sorting orders.
- ❌ Not maskable.
- ❌ More batches.
- ❌ Requires Canvas.
- **Use RenderTexture**
![](https://user-images.githubusercontent.com/12690315/41765085-0291b3e2-763e-11e8-827b-72e5ee9bc556.gif)
- ✅ Maskable.
- ✅ Sortable.
- ❌ Requires Camera and RenderTexture.
- ❌ Difficult to adjust position and size.
- ❌ Quality depends on the RenderTexture's setting.
[UIParticleSystem]: https://forum.unity.com/threads/free-script-particle-systems-in-ui-screen-space-overlay.406862/
#### [Performance test results](https://github.com/mob-sakai/ParticleEffectForUGUI/issues/193#issuecomment-1160028374)
| Approach | FPS on Editor | FPS on iPhone6 | FPS on Xperia XZ |
|-----------------------------|---------------|----------------|------------------|
| Particle System | 43 | 57 | 22 |
| UIParticleSystem | 4 | 3 | 0 (unmeasurable) |
| Sorting By Canvas | 43 | 44 | 18 |
| UIParticle | 17 | 12 | 4 |
| UIParticle with MeshSharing | 44 | 45 | 30 |
### 🔍 FAQ: Why Are My UIParticles Not Displayed Correctly?
If `ParticleSystem` alone displays particles correctly but `UIParticle` does not, please check the following points:
- [Shader Limitation](#shader-limitation)
- `UIParticle` does not support all built-in shaders except for `UI/Default`.
- Most cases can be solved by using `UI/Additive` or `UI/Default`.
- Particles are not masked
- `UIParticle` is maskable.
- Set `Mask` or `RectMask2D` component properly.
- [Use maskable/clipable shader](#how-to-make-a-custom-shader-to-support-maskrectmask2d-component) (such
as `UI/Additive` or `UI/Default`)
- Particles are too small
- If particles are small enough, they will not appear on the screen.
- Increase the `Scale` value.
- If you don't want to change the apparent size depending on the resolution, try the `Auto Scaling` option.
- Particles are too many
- No more than 65535 vertices can be displayed (for mesh combination limitations).
- Please set `Emission` module and `Max Particles` of ParticleSystem properly.
- Particles are emitted off-screen.
- When `Position Mode = Relative`, particles are emitted from the scaled position of the ParticleSystem, not from
the screen point of the ParticleSystem.
- Place the ParticleSystem in the proper position or try `Position Mode = Absolute`.
- Attaching `UIParticle` to the same object as `ParticleSystem`
- `Transform.localScale` will be overridden by the `Auto Scaling` option.
- It is recommended to place `ParticleSystem` under `UIParticle`.
- If `Transform.localScale` contains 0, rendering will be skipped.
- Displayed particles are in the correct position but too large/too small
- Adjust `ParticleSystem.renderer.Min/MaxParticleSize`.
<br>
### Shader Limitation
The use of UI shaders is recommended.
- If you need a simple Additive shader, use the `UI/Additive` shader instead.
- If you need a simple alpha-blend shader, use the `UI/Default` shader instead.
- If your custom shader does not work properly with UIParticle, consider creating a custom UI shader.
#### Built-in shaders are not supported
`UIParticle` does not support all built-in shaders except for `UI/Default`.
If their use is detected, an error is displayed in the inspector.
Use UI shaders instead.
#### (Unity 2018 or 2019) UV.zw components will be discarded
UIParticleRenderer renders the particles based on UIVertex.
Therefore, only the xy components are available for each UV in the shader. (zw components will be discarded).
So unfortunately, UIParticles will not work well with some shaders.
#### (Unity 2018 or 2019) Custom vertex streams
When using custom vertex streams, you can fill zw components with "unnecessary" data.
Refer to [this issue](https://github.com/mob-sakai/ParticleEffectForUGUI/issues/191) for more information.
<br>
### Overheads
UIParticle has some overheads, and the batching depends on uGUI.
When improving performance, keep the following in mind:
- If you are displaying a large number of the same effect, consider the `Mesh Sharing` feature in
the [UIParticle Component](#uiparticle-component).
- If you don't like the uniform output, consider the `Random Group` feature.
![](https://user-images.githubusercontent.com/12690315/174311048-c882df81-6c34-4eba-b0aa-5645457692f1.gif)
- If you are using multiple materials, you will have more draw calls.
- Consider a single material, atlasing the sprites, and using `Sprite` mode in the `Texture Sheet Animation` module
in the ParticleSystem.
### How to Make a Custom Shader to Support Mask/RectMask2D Component
<details>
<summary>Shader tips</summary>
```ShaderLab
Shader "Your/Custom/Shader"
{
Properties
{
// ...
// #### required for Mask ####
_StencilComp ("Stencil Comparison", Float) = 8
_Stencil ("Stencil ID", Float) = 0
_StencilOp ("Stencil Operation", Float) = 0
_StencilWriteMask ("Stencil Write Mask", Float) = 255
_StencilReadMask ("Stencil Read Mask", Float) = 255
_ColorMask ("Color Mask", Float) = 15
[Toggle(UNITY_UI_ALPHACLIP)] _UseUIAlphaClip ("Use Alpha Clip", Float) = 0
}
SubShader
{
Tags
{
// ...
}
// #### required for Mask ####
Stencil
{
Ref [_Stencil]
Comp [_StencilComp]
Pass [_StencilOp]
ReadMask [_StencilReadMask]
WriteMask [_StencilWriteMask]
}
ColorMask [_ColorMask]
// ...
Pass
{
// ...
// #### required for RectMask2D ####
#include "UnityUI.cginc"
#pragma multi_compile __ UNITY_UI_CLIP_RECT
float4 _ClipRect;
// #### required for Mask ####
#pragma multi_compile __ UNITY_UI_ALPHACLIP
struct appdata_t
{
// ...
};
struct v2f
{
// ...
// #### required for RectMask2D ####
float4 worldPosition : TEXCOORD1;
};
v2f vert(appdata_t v)
{
v2f OUT;
// ...
// #### required for RectMask2D ####
OUT.worldPosition = v.vertex;
return OUT;
}
fixed4 frag(v2f IN) : SV_Target
{
// ...
// #### required for RectMask2D ####
#ifdef UNITY_UI_CLIP_RECT
color.a *= UnityGet2DClipping(IN.worldPosition.xy, _ClipRect);
#endif
// #### required for Mask ####
#ifdef UNITY_UI_ALPHACLIP
clip (color.a - 0.001);
#endif
return color;
}
ENDCG
}
}
}
```
</details>
<br><br>
## 🤝 Contributing
## Contributing
### Issues
Issues are incredibly valuable to this project:
Issues are very valuable to this project.
- Ideas provide a valuable source of contributions that others can make.
- Problems help identify areas where this project needs improvement.
- Questions indicate where contributors can enhance the user experience.
- Ideas are a valuable source of contributions others can make
- Problems show where this project is lacking
- With a question you show where contributors can improve the user experience
### Pull Requests
Pull requests offer a fantastic way to contribute your ideas to this repository.
Please refer to [CONTRIBUTING.md](https://github.com/mob-sakai/ParticleEffectForUGUI/blob/main/CONTRIBUTING.md)
and [develop branch](https://github.com/mob-sakai/ParticleEffectForUGUI/tree/develop) for guidelines.
Pull requests are, a great way to get your ideas into this repository.
See [CONTRIBUTING.md](/../../blob/develop/CONTRIBUTING.md).
### Support
This is an open-source project developed during my spare time.
If you appreciate it, consider supporting me.
Your support allows me to dedicate more time to development. 😊
This is an open source project that I am developing in my spare time.
If you like it, please support me.
With your support, I can spend more time on development. :)
[![](https://user-images.githubusercontent.com/12690315/50731629-3b18b480-11ad-11e9-8fad-4b13f27969c1.png)](https://www.patreon.com/join/2343451?)
[![](https://user-images.githubusercontent.com/12690315/50731629-3b18b480-11ad-11e9-8fad-4b13f27969c1.png)](https://www.patreon.com/join/mob_sakai?)
[![](https://user-images.githubusercontent.com/12690315/66942881-03686280-f085-11e9-9586-fc0b6011029f.png)](https://github.com/users/mob-sakai/sponsorship)
<br><br>
<br><br><br><br>
## License
* MIT
## Author
* ![](https://user-images.githubusercontent.com/12690315/96986908-434a0b80-155d-11eb-8275-85138ab90afa.png) [mob-sakai](https://github.com/mob-sakai) [![](https://img.shields.io/twitter/follow/mob_sakai.svg?label=Follow&style=social)](https://twitter.com/intent/follow?screen_name=mob_sakai) ![GitHub followers](https://img.shields.io/github/followers/mob-sakai?style=social)
## See Also
* GitHub page : https://github.com/mob-sakai/ParticleEffectForUGUI
* Releases : https://github.com/mob-sakai/ParticleEffectForUGUI/releases
* Issue tracker : https://github.com/mob-sakai/ParticleEffectForUGUI/issues
* Change log : https://github.com/mob-sakai/ParticleEffectForUGUI/blob/main/CHANGELOG.md
* Change log : https://github.com/mob-sakai/ParticleEffectForUGUI/blob/upm/CHANGELOG.md

View File

@@ -1,748 +0,0 @@
using System;
using System.Collections.Generic;
using System.Runtime.CompilerServices;
using Coffee.UIParticleExtensions;
using UnityEngine;
using UnityEngine.Rendering;
using UnityEngine.Serialization;
using UnityEngine.UI;
using Random = UnityEngine.Random;
[assembly: InternalsVisibleTo("Coffee.UIParticle.Editor")]
namespace Coffee.UIExtensions
{
/// <summary>
/// Render maskable and sortable particle effect ,without Camera, RenderTexture or Canvas.
/// </summary>
[ExecuteAlways]
[RequireComponent(typeof(RectTransform))]
[RequireComponent(typeof(CanvasRenderer))]
public class UIParticle : MaskableGraphic, ISerializationCallbackReceiver
{
public enum AutoScalingMode
{
None,
UIParticle,
Transform
}
public enum MeshSharing
{
None,
Auto,
Primary,
PrimarySimulator,
Replica
}
public enum PositionMode
{
Relative,
Absolute
}
[HideInInspector]
[SerializeField]
[Obsolete]
internal bool m_IsTrail;
[HideInInspector]
[FormerlySerializedAs("m_IgnoreParent")]
[SerializeField]
[Obsolete]
private bool m_IgnoreCanvasScaler;
[HideInInspector]
[SerializeField]
[Obsolete]
internal bool m_AbsoluteMode;
[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);
[Tooltip("If you want to update material properties (e.g. _MainTex_ST, _Color) in AnimationClip, " +
"use this to mark as animatable.")]
[SerializeField]
internal AnimatableProperty[] m_AnimatableProperties = new AnimatableProperty[0];
[Tooltip("Particles")]
[SerializeField]
private List<ParticleSystem> m_Particles = new List<ParticleSystem>();
[Tooltip("Particle simulation results are shared within the same group. " +
"A large number of the same effects can be displayed with a small load.\n" +
"None: Disable mesh sharing.\n" +
"Auto: Automatically select Primary/Replica.\n" +
"Primary: Provides particle simulation results to the same group.\n" +
"Primary Simulator: Primary, but do not render the particle (simulation only).\n" +
"Replica: Render simulation results provided by the primary.")]
[SerializeField]
private MeshSharing m_MeshSharing = MeshSharing.None;
[Tooltip("Mesh sharing group ID.\n" +
"If non-zero is specified, particle simulation results are shared within the group.")]
[SerializeField]
private int m_GroupId;
[SerializeField]
private int m_GroupMaxId;
[Tooltip("Emission position mode.\n" +
"Relative: The particles will be emitted from the scaled position.\n" +
"Absolute: The particles will be emitted from the world position.")]
[SerializeField]
private PositionMode m_PositionMode = PositionMode.Relative;
[SerializeField]
[Obsolete]
internal bool m_AutoScaling;
[SerializeField]
[Tooltip(
"How to automatically adjust when the Canvas scale is changed by the screen size or reference resolution.\n" +
"None: Do nothing.\n" +
"Transform: Transform.lossyScale (=world scale) will be set to (1, 1, 1).\n" +
"UIParticle: UIParticle.scale will be adjusted.")]
private AutoScalingMode m_AutoScalingMode = AutoScalingMode.Transform;
[SerializeField]
[Tooltip("Use a custom view.\n" +
"Use this if the particles are not displayed correctly due to min/max particle size.")]
private bool m_UseCustomView;
[SerializeField]
[Tooltip("Custom view size.\n" +
"Change the bake view size.")]
private float m_CustomViewSize = 10;
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
{
get => false;
set { }
}
/// <summary>
/// Particle simulation results are shared within the same group.
/// A large number of the same effects can be displayed with a small load.
/// None: disable mesh sharing.
/// Auto: automatically select Primary/Replica.
/// Primary: provides particle simulation results to the same group.
/// Primary Simulator: Primary, but do not render the particle (simulation only).
/// Replica: render simulation results provided by the primary.
/// </summary>
public MeshSharing meshSharing
{
get => m_MeshSharing;
set => m_MeshSharing = value;
}
/// <summary>
/// Mesh sharing group ID.
/// If non-zero is specified, particle simulation results are shared within the group.
/// </summary>
public int groupId
{
get => _groupId;
set
{
if (m_GroupId == value) return;
m_GroupId = value;
if (m_GroupId != m_GroupMaxId)
{
ResetGroupId();
}
}
}
public int groupMaxId
{
get => m_GroupMaxId;
set
{
if (m_GroupMaxId == value) return;
m_GroupMaxId = value;
ResetGroupId();
}
}
/// <summary>
/// Emission position mode.
/// Relative: The particles will be emitted from the scaled position.
/// Absolute: The particles will be emitted from the world position.
/// </summary>
public PositionMode positionMode
{
get => m_PositionMode;
set => m_PositionMode = value;
}
/// <summary>
/// Particle position mode.
/// Relative: The particles will be emitted from the scaled position of the ParticleSystem.
/// Absolute: The particles will be emitted from the world position of the ParticleSystem.
/// </summary>
[Obsolete("The absoluteMode is now obsolete. Please use the autoScalingMode instead.", false)]
public bool absoluteMode
{
get => m_PositionMode == PositionMode.Absolute;
set => positionMode = value ? PositionMode.Absolute : PositionMode.Relative;
}
/// <summary>
/// Prevents the root-Canvas scale from affecting the hierarchy-scaled ParticleSystem.
/// </summary>
[Obsolete("The autoScaling is now obsolete. Please use the autoScalingMode instead.", false)]
public bool autoScaling
{
get => m_AutoScalingMode != AutoScalingMode.None;
set => autoScalingMode = value ? AutoScalingMode.Transform : AutoScalingMode.None;
}
/// <summary>
/// How to automatically adjust when the Canvas scale is changed by the screen size or reference resolution.
/// <para/>
/// None: Do nothing.
/// <para/>
/// Transform: Transform.lossyScale (=world scale) will be set to (1, 1, 1).
/// <para/>
/// UIParticle: UIParticle.scale will be adjusted.
/// </summary>
public AutoScalingMode autoScalingMode
{
get => m_AutoScalingMode;
set
{
if (m_AutoScalingMode == value) return;
m_AutoScalingMode = value;
if (autoScalingMode != AutoScalingMode.Transform && _isScaleStored)
{
transform.localScale = _storedScale;
_isScaleStored = false;
}
}
}
/// <summary>
/// Use a custom view.
/// Use this if the particles are not displayed correctly due to min/max particle size.
/// </summary>
public bool useCustomView
{
get => m_UseCustomView;
set => m_UseCustomView = value;
}
/// <summary>
/// Custom view size.
/// Change the bake view size.
/// </summary>
public float customViewSize
{
get => m_CustomViewSize;
set => m_CustomViewSize = Mathf.Max(0.1f, value);
}
internal bool useMeshSharing => m_MeshSharing != MeshSharing.None;
internal bool isPrimary =>
m_MeshSharing == MeshSharing.Primary
|| m_MeshSharing == MeshSharing.PrimarySimulator;
internal bool canSimulate =>
m_MeshSharing == MeshSharing.None
|| m_MeshSharing == MeshSharing.Auto
|| m_MeshSharing == MeshSharing.Primary
|| m_MeshSharing == MeshSharing.PrimarySimulator;
internal bool canRender =>
m_MeshSharing == MeshSharing.None
|| m_MeshSharing == MeshSharing.Auto
|| m_MeshSharing == MeshSharing.Primary
|| m_MeshSharing == MeshSharing.Replica;
/// <summary>
/// Particle effect scale.
/// </summary>
public float scale
{
get => m_Scale3D.x;
set => m_Scale3D = new Vector3(value, value, value);
}
/// <summary>
/// Particle effect scale.
/// </summary>
public Vector3 scale3D
{
get => m_Scale3D;
set => m_Scale3D = value;
}
/// <summary>
/// Particle effect scale.
/// </summary>
public Vector3 scale3DForCalc => autoScalingMode == AutoScalingMode.Transform
? m_Scale3D
: m_Scale3D.GetScaled(canvasScale, transform.localScale);
public List<ParticleSystem> particles => m_Particles;
/// <summary>
/// Paused.
/// </summary>
public bool isPaused { get; private set; }
public Vector3 parentScale { get; private set; }
public Vector3 canvasScale { get; private set; }
protected override void OnEnable()
{
_isScaleStored = false;
ResetGroupId();
UIParticleUpdater.Register(this);
RegisterDirtyMaterialCallback(UpdateRendererMaterial);
if (0 < particles.Count)
{
RefreshParticles(particles);
}
else
{
RefreshParticles();
}
base.OnEnable();
}
/// <summary>
/// This function is called when the behaviour becomes disabled.
/// </summary>
protected override void OnDisable()
{
_tracker.Clear();
if (autoScalingMode == AutoScalingMode.Transform && _isScaleStored)
{
transform.localScale = _storedScale;
}
_isScaleStored = false;
UIParticleUpdater.Unregister(this);
_renderers.ForEach(r => r.Reset());
UnregisterDirtyMaterialCallback(UpdateRendererMaterial);
base.OnDisable();
}
/// <summary>
/// Callback for when properties have been changed by animation.
/// </summary>
protected override void OnDidApplyAnimationProperties()
{
}
/// <summary>
/// This function is called when a direct or indirect parent of the transform of the GameObject has changed.
/// </summary>
protected override void OnTransformParentChanged()
{
}
void ISerializationCallbackReceiver.OnBeforeSerialize()
{
}
void ISerializationCallbackReceiver.OnAfterDeserialize()
{
#pragma warning disable CS0612 // Type or member is obsolete
if (m_IgnoreCanvasScaler || m_AutoScaling)
{
m_IgnoreCanvasScaler = false;
m_AutoScaling = false;
m_AutoScalingMode = AutoScalingMode.Transform;
}
if (m_AbsoluteMode)
{
m_AbsoluteMode = false;
m_PositionMode = PositionMode.Absolute;
}
#pragma warning restore CS0612 // Type or member is obsolete
}
/// <summary>
/// Play the ParticleSystems.
/// </summary>
public void Play()
{
particles.Exec(p => p.Simulate(0, false, true));
isPaused = false;
}
/// <summary>
/// Pause the ParticleSystems.
/// </summary>
public void Pause()
{
particles.Exec(p => p.Pause());
isPaused = true;
}
/// <summary>
/// Unpause the ParticleSystems.
/// </summary>
public void Resume()
{
isPaused = false;
}
/// <summary>
/// Stop the ParticleSystems.
/// </summary>
public void Stop()
{
particles.Exec(p => p.Stop());
isPaused = true;
}
/// <summary>
/// Start emission of the ParticleSystems.
/// </summary>
public void StartEmission()
{
particles.Exec(p =>
{
var emission = p.emission;
emission.enabled = true;
});
}
/// <summary>
/// Stop emission of the ParticleSystems.
/// </summary>
public void StopEmission()
{
particles.Exec(p =>
{
var emission = p.emission;
emission.enabled = false;
});
}
/// <summary>
/// Clear the particles of the ParticleSystems.
/// </summary>
public void Clear()
{
particles.Exec(p => p.Clear());
isPaused = true;
}
/// <summary>
/// Get all base materials to render.
/// </summary>
public void GetMaterials(List<Material> result)
{
if (result == null) return;
for (var i = 0; i < _renderers.Count; i++)
{
var r = _renderers[i];
if (!r || !r.material) continue;
result.Add(r.material);
}
}
/// <summary>
/// Refresh UIParticle using the ParticleSystem instance.
/// </summary>
public void SetParticleSystemInstance(GameObject instance)
{
SetParticleSystemInstance(instance, true);
}
/// <summary>
/// Refresh UIParticle using the ParticleSystem instance.
/// </summary>
public void SetParticleSystemInstance(GameObject instance, bool destroyOldParticles)
{
if (!instance) return;
var childCount = transform.childCount;
for (var i = 0; i < childCount; i++)
{
var go = transform.GetChild(i).gameObject;
if (go.TryGetComponent<Camera>(out var cam) && cam == _bakeCamera) continue;
if (go.TryGetComponent<UIParticleRenderer>(out var _)) continue;
go.SetActive(false);
if (destroyOldParticles)
{
Misc.Destroy(go);
}
}
var tr = instance.transform;
tr.SetParent(transform, false);
tr.localPosition = Vector3.zero;
RefreshParticles(instance);
}
/// <summary>
/// Refresh UIParticle using the prefab.
/// The prefab is automatically instantiated.
/// </summary>
public void SetParticleSystemPrefab(GameObject prefab)
{
if (!prefab) return;
SetParticleSystemInstance(Instantiate(prefab.gameObject), true);
}
/// <summary>
/// Refresh UIParticle.
/// Collect ParticleSystems under the GameObject and refresh the UIParticle.
/// </summary>
public void RefreshParticles()
{
RefreshParticles(gameObject);
}
/// <summary>
/// Refresh UIParticle.
/// Collect ParticleSystems under the GameObject and refresh the UIParticle.
/// </summary>
private void RefreshParticles(GameObject root)
{
if (!root) return;
root.GetComponentsInChildren(true, particles);
for (var i = particles.Count - 1; 0 <= i; i--)
{
var ps = particles[i];
if (!ps || ps.GetComponentInParent<UIParticle>(true) != this)
{
particles.RemoveAt(i);
}
}
for (var i = 0; i < particles.Count; i++)
{
var ps = particles[i];
var tsa = ps.textureSheetAnimation;
if (tsa.mode == ParticleSystemAnimationMode.Sprites && tsa.uvChannelMask == 0)
{
tsa.uvChannelMask = UVChannelFlags.UV0;
}
}
RefreshParticles(particles);
}
/// <summary>
/// Refresh UIParticle using a list of ParticleSystems.
/// </summary>
public void RefreshParticles(List<ParticleSystem> particleSystems)
{
// Collect children UIParticleRenderer components.
// #246: Nullptr exceptions when using nested UIParticle components in hierarchy
_renderers.Clear();
var childCount = transform.childCount;
for (var i = 0; i < childCount; i++)
{
var child = transform.GetChild(i);
if (child.TryGetComponent(out UIParticleRenderer uiParticleRenderer))
{
_renderers.Add(uiParticleRenderer);
}
}
// Reset the UIParticleRenderer components.
for (var i = 0; i < _renderers.Count; i++)
{
_renderers[i].Reset(i);
}
// Set the ParticleSystem to the UIParticleRenderer. If the trail is enabled, set it additionally.
var j = 0;
for (var i = 0; i < particleSystems.Count; i++)
{
var ps = particleSystems[i];
if (!ps) continue;
GetRenderer(j++).Set(this, ps, false);
// If the trail is enabled, set it additionally.
if (ps.trails.enabled)
{
GetRenderer(j++).Set(this, ps, true);
}
}
}
internal void UpdateTransformScale()
{
_tracker.Clear();
canvasScale = canvas.rootCanvas.transform.localScale.Inverse();
parentScale = transform.parent.lossyScale;
if (autoScalingMode != AutoScalingMode.Transform)
{
if (_isScaleStored)
{
transform.localScale = _storedScale;
}
_isScaleStored = false;
return;
}
var currentScale = transform.localScale;
if (!_isScaleStored)
{
_storedScale = currentScale.IsVisible() ? currentScale : Vector3.one;
_isScaleStored = true;
}
_tracker.Add(this, rectTransform, DrivenTransformProperties.Scale);
var newScale = parentScale.Inverse();
if (currentScale != newScale)
{
transform.localScale = newScale;
}
}
internal void UpdateRenderers()
{
if (!isActiveAndEnabled) return;
for (var i = 0; i < _renderers.Count; i++)
{
var r = _renderers[i];
if (r) continue;
RefreshParticles(particles);
break;
}
var bakeCamera = GetBakeCamera();
for (var i = 0; i < _renderers.Count; i++)
{
var r = _renderers[i];
if (!r) continue;
r.UpdateMesh(bakeCamera);
}
}
internal void ResetGroupId()
{
_groupId = m_GroupId == m_GroupMaxId
? m_GroupId
: 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) continue;
r.maskable = maskable;
r.SetMaterialDirty();
}
}
internal UIParticleRenderer GetRenderer(int index)
{
if (_renderers.Count <= index)
{
_renderers.Add(UIParticleRenderer.AddRenderer(this, index));
}
if (!_renderers[index])
{
_renderers[index] = UIParticleRenderer.AddRenderer(this, index);
}
return _renderers[index];
}
private Camera GetBakeCamera()
{
if (!canvas) return Camera.main;
if (!useCustomView && canvas.renderMode != RenderMode.ScreenSpaceOverlay && canvas.rootCanvas.worldCamera)
{
return canvas.rootCanvas.worldCamera;
}
if (_bakeCamera)
{
_bakeCamera.orthographicSize = useCustomView ? customViewSize : 10;
return _bakeCamera;
}
// Find existing baking camera.
var childCount = transform.childCount;
for (var i = 0; i < childCount; i++)
{
if (transform.GetChild(i).TryGetComponent<Camera>(out var cam)
&& cam.name == "[generated] UIParticle BakingCamera")
{
_bakeCamera = cam;
break;
}
}
// Create baking camera.
if (!_bakeCamera)
{
var go = new GameObject("[generated] UIParticle BakingCamera");
go.SetActive(false);
go.transform.SetParent(transform, false);
_bakeCamera = go.AddComponent<Camera>();
}
// Setup baking camera.
_bakeCamera.enabled = false;
_bakeCamera.orthographicSize = useCustomView ? customViewSize : 10;
_bakeCamera.transform.SetPositionAndRotation(new Vector3(0, 0, -1000), Quaternion.identity);
_bakeCamera.orthographic = true;
_bakeCamera.farClipPlane = 2000f;
_bakeCamera.clearFlags = CameraClearFlags.Nothing;
_bakeCamera.cullingMask = 0; // Nothing
_bakeCamera.allowHDR = false;
_bakeCamera.allowMSAA = false;
_bakeCamera.renderingPath = RenderingPath.Forward;
_bakeCamera.useOcclusionCulling = false;
_bakeCamera.gameObject.SetActive(false);
_bakeCamera.gameObject.hideFlags = HideFlags.HideAndDontSave;
return _bakeCamera;
}
}
}

View File

@@ -1,11 +0,0 @@
fileFormatVersion: 2
guid: 16f0b0b6d0b7542bfbd20a3e05b04ff1
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {fileID: 2800000, guid: 5f0675613942149309588d556e33d990, type: 3}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -1,262 +0,0 @@
using System;
using Coffee.UIParticleExtensions;
using UnityEngine;
using UnityEngine.Events;
namespace Coffee.UIExtensions
{
[ExecuteAlways]
public class UIParticleAttractor : MonoBehaviour
{
public enum Movement
{
Linear,
Smooth,
Sphere
}
public enum UpdateMode
{
Normal,
UnscaledTime
}
[SerializeField]
private ParticleSystem m_ParticleSystem;
[Range(0.1f, 10f)]
[SerializeField]
private float m_DestinationRadius = 1;
[Range(0f, 0.95f)]
[SerializeField]
private float m_DelayRate;
[Range(0.001f, 100f)]
[SerializeField]
private float m_MaxSpeed = 1;
[SerializeField]
private Movement m_Movement;
[SerializeField]
private UpdateMode m_UpdateMode;
[SerializeField]
private UnityEvent m_OnAttracted;
private UIParticle _uiParticle;
public float destinationRadius
{
get => m_DestinationRadius;
set => m_DestinationRadius = Mathf.Clamp(value, 0.1f, 10f);
}
public float delay
{
get => m_DelayRate;
set => m_DelayRate = value;
}
public float maxSpeed
{
get => m_MaxSpeed;
set => m_MaxSpeed = value;
}
public Movement movement
{
get => m_Movement;
set => m_Movement = value;
}
public UpdateMode updateMode
{
get => m_UpdateMode;
set => m_UpdateMode = value;
}
public UnityEvent onAttracted
{
get => m_OnAttracted;
set => m_OnAttracted = value;
}
/// <summary>
/// The target ParticleSystem to attract.
/// </summary>
#if UNITY_EDITOR
public new ParticleSystem particleSystem
#else
public ParticleSystem particleSystem
#endif
{
get => m_ParticleSystem;
set
{
m_ParticleSystem = value;
ApplyParticleSystem();
}
}
private void OnEnable()
{
ApplyParticleSystem();
UIParticleUpdater.Register(this);
}
private void OnDisable()
{
UIParticleUpdater.Unregister(this);
}
private void OnDestroy()
{
_uiParticle = null;
m_ParticleSystem = null;
}
internal void Attract()
{
if (m_ParticleSystem == null) return;
var count = m_ParticleSystem.particleCount;
if (count == 0) return;
var particles = ParticleSystemExtensions.GetParticleArray(count);
m_ParticleSystem.GetParticles(particles, count);
var dstPos = GetDestinationPosition();
for (var i = 0; i < count; i++)
{
// Attracted
var p = particles[i];
if (0f < p.remainingLifetime && Vector3.Distance(p.position, dstPos) < m_DestinationRadius)
{
p.remainingLifetime = 0f;
particles[i] = p;
if (m_OnAttracted != null)
{
try
{
m_OnAttracted.Invoke();
}
catch (Exception e)
{
Debug.LogException(e);
}
}
continue;
}
// Calc attracting time
var delayTime = p.startLifetime * m_DelayRate;
var duration = p.startLifetime - delayTime;
var time = Mathf.Max(0, p.startLifetime - p.remainingLifetime - delayTime);
// Delay
if (time <= 0) continue;
// Attract
p.position = GetAttractedPosition(p.position, dstPos, duration, time);
p.velocity *= 0.5f;
particles[i] = p;
}
m_ParticleSystem.SetParticles(particles, count);
}
private Vector3 GetDestinationPosition()
{
var isUI = _uiParticle && _uiParticle.enabled;
var psPos = m_ParticleSystem.transform.position;
var attractorPos = transform.position;
var dstPos = attractorPos;
var isLocalSpace = m_ParticleSystem.IsLocalSpace();
if (isLocalSpace)
{
dstPos = m_ParticleSystem.transform.InverseTransformPoint(dstPos);
}
if (isUI)
{
var inverseScale = _uiParticle.parentScale.Inverse();
var scale3d = _uiParticle.scale3DForCalc;
dstPos = dstPos.GetScaled(inverseScale, scale3d.Inverse());
// Relative mode
if (_uiParticle.positionMode == UIParticle.PositionMode.Relative)
{
var diff = _uiParticle.transform.position - psPos;
diff.Scale(scale3d - inverseScale);
diff.Scale(scale3d.Inverse());
dstPos += diff;
}
#if UNITY_EDITOR
if (!Application.isPlaying && !isLocalSpace)
{
dstPos += psPos - psPos.GetScaled(inverseScale, scale3d.Inverse());
}
#endif
}
return dstPos;
}
private Vector3 GetAttractedPosition(Vector3 current, Vector3 target, float duration, float time)
{
var speed = m_MaxSpeed;
switch (m_UpdateMode)
{
case UpdateMode.Normal:
speed *= 60 * Time.deltaTime;
break;
case UpdateMode.UnscaledTime:
speed *= 60 * Time.unscaledDeltaTime;
break;
}
switch (m_Movement)
{
case Movement.Linear:
speed /= duration;
break;
case Movement.Smooth:
target = Vector3.Lerp(current, target, time / duration);
break;
case Movement.Sphere:
target = Vector3.Slerp(current, target, time / duration);
break;
}
return Vector3.MoveTowards(current, target, speed);
}
private void ApplyParticleSystem()
{
_uiParticle = null;
if (m_ParticleSystem == null)
{
#if UNITY_EDITOR
if (Application.isPlaying)
#endif
{
Debug.LogError("No particle system attached to particle attractor script", this);
}
return;
}
_uiParticle = m_ParticleSystem.GetComponentInParent<UIParticle>(true);
if (_uiParticle && !_uiParticle.particles.Contains(m_ParticleSystem))
{
_uiParticle = null;
}
}
}
}

View File

@@ -1,715 +0,0 @@
#if UNITY_2022_3_0 || UNITY_2022_3_1 || UNITY_2022_3_2 || UNITY_2022_3_3 || UNITY_2022_3_4 || UNITY_2022_3_5 || UNITY_2022_3_6 || UNITY_2022_3_7 || UNITY_2022_3_8 || UNITY_2022_3_9 || UNITY_2022_3_10
#elif UNITY_2023_1_0 || UNITY_2023_1_1 || UNITY_2023_1_2 || UNITY_2023_1_3 || UNITY_2023_1_4 || UNITY_2023_1_5 || UNITY_2023_1_6 || UNITY_2023_1_7 || UNITY_2023_1_8 || UNITY_2023_1_9
#elif UNITY_2023_1_10 || UNITY_2023_1_11 || UNITY_2023_1_12 || UNITY_2023_1_13 || UNITY_2023_1_14 || UNITY_2023_1_15 || UNITY_2023_1_16
#elif UNITY_2022_3_OR_NEWER
#define PS_BAKE_API_V2
#endif
using System;
using System.Collections.Generic;
using Coffee.UIParticleExtensions;
using UnityEditor;
using UnityEngine;
using UnityEngine.Profiling;
using UnityEngine.Rendering;
using UnityEngine.UI;
namespace Coffee.UIExtensions
{
[ExecuteAlways]
[RequireComponent(typeof(RectTransform))]
[RequireComponent(typeof(CanvasRenderer))]
[AddComponentMenu("")]
internal class UIParticleRenderer : MaskableGraphic
{
private static readonly List<Component> s_Components = new List<Component>();
private static readonly CombineInstance[] s_CombineInstances = { new CombineInstance() };
private static readonly List<Material> s_Materials = new List<Material>(2);
private static MaterialPropertyBlock s_Mpb;
private static readonly List<UIParticleRenderer> s_Renderers = new List<UIParticleRenderer>();
private static readonly List<Color32> s_Colors = new List<Color32>();
private static readonly Vector3[] s_Corners = new Vector3[4];
private Material _currentMaterialForRendering;
private bool _delay;
private int _index;
private bool _isPrevStored;
private bool _isTrail;
private Bounds _lastBounds;
private Material _modifiedMaterial;
private UIParticle _parent;
private ParticleSystem _particleSystem;
private float _prevCanvasScale;
private Vector3 _prevPsPos;
private Vector3 _prevScale;
private Vector2Int _prevScreenSize;
private bool _preWarm;
private ParticleSystemRenderer _renderer;
public override Texture mainTexture => _isTrail ? null : _particleSystem.GetTextureForSprite();
public override bool raycastTarget => false;
private Rect rootCanvasRect
{
get
{
s_Corners[0] = transform.TransformPoint(_lastBounds.min.x, _lastBounds.min.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[3] = transform.TransformPoint(_lastBounds.max.x, _lastBounds.min.y, 0);
if (canvas)
{
var worldToLocalMatrix = canvas.rootCanvas.transform.worldToLocalMatrix;
for (var i = 0; i < 4; ++i)
{
s_Corners[i] = worldToLocalMatrix.MultiplyPoint(s_Corners[i]);
}
}
var corner1 = (Vector2)s_Corners[0];
var corner2 = (Vector2)s_Corners[0];
for (var i = 1; i < 4; ++i)
{
if (s_Corners[i].x < corner1.x)
{
corner1.x = s_Corners[i].x;
}
else if (s_Corners[i].x > corner2.x)
{
corner2.x = s_Corners[i].x;
}
if (s_Corners[i].y < corner1.y)
{
corner1.y = s_Corners[i].y;
}
else if (s_Corners[i].y > corner2.y)
{
corner2.y = s_Corners[i].y;
}
}
return new Rect(corner1, corner2 - corner1);
}
}
public void Reset(int index = -1)
{
if (_renderer)
{
_renderer.enabled = true;
}
_parent = null;
_particleSystem = null;
_renderer = null;
if (0 <= index)
{
_index = index;
}
//_emitter = null;
if (this && isActiveAndEnabled)
{
material = null;
canvasRenderer.Clear();
_lastBounds = new Bounds();
enabled = false;
}
else
{
ModifiedMaterial.Remove(_modifiedMaterial);
_modifiedMaterial = null;
_currentMaterialForRendering = null;
}
}
protected override void OnEnable()
{
base.OnEnable();
if (!s_CombineInstances[0].mesh)
{
s_CombineInstances[0].mesh = new Mesh
{
name = "[UIParticleRenderer] Combine Instance Mesh",
hideFlags = HideFlags.HideAndDontSave
};
}
_currentMaterialForRendering = null;
}
protected override void OnDisable()
{
base.OnDisable();
ModifiedMaterial.Remove(_modifiedMaterial);
_modifiedMaterial = null;
_currentMaterialForRendering = null;
_isPrevStored = false;
}
public static UIParticleRenderer AddRenderer(UIParticle parent, int index)
{
// Create renderer object.
var go = new GameObject("[generated] UIParticleRenderer", typeof(UIParticleRenderer))
{
hideFlags = HideFlags.HideAndDontSave,
layer = parent.gameObject.layer
};
// Set parent.
var transform = go.transform;
transform.SetParent(parent.transform, false);
transform.localPosition = Vector3.zero;
transform.localRotation = Quaternion.identity;
transform.localScale = Vector3.one;
// Add renderer component.
var renderer = go.GetComponent<UIParticleRenderer>();
renderer._parent = parent;
renderer._index = index;
return renderer;
}
/// <summary>
/// Perform material modification in this function.
/// </summary>
public override Material GetModifiedMaterial(Material baseMaterial)
{
_currentMaterialForRendering = null;
if (!IsActive() || !_parent)
{
ModifiedMaterial.Remove(_modifiedMaterial);
_modifiedMaterial = null;
return baseMaterial;
}
var modifiedMaterial = base.GetModifiedMaterial(baseMaterial);
//
var texture = mainTexture;
if (texture == null && _parent.m_AnimatableProperties.Length == 0)
{
ModifiedMaterial.Remove(_modifiedMaterial);
_modifiedMaterial = null;
return modifiedMaterial;
}
//
var id = _parent.m_AnimatableProperties.Length == 0 ? 0 : GetInstanceID();
#if UNITY_EDITOR
var props = EditorJsonUtility.ToJson(modifiedMaterial).GetHashCode();
#else
var props = 0;
#endif
modifiedMaterial = ModifiedMaterial.Add(modifiedMaterial, texture, id, props);
ModifiedMaterial.Remove(_modifiedMaterial);
_modifiedMaterial = modifiedMaterial;
return modifiedMaterial;
}
public void Set(UIParticle parent, ParticleSystem ps, bool isTrail)
{
_parent = parent;
maskable = parent.maskable;
gameObject.layer = parent.gameObject.layer;
_particleSystem = ps;
_preWarm = _particleSystem.main.prewarm;
#if UNITY_EDITOR
if (Application.isPlaying)
#endif
{
if (_particleSystem.isPlaying || _preWarm)
{
_particleSystem.Clear();
_particleSystem.Pause();
}
}
ps.TryGetComponent(out _renderer);
_renderer.enabled = false;
//_emitter = emitter;
_isTrail = isTrail;
_renderer.GetSharedMaterials(s_Materials);
material = s_Materials[isTrail ? 1 : 0];
s_Materials.Clear();
// Support sprite.
var tsa = ps.textureSheetAnimation;
if (tsa.mode == ParticleSystemAnimationMode.Sprites && tsa.uvChannelMask == 0)
{
tsa.uvChannelMask = UVChannelFlags.UV0;
}
_prevScale = GetWorldScale();
_prevPsPos = _particleSystem.transform.position;
_prevScreenSize = new Vector2Int(Screen.width, Screen.height);
_prevCanvasScale = canvas ? canvas.scaleFactor : 1f;
_delay = true;
canvasRenderer.SetTexture(null);
enabled = true;
}
public void UpdateMesh(Camera bakeCamera)
{
// No particle to render: Clear mesh.
if (
!isActiveAndEnabled || !_particleSystem || !_parent
|| !canvasRenderer || !canvas || !bakeCamera
|| _parent.meshSharing == UIParticle.MeshSharing.Replica
|| !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
)
{
Profiler.BeginSample("[UIParticleRenderer] Clear Mesh");
workerMesh.Clear();
canvasRenderer.SetMesh(workerMesh);
_lastBounds = new Bounds();
Profiler.EndSample();
return;
}
var main = _particleSystem.main;
var scale = GetWorldScale();
var psPos = _particleSystem.transform.position;
// Simulate particles.
Profiler.BeginSample("[UIParticle] Bake Mesh > Simulate Particles");
if (!_isTrail && _parent.canSimulate)
{
#if UNITY_EDITOR
if (!Application.isPlaying)
{
SimulateForEditor(psPos - _prevPsPos, scale);
}
else
#endif
{
ResolveResolutionChange(psPos, scale);
Simulate(scale, _parent.isPaused || _delay);
if (_delay && !_parent.isPaused)
{
Simulate(scale, _parent.isPaused);
}
// When the ParticleSystem simulation is complete, stop it.
if (!main.loop
&& main.duration <= _particleSystem.time
&& (_particleSystem.IsAlive() || _particleSystem.particleCount == 0)
)
{
_particleSystem.Stop(false);
}
}
_prevScale = scale;
_prevPsPos = psPos;
_delay = false;
}
Profiler.EndSample();
// Bake mesh.
Profiler.BeginSample("[UIParticleRenderer] Bake Mesh");
s_CombineInstances[0].mesh.Clear(false);
// Assertion failed on expression: 'ps->array_size()' #278
var extends = s_CombineInstances[0].mesh.bounds.extents.x;
if (!float.IsNaN(extends) && !float.IsInfinity(extends) && 0 < extends)
{
s_CombineInstances[0].mesh.RecalculateBounds();
}
if (_isTrail && _parent.canSimulate && 0 < _particleSystem.particleCount)
{
#if PS_BAKE_API_V2
_renderer.BakeTrailsMesh(s_CombineInstances[0].mesh, bakeCamera,
ParticleSystemBakeMeshOptions.BakeRotationAndScale);
#else
_renderer.BakeTrailsMesh(s_CombineInstances[0].mesh, bakeCamera, true);
#endif
}
else if (!_isTrail && _renderer.CanBakeMesh())
{
_particleSystem.ValidateShape();
#if PS_BAKE_API_V2
_renderer.BakeMesh(s_CombineInstances[0].mesh, bakeCamera,
ParticleSystemBakeMeshOptions.BakeRotationAndScale);
#else
_renderer.BakeMesh(s_CombineInstances[0].mesh, bakeCamera, true);
#endif
}
// Too many vertices to render.
if (65535 <= s_CombineInstances[0].mesh.vertexCount)
{
Debug.LogErrorFormat(this,
"Too many vertices to render. index={0}, isTrail={1}, vertexCount={2}(>=65535)",
_index,
_isTrail,
s_CombineInstances[0].mesh.vertexCount
);
s_CombineInstances[0].mesh.Clear(false);
}
Profiler.EndSample();
// Combine mesh to transform. ([ParticleSystem local ->] world -> renderer local)
Profiler.BeginSample("[UIParticleRenderer] Combine Mesh");
if (_parent.canSimulate)
{
if (_parent.positionMode == UIParticle.PositionMode.Absolute)
{
s_CombineInstances[0].transform =
canvasRenderer.transform.worldToLocalMatrix
* GetWorldMatrix(psPos, scale);
}
else
{
var diff = _particleSystem.transform.position - _parent.transform.position;
s_CombineInstances[0].transform =
canvasRenderer.transform.worldToLocalMatrix
* Matrix4x4.Translate(diff.GetScaled(scale - Vector3.one))
* GetWorldMatrix(psPos, scale);
}
workerMesh.CombineMeshes(s_CombineInstances, true, true);
workerMesh.RecalculateBounds();
var bounds = workerMesh.bounds;
var center = bounds.center;
center.z = 0;
bounds.center = center;
var extents = bounds.extents;
extents.z = 0;
bounds.extents = extents;
workerMesh.bounds = bounds;
_lastBounds = bounds;
// Convert linear color to gamma color.
if (QualitySettings.activeColorSpace == ColorSpace.Linear)
{
Profiler.BeginSample("[UIParticleRenderer] Convert Linear to Gamma");
workerMesh.GetColors(s_Colors);
var count_c = s_Colors.Count;
for (var i = 0; i < count_c; i++)
{
var c = s_Colors[i];
c.r = c.r.LinearToGamma();
c.g = c.g.LinearToGamma();
c.b = c.b.LinearToGamma();
s_Colors[i] = c;
}
workerMesh.SetColors(s_Colors);
Profiler.EndSample();
}
GetComponents(typeof(IMeshModifier), s_Components);
for (var i = 0; i < s_Components.Count; i++)
{
#pragma warning disable CS0618 // Type or member is obsolete
((IMeshModifier)s_Components[i]).ModifyMesh(workerMesh);
#pragma warning restore CS0618 // Type or member is obsolete
}
s_Components.Clear();
}
Profiler.EndSample();
// Get grouped renderers.
s_Renderers.Clear();
if (_parent.useMeshSharing)
{
UIParticleUpdater.GetGroupedRenderers(_parent.groupId, _index, s_Renderers);
}
// Set mesh to the CanvasRenderer.
Profiler.BeginSample("[UIParticleRenderer] Set Mesh");
for (var i = 0; i < s_Renderers.Count; i++)
{
if (s_Renderers[i] == this) continue;
s_Renderers[i].canvasRenderer.SetMesh(workerMesh);
s_Renderers[i]._lastBounds = _lastBounds;
}
if (!_parent.canRender)
{
workerMesh.Clear();
}
canvasRenderer.SetMesh(workerMesh);
Profiler.EndSample();
// Update animatable material properties.
Profiler.BeginSample("[UIParticleRenderer] Update Animatable Material Properties");
#if UNITY_EDITOR
if (_modifiedMaterial != material)
{
_renderer.GetSharedMaterials(s_Materials);
material = s_Materials[_isTrail ? 1 : 0];
s_Materials.Clear();
SetMaterialDirty();
}
#endif
UpdateMaterialProperties();
if (_parent.useMeshSharing)
{
if (!_currentMaterialForRendering)
{
_currentMaterialForRendering = materialForRendering;
}
for (var i = 0; i < s_Renderers.Count; i++)
{
if (s_Renderers[i] == this) continue;
s_Renderers[i].canvasRenderer.materialCount = 1;
s_Renderers[i].canvasRenderer.SetMaterial(_currentMaterialForRendering, 0);
}
}
Profiler.EndSample();
s_Renderers.Clear();
}
/// <summary>
/// Call to update the geometry of the Graphic onto the CanvasRenderer.
/// </summary>
protected override void UpdateGeometry()
{
}
public override void Cull(Rect clipRect, bool validRect)
{
var cull = _lastBounds.extents == Vector3.zero
|| !validRect
|| !clipRect.Overlaps(rootCanvasRect, true);
if (canvasRenderer.cull == cull) return;
canvasRenderer.cull = cull;
UISystemProfilerApi.AddMarker("MaskableGraphic.cullingChanged", this);
onCullStateChanged.Invoke(cull);
OnCullingChanged();
}
private Vector3 GetWorldScale()
{
Profiler.BeginSample("[UIParticleRenderer] GetWorldScale");
var scale = _parent.scale3DForCalc.GetScaled(_parent.parentScale);
if (_parent.autoScalingMode == UIParticle.AutoScalingMode.UIParticle
&& _particleSystem.main.scalingMode == ParticleSystemScalingMode.Local
&& _parent.canvas)
{
scale = scale.GetScaled(_parent.canvas.rootCanvas.transform.localScale);
}
Profiler.EndSample();
return scale;
}
private Matrix4x4 GetWorldMatrix(Vector3 psPos, Vector3 scale)
{
var space = _particleSystem.GetActualSimulationSpace();
if (_isTrail && _particleSystem.trails.worldSpace)
{
space = ParticleSystemSimulationSpace.World;
}
#if UNITY_EDITOR
if (!Application.isPlaying)
{
switch (space)
{
case ParticleSystemSimulationSpace.World:
return Matrix4x4.Translate(psPos)
* Matrix4x4.Scale(scale)
* Matrix4x4.Translate(-psPos);
}
}
#endif
switch (space)
{
case ParticleSystemSimulationSpace.Local:
return Matrix4x4.Translate(psPos)
* Matrix4x4.Scale(scale);
case ParticleSystemSimulationSpace.World:
return Matrix4x4.Scale(scale);
case ParticleSystemSimulationSpace.Custom:
return Matrix4x4.Translate(_particleSystem.main.customSimulationSpace.position.GetScaled(scale))
* Matrix4x4.Scale(scale);
default:
throw new NotSupportedException();
}
}
/// <summary>
/// For world simulation, interpolate particle positions when the screen size is changed.
/// </summary>
/// <param name="psPos"></param>
/// <param name="scale"></param>
private void ResolveResolutionChange(Vector3 psPos, Vector3 scale)
{
var screenSize = new Vector2Int(Screen.width, Screen.height);
var isWorldSpace = _particleSystem.IsWorldSpace();
var canvasScale = _parent.canvas ? _parent.canvas.scaleFactor : 1f;
var resolutionChanged = _prevScreenSize != screenSize
|| !Mathf.Approximately(_prevCanvasScale, canvasScale);
if (resolutionChanged && isWorldSpace && _isPrevStored)
{
// Update particle array size and get particles.
var size = _particleSystem.particleCount;
var particles = ParticleSystemExtensions.GetParticleArray(size);
_particleSystem.GetParticles(particles, size);
// Resolution resolver:
// (psPos / scale) / (prevPsPos / prevScale) -> psPos * scale.inv * prevPsPos.inv * prevScale
var modifier = psPos.GetScaled(
scale.Inverse(),
_prevPsPos.Inverse(),
_prevScale);
for (var i = 0; i < size; i++)
{
var particle = particles[i];
particle.position = particle.position.GetScaled(modifier);
particles[i] = particle;
}
_particleSystem.SetParticles(particles, size);
// Delay: Do not progress in the frame where the resolution has been changed.
_delay = true;
_prevScale = scale;
_prevPsPos = psPos;
_isPrevStored = true;
}
_prevCanvasScale = canvas ? canvas.scaleFactor : 1f;
_prevScreenSize = screenSize;
}
private void Simulate(Vector3 scale, bool paused)
{
var main = _particleSystem.main;
var deltaTime = paused
? 0
: main.useUnscaledTime
? Time.unscaledDeltaTime
: Time.deltaTime;
// Pre-warm:
if (0 < deltaTime && _preWarm)
{
deltaTime += main.duration;
_preWarm = false;
}
// get world position.
var isLocalSpace = _particleSystem.IsLocalSpace();
var psTransform = _particleSystem.transform;
var originLocalPosition = psTransform.localPosition;
var originLocalRotation = psTransform.localRotation;
var originWorldPosition = psTransform.position;
var originWorldRotation = psTransform.rotation;
var emission = _particleSystem.emission;
var rateOverDistance = emission.enabled
&& 0 < emission.rateOverDistance.constant
&& 0 < emission.rateOverDistanceMultiplier;
if (rateOverDistance && !paused && _isPrevStored)
{
// (For rate-over-distance emission,) Move to previous scaled position, simulate (delta = 0).
var prevScaledPos = isLocalSpace
? _prevPsPos
: _prevPsPos.GetScaled(_prevScale.Inverse());
psTransform.SetPositionAndRotation(prevScaledPos, originWorldRotation);
_particleSystem.Simulate(0, false, false, false);
}
// Move to scaled position, simulate, revert to origin position.
var scaledPos = isLocalSpace
? originWorldPosition
: originWorldPosition.GetScaled(scale.Inverse());
psTransform.SetPositionAndRotation(scaledPos, originWorldRotation);
_particleSystem.Simulate(deltaTime, false, false, false);
psTransform.localPosition = originLocalPosition;
psTransform.localRotation = originLocalRotation;
}
#if UNITY_EDITOR
private void SimulateForEditor(Vector3 diffPos, Vector3 scale)
{
// Extra world simulation.
var isWorldSpace = _particleSystem.IsWorldSpace();
if (isWorldSpace && 0 < Vector3.SqrMagnitude(diffPos))
{
Profiler.BeginSample("[UIParticle] Bake Mesh > Extra world simulation");
diffPos.x *= 1f - 1f / Mathf.Max(0.001f, scale.x);
diffPos.y *= 1f - 1f / Mathf.Max(0.001f, scale.y);
diffPos.z *= 1f - 1f / Mathf.Max(0.001f, scale.z);
var size = _particleSystem.particleCount;
var particles = ParticleSystemExtensions.GetParticleArray(size);
_particleSystem.GetParticles(particles, size);
for (var i = 0; i < size; i++)
{
var p = particles[i];
p.position += diffPos;
particles[i] = p;
}
_particleSystem.SetParticles(particles, size);
Profiler.EndSample();
}
}
#endif
private void UpdateMaterialProperties()
{
if (_parent.m_AnimatableProperties.Length == 0) return;
if (s_Mpb == null)
{
s_Mpb = new MaterialPropertyBlock();
}
_renderer.GetPropertyBlock(s_Mpb);
if (s_Mpb.isEmpty) return;
// #41: Copy the value from MaterialPropertyBlock to CanvasRenderer
if (!_modifiedMaterial) return;
for (var i = 0; i < _parent.m_AnimatableProperties.Length; i++)
{
var ap = _parent.m_AnimatableProperties[i];
ap.UpdateMaterialProperties(_modifiedMaterial, s_Mpb);
}
s_Mpb.Clear();
}
}
}

View File

@@ -1,121 +0,0 @@
using System.Collections.Generic;
using UnityEditor;
using UnityEngine;
namespace Coffee.UIExtensions
{
internal static class UIParticleUpdater
{
private static readonly List<UIParticle> s_ActiveParticles = new List<UIParticle>();
private static readonly List<UIParticleAttractor> s_ActiveAttractors = new List<UIParticleAttractor>();
private static readonly HashSet<int> s_UpdatedGroupIds = new HashSet<int>();
private static int s_FrameCount;
public static int uiParticleCount => s_ActiveParticles.Count;
public static void Register(UIParticle particle)
{
if (!particle) return;
s_ActiveParticles.Add(particle);
}
public static void Unregister(UIParticle particle)
{
if (!particle) return;
s_ActiveParticles.Remove(particle);
}
public static void Register(UIParticleAttractor attractor)
{
if (!attractor) return;
s_ActiveAttractors.Add(attractor);
}
public static void Unregister(UIParticleAttractor attractor)
{
if (!attractor) return;
s_ActiveAttractors.Remove(attractor);
}
#if UNITY_EDITOR
[InitializeOnLoadMethod]
#else
[RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.BeforeSceneLoad)]
#endif
private static void InitializeOnLoad()
{
Canvas.willRenderCanvases -= Refresh;
Canvas.willRenderCanvases += Refresh;
}
private static void Refresh()
{
// Do not allow it to be called in the same frame.
if (s_FrameCount == Time.frameCount) return;
s_FrameCount = Time.frameCount;
// Simulate -> Primary
for (var i = 0; i < s_ActiveParticles.Count; i++)
{
var uip = s_ActiveParticles[i];
if (!uip || !uip.canvas || !uip.isPrimary || !s_UpdatedGroupIds.Add(uip.groupId)) continue;
uip.UpdateTransformScale();
uip.UpdateRenderers();
}
// Simulate -> Others
for (var i = 0; i < s_ActiveParticles.Count; i++)
{
var uip = s_ActiveParticles[i];
if (!uip || !uip.canvas) continue;
uip.UpdateTransformScale();
if (!uip.useMeshSharing)
{
uip.UpdateRenderers();
}
else if (s_UpdatedGroupIds.Add(uip.groupId))
{
uip.UpdateRenderers();
}
}
s_UpdatedGroupIds.Clear();
// Attract
for (var i = 0; i < s_ActiveAttractors.Count; i++)
{
s_ActiveAttractors[i].Attract();
}
}
public static void GetGroupedRenderers(int groupId, int index, List<UIParticleRenderer> results)
{
results.Clear();
for (var i = 0; i < s_ActiveParticles.Count; i++)
{
var uip = s_ActiveParticles[i];
if (uip.useMeshSharing && uip.groupId == groupId)
{
results.Add(uip.GetRenderer(index));
}
}
}
internal static UIParticle GetPrimary(int groupId)
{
UIParticle primary = null;
for (var i = 0; i < s_ActiveParticles.Count; i++)
{
var uip = s_ActiveParticles[i];
if (!uip.useMeshSharing || uip.groupId != groupId) continue;
if (uip.isPrimary) return uip;
if (!primary && uip.canSimulate) primary = uip;
}
return primary;
}
}
}

View File

@@ -1,308 +0,0 @@
using System;
using System.Collections.Generic;
using System.Reflection;
using UnityEngine;
using Object = UnityEngine.Object;
namespace Coffee.UIParticleExtensions
{
public static class Color32Extensions
{
private static byte[] s_LinearToGammaLut;
public static byte LinearToGamma(this byte self)
{
if (s_LinearToGammaLut == null)
{
s_LinearToGammaLut = new byte[256];
for (var i = 0; i < 256; i++)
{
s_LinearToGammaLut[i] = (byte)(Mathf.LinearToGammaSpace(i / 255f) * 255f);
}
}
return s_LinearToGammaLut[self];
}
}
public static class Vector3Extensions
{
public static Vector3 Inverse(this Vector3 self)
{
self.x = Mathf.Approximately(self.x, 0) ? 1 : 1 / self.x;
self.y = Mathf.Approximately(self.y, 0) ? 1 : 1 / self.y;
self.z = Mathf.Approximately(self.z, 0) ? 1 : 1 / self.z;
return self;
}
public static Vector3 GetScaled(this Vector3 self, Vector3 other1)
{
self.Scale(other1);
return self;
}
public static Vector3 GetScaled(this Vector3 self, Vector3 other1, Vector3 other2)
{
self.Scale(other1);
self.Scale(other2);
return self;
}
public static Vector3 GetScaled(this Vector3 self, Vector3 other1, Vector3 other2, Vector3 other3)
{
self.Scale(other1);
self.Scale(other2);
self.Scale(other3);
return self;
}
public static bool IsVisible(this Vector3 self)
{
return 0 < Mathf.Abs(self.x * self.y * self.z);
}
}
internal static class SpriteExtensions
{
#if UNITY_EDITOR
private static readonly Type s_SpriteEditorExtensionType =
Type.GetType("UnityEditor.Experimental.U2D.SpriteEditorExtension, UnityEditor")
?? Type.GetType("UnityEditor.U2D.SpriteEditorExtension, UnityEditor");
private static readonly MethodInfo s_GetActiveAtlasTextureMethodInfo = s_SpriteEditorExtensionType
.GetMethod("GetActiveAtlasTexture", BindingFlags.Static | BindingFlags.NonPublic);
public static Texture2D GetActualTexture(this Sprite self)
{
if (!self) return null;
if (Application.isPlaying) return self.texture;
var ret = s_GetActiveAtlasTextureMethodInfo.Invoke(null, new object[] { self }) as Texture2D;
return ret
? ret
: self.texture;
}
#else
internal static Texture2D GetActualTexture(this Sprite self)
{
return self ? self.texture : null;
}
#endif
}
public static class ParticleSystemExtensions
{
private static ParticleSystem.Particle[] s_TmpParticles = new ParticleSystem.Particle[2048];
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];
}
return s_TmpParticles;
}
public static void ValidateShape(this ParticleSystem self)
{
var shape = self.shape;
if (shape.enabled && shape.alignToDirection)
{
if (Mathf.Approximately(shape.scale.x * shape.scale.y * shape.scale.z, 0))
{
if (Mathf.Approximately(shape.scale.x, 0))
{
shape.scale.Set(0.0001f, shape.scale.y, shape.scale.z);
}
else if (Mathf.Approximately(shape.scale.y, 0))
{
shape.scale.Set(shape.scale.x, 0.0001f, shape.scale.z);
}
else if (Mathf.Approximately(shape.scale.z, 0))
{
shape.scale.Set(shape.scale.x, shape.scale.y, 0.0001f);
}
}
}
}
public static bool CanBakeMesh(this ParticleSystemRenderer self)
{
// #69: Editor crashes when mesh is set to null when `ParticleSystem.RenderMode = Mesh`
if (self.renderMode == ParticleSystemRenderMode.Mesh && self.mesh == null) return false;
// #61: When `ParticleSystem.RenderMode = None`, an error occurs
if (self.renderMode == ParticleSystemRenderMode.None) return false;
return true;
}
public static ParticleSystemSimulationSpace GetActualSimulationSpace(this ParticleSystem self)
{
var main = self.main;
var space = main.simulationSpace;
if (space == ParticleSystemSimulationSpace.Custom && !main.customSimulationSpace)
{
space = ParticleSystemSimulationSpace.Local;
}
return space;
}
public static bool IsLocalSpace(this ParticleSystem self)
{
return GetActualSimulationSpace(self) == ParticleSystemSimulationSpace.Local;
}
public static bool IsWorldSpace(this ParticleSystem self)
{
return GetActualSimulationSpace(self) == ParticleSystemSimulationSpace.World;
}
public static void SortForRendering(this List<ParticleSystem> self, Transform transform, bool sortByMaterial)
{
self.Sort((a, b) =>
{
var aRenderer = a.GetComponent<ParticleSystemRenderer>();
var bRenderer = b.GetComponent<ParticleSystemRenderer>();
// Render queue: ascending
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.GetInstanceID() - bMat.GetInstanceID();
}
if (aMat.renderQueue != bMat.renderQueue)
{
return aMat.renderQueue - bMat.renderQueue;
}
// Sorting layer: ascending
if (aRenderer.sortingLayerID != bRenderer.sortingLayerID)
{
return SortingLayer.GetLayerValueFromID(aRenderer.sortingLayerID) -
SortingLayer.GetLayerValueFromID(bRenderer.sortingLayerID);
}
// Sorting order: ascending
if (aRenderer.sortingOrder != bRenderer.sortingOrder)
{
return aRenderer.sortingOrder - bRenderer.sortingOrder;
}
// Z position & sortingFudge: descending
var aTransform = a.transform;
var bTransform = b.transform;
var aPos = transform.InverseTransformPoint(aTransform.position).z + aRenderer.sortingFudge;
var bPos = transform.InverseTransformPoint(bTransform.position).z + bRenderer.sortingFudge;
if (!Mathf.Approximately(aPos, bPos))
{
return (int)Mathf.Sign(bPos - aPos);
}
return (int)Mathf.Sign(GetIndex(self, a) - GetIndex(self, b));
});
}
private static int GetIndex(IList<ParticleSystem> list, Object ps)
{
for (var i = 0; i < list.Count; i++)
{
if (list[i].GetInstanceID() == ps.GetInstanceID())
{
return i;
}
}
return 0;
}
public static Texture2D GetTextureForSprite(this ParticleSystem self)
{
if (!self) return null;
// Get sprite's texture.
var tsaModule = self.textureSheetAnimation;
if (!tsaModule.enabled || tsaModule.mode != ParticleSystemAnimationMode.Sprites) return null;
for (var i = 0; i < tsaModule.spriteCount; i++)
{
var sprite = tsaModule.GetSprite(i);
if (!sprite) continue;
return sprite.GetActualTexture();
}
return null;
}
public static void Exec(this List<ParticleSystem> self, Action<ParticleSystem> action)
{
self.RemoveAll(p => !p);
self.ForEach(action);
}
}
internal static class Misc
{
public static void Destroy(Object obj)
{
if (!obj) return;
#if UNITY_EDITOR
if (!Application.isPlaying)
{
Object.DestroyImmediate(obj);
}
else
#endif
{
Object.Destroy(obj);
}
}
public static void DestroyImmediate(Object obj)
{
if (!obj) return;
#if UNITY_EDITOR
if (Application.isEditor)
{
Object.DestroyImmediate(obj);
}
else
#endif
{
Object.Destroy(obj);
}
}
#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) return null;
if (!includeInactive) return self.GetComponentInParent<T>();
var current = self.transform;
while (current)
{
var component = current.GetComponent<T>();
if (component) return component;
current = current.parent;
}
return null;
}
#endif
}
}

View File

@@ -1,5 +1,5 @@
fileFormatVersion: 2
guid: 097ebac92791448c1871b0dffb43c4c6
guid: 15e5409f0334e479e91e672ae14567d3
folderAsset: yes
DefaultImporter:
externalObjects: {}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,4 @@
fileFormatVersion: 2
guid: 064daa6b97d6846ec9334e98d642f081
DefaultImporter:
userData:

View File

@@ -1,5 +1,5 @@
{
"name": "Coffee.UIParticle.Demo",
"name": "Coffee.CFX_Demo_With_UIParticle",
"references": [
"Coffee.UIParticle"
],
@@ -9,6 +9,6 @@
"allowUnsafeCode": false,
"overrideReferences": false,
"precompiledReferences": [],
"autoReferenced": false,
"autoReferenced": true,
"defineConstraints": []
}

View File

@@ -1,7 +1,6 @@
fileFormatVersion: 2
guid: bd5b57519ab8b45df881c2be89882e8f
folderAsset: yes
DefaultImporter:
guid: 67b89587ad4f645e18aa12053a6cc9b7
AssemblyDefinitionImporter:
externalObjects: {}
userData:
assetBundleName:

View File

@@ -0,0 +1,85 @@
using System;
using System.Linq;
using System.Reflection;
using Coffee.UIExtensions;
using UnityEditor;
using UnityEngine;
using UnityEngine.SceneManagement;
using UnityEngine.UI;
using Object = UnityEngine.Object;
public class CFX_Demo_With_UIParticle : MonoBehaviour
{
private UIParticle UiParticle;
private Toggle spawnOnUI;
private MonoBehaviour demo;
// Start is called before the first frame update
private void Start()
{
UiParticle = GetComponentInChildren<UIParticle>();
spawnOnUI = GetComponentInChildren<Toggle>();
demo = FindObjectOfType("CFX_Demo_New") as MonoBehaviour
?? FindObjectOfType("WFX_Demo_New") as MonoBehaviour;
SetCanvasWidth(800);
SetCanvasRenderOverlay(true);
}
private Object FindObjectOfType(string typeName)
{
var type = AppDomain.CurrentDomain.GetAssemblies()
.SelectMany(x => x.GetTypes())
.FirstOrDefault(x => x.Name == typeName);
return type == null ? null : FindObjectOfType(type);
}
// Update is called once per frame
private void Update()
{
if (!spawnOnUI.isOn || !demo || !Input.GetMouseButtonDown(0)) return;
foreach (Transform child in UiParticle.transform)
{
Destroy(child.gameObject);
}
var particle = demo.GetType()
.GetMethod("spawnParticle", BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public)
.Invoke(demo, new object[0]) as GameObject;
particle.transform.localScale = Vector3.one;
UiParticle.SetParticleSystemInstance(particle);
}
public void SetCanvasWidth(int width)
{
var scaler = GetComponentInParent<CanvasScaler>();
scaler.screenMatchMode = CanvasScaler.ScreenMatchMode.MatchWidthOrHeight;
scaler.matchWidthOrHeight = 0;
var resolution = scaler.referenceResolution;
resolution.x = width;
scaler.referenceResolution = resolution;
}
public void SetCanvasRenderOverlay(bool enable)
{
var canvas = GetComponentInParent<Canvas>();
if (enable)
{
canvas.renderMode = RenderMode.ScreenSpaceOverlay;
}
else
{
canvas.worldCamera = Camera.main;
canvas.renderMode = RenderMode.ScreenSpaceCamera;
canvas.planeDistance = 5;
}
}
public void LoadScene(string scene)
{
SceneManager.LoadScene(scene);
}
}

View File

@@ -1,5 +1,5 @@
fileFormatVersion: 2
guid: d1979128e1e7d427cb18fde94c6ff4b5
guid: a845100b226da488ab9037ad254b5860
MonoImporter:
externalObjects: {}
serializedVersion: 2

File diff suppressed because it is too large Load Diff

View File

@@ -1,5 +1,5 @@
fileFormatVersion: 2
guid: 0ddf94eaac8ad4e0cba66dc25b7fc1f5
guid: 3432d66abba624d4fad1150154199656
PrefabImporter:
externalObjects: {}
userData:

View File

@@ -0,0 +1,4 @@
Cartoon FX & War FX Demo
===
Please import assets "Cartoon FX Free" and/or "War FX Free" from Unity asset store.

View File

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

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,4 @@
fileFormatVersion: 2
guid: a81f9cd434f104e1fad7ffa20eb7a3d4
DefaultImporter:
userData:

View File

@@ -1,339 +0,0 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!91 &9100000
AnimatorController:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_Name: UIParticle_Demo_Animatable
serializedVersion: 5
m_AnimatorParameters: []
m_AnimatorLayers:
- serializedVersion: 5
m_Name: Base Layer
m_StateMachine: {fileID: 1107990299158400902}
m_Mask: {fileID: 0}
m_Motions: []
m_Behaviours: []
m_BlendingMode: 0
m_SyncedLayerIndex: -1
m_DefaultWeight: 0
m_IKPass: 0
m_SyncedLayerAffectsTiming: 0
m_Controller: {fileID: 9100000}
--- !u!74 &74971957227727780
AnimationClip:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_Name: UIParticle_Demo_Animatable
serializedVersion: 6
m_Legacy: 0
m_Compressed: 0
m_UseHighQualityCurve: 1
m_RotationCurves: []
m_CompressedRotationCurves: []
m_EulerCurves: []
m_PositionCurves: []
m_ScaleCurves: []
m_FloatCurves:
- curve:
serializedVersion: 2
m_Curve:
- serializedVersion: 3
time: 0
value: 1
inSlope: 0
outSlope: 0
tangentMode: 136
weightedMode: 0
inWeight: 0.33333334
outWeight: 0.33333334
m_PreInfinity: 2
m_PostInfinity: 2
m_RotationOrder: 4
attribute: material._MainTex_ST.x
path:
classID: 199
script: {fileID: 0}
- curve:
serializedVersion: 2
m_Curve:
- serializedVersion: 3
time: 0
value: 1
inSlope: 0
outSlope: 0
tangentMode: 136
weightedMode: 0
inWeight: 0.33333334
outWeight: 0.33333334
m_PreInfinity: 2
m_PostInfinity: 2
m_RotationOrder: 4
attribute: material._MainTex_ST.y
path:
classID: 199
script: {fileID: 0}
- curve:
serializedVersion: 2
m_Curve:
- serializedVersion: 3
time: 0
value: 0
inSlope: 0
outSlope: 0
tangentMode: 136
weightedMode: 0
inWeight: 0.33333334
outWeight: 0.33333334
m_PreInfinity: 2
m_PostInfinity: 2
m_RotationOrder: 4
attribute: material._MainTex_ST.z
path:
classID: 199
script: {fileID: 0}
- curve:
serializedVersion: 2
m_Curve:
- serializedVersion: 3
time: 0
value: -0.6
inSlope: 0
outSlope: 0
tangentMode: 136
weightedMode: 0
inWeight: 0.33333334
outWeight: 0.33333334
- serializedVersion: 3
time: 1
value: 0.6
inSlope: 0
outSlope: 0
tangentMode: 136
weightedMode: 0
inWeight: 0.33333334
outWeight: 0.33333334
- serializedVersion: 3
time: 1.5
value: 0.6
inSlope: 0
outSlope: 0
tangentMode: 136
weightedMode: 0
inWeight: 0.33333334
outWeight: 0.33333334
m_PreInfinity: 2
m_PostInfinity: 2
m_RotationOrder: 4
attribute: material._MainTex_ST.w
path:
classID: 199
script: {fileID: 0}
m_PPtrCurves: []
m_SampleRate: 30
m_WrapMode: 0
m_Bounds:
m_Center: {x: 0, y: 0, z: 0}
m_Extent: {x: 0, y: 0, z: 0}
m_ClipBindingConstant:
genericBindings:
- serializedVersion: 2
path: 0
attribute: 914802057
script: {fileID: 0}
typeID: 199
customType: 22
isPPtrCurve: 0
- serializedVersion: 2
path: 0
attribute: 109495689
script: {fileID: 0}
typeID: 199
customType: 22
isPPtrCurve: 0
- serializedVersion: 2
path: 0
attribute: 377931145
script: {fileID: 0}
typeID: 199
customType: 22
isPPtrCurve: 0
- serializedVersion: 2
path: 0
attribute: 646366601
script: {fileID: 0}
typeID: 199
customType: 22
isPPtrCurve: 0
pptrCurveMapping: []
m_AnimationClipSettings:
serializedVersion: 2
m_AdditiveReferencePoseClip: {fileID: 0}
m_AdditiveReferencePoseTime: 0
m_StartTime: 0
m_StopTime: 1.5
m_OrientationOffsetY: 0
m_Level: 0
m_CycleOffset: 0
m_HasAdditiveReferencePose: 0
m_LoopTime: 1
m_LoopBlend: 0
m_LoopBlendOrientation: 0
m_LoopBlendPositionY: 0
m_LoopBlendPositionXZ: 0
m_KeepOriginalOrientation: 0
m_KeepOriginalPositionY: 1
m_KeepOriginalPositionXZ: 0
m_HeightFromFeet: 0
m_Mirror: 0
m_EditorCurves:
- curve:
serializedVersion: 2
m_Curve:
- serializedVersion: 3
time: 0
value: 1
inSlope: 0
outSlope: 0
tangentMode: 136
weightedMode: 0
inWeight: 0.33333334
outWeight: 0.33333334
m_PreInfinity: 2
m_PostInfinity: 2
m_RotationOrder: 4
attribute: material._MainTex_ST.x
path:
classID: 199
script: {fileID: 0}
- curve:
serializedVersion: 2
m_Curve:
- serializedVersion: 3
time: 0
value: 1
inSlope: 0
outSlope: 0
tangentMode: 136
weightedMode: 0
inWeight: 0.33333334
outWeight: 0.33333334
m_PreInfinity: 2
m_PostInfinity: 2
m_RotationOrder: 4
attribute: material._MainTex_ST.y
path:
classID: 199
script: {fileID: 0}
- curve:
serializedVersion: 2
m_Curve:
- serializedVersion: 3
time: 0
value: 0
inSlope: 0
outSlope: 0
tangentMode: 136
weightedMode: 0
inWeight: 0.33333334
outWeight: 0.33333334
m_PreInfinity: 2
m_PostInfinity: 2
m_RotationOrder: 4
attribute: material._MainTex_ST.z
path:
classID: 199
script: {fileID: 0}
- curve:
serializedVersion: 2
m_Curve:
- serializedVersion: 3
time: 0
value: -0.6
inSlope: 0
outSlope: 0
tangentMode: 136
weightedMode: 0
inWeight: 0.33333334
outWeight: 0.33333334
- serializedVersion: 3
time: 1
value: 0.6
inSlope: 0
outSlope: 0
tangentMode: 136
weightedMode: 0
inWeight: 0.33333334
outWeight: 0.33333334
- serializedVersion: 3
time: 1.5
value: 0.6
inSlope: 0
outSlope: 0
tangentMode: 136
weightedMode: 0
inWeight: 0.33333334
outWeight: 0.33333334
m_PreInfinity: 2
m_PostInfinity: 2
m_RotationOrder: 4
attribute: material._MainTex_ST.w
path:
classID: 199
script: {fileID: 0}
m_EulerEditorCurves: []
m_HasGenericRootTransform: 0
m_HasMotionFloatCurves: 0
m_Events: []
--- !u!1102 &1102093862037490004
AnimatorState:
serializedVersion: 5
m_ObjectHideFlags: 1
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_Name: Play
m_Speed: 1
m_CycleOffset: 0
m_Transitions: []
m_StateMachineBehaviours: []
m_Position: {x: 50, y: 50, z: 0}
m_IKOnFeet: 0
m_WriteDefaultValues: 1
m_Mirror: 0
m_SpeedParameterActive: 0
m_MirrorParameterActive: 0
m_CycleOffsetParameterActive: 0
m_TimeParameterActive: 0
m_Motion: {fileID: 74971957227727780}
m_Tag:
m_SpeedParameter:
m_MirrorParameter:
m_CycleOffsetParameter:
m_TimeParameter:
--- !u!1107 &1107990299158400902
AnimatorStateMachine:
serializedVersion: 5
m_ObjectHideFlags: 1
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_Name: Base Layer
m_ChildStates:
- serializedVersion: 1
m_State: {fileID: 1102093862037490004}
m_Position: {x: 288, y: 48, z: 0}
m_ChildStateMachines: []
m_AnyStateTransitions: []
m_EntryTransitions: []
m_StateMachineTransitions: {}
m_StateMachineBehaviours: []
m_AnyStatePosition: {x: 50, y: 20, z: 0}
m_EntryPosition: {x: 48, y: 120, z: 0}
m_ExitPosition: {x: 800, y: 120, z: 0}
m_ParentStateMachinePosition: {x: 800, y: 20, z: 0}
m_DefaultState: {fileID: 1102093862037490004}

View File

@@ -1,8 +0,0 @@
fileFormatVersion: 2
guid: 23dca587da071cd41ac3a7fc070bea5c
NativeFormatImporter:
externalObjects: {}
mainObjectFileID: 9100000
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -1,268 +0,0 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!91 &9100000
AnimatorController:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_Name: UIParticle_Demo_Pop
serializedVersion: 5
m_AnimatorParameters: []
m_AnimatorLayers:
- serializedVersion: 5
m_Name: Base Layer
m_StateMachine: {fileID: 1107303963999173640}
m_Mask: {fileID: 0}
m_Motions: []
m_Behaviours: []
m_BlendingMode: 0
m_SyncedLayerIndex: -1
m_DefaultWeight: 0
m_IKPass: 0
m_SyncedLayerAffectsTiming: 0
m_Controller: {fileID: 9100000}
--- !u!74 &74513151621551130
AnimationClip:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_Name: UIParticle_Demo_Pop
serializedVersion: 6
m_Legacy: 0
m_Compressed: 0
m_UseHighQualityCurve: 1
m_RotationCurves: []
m_CompressedRotationCurves: []
m_EulerCurves: []
m_PositionCurves: []
m_ScaleCurves:
- curve:
serializedVersion: 2
m_Curve:
- serializedVersion: 3
time: 0
value: {x: 1, y: 1, z: 1}
inSlope: {x: 0, y: 0, z: 0}
outSlope: {x: 0, y: 0, z: 0}
tangentMode: 0
weightedMode: 0
inWeight: {x: 0.33333334, y: 0.33333334, z: 0.33333334}
outWeight: {x: 0.33333334, y: 0.33333334, z: 0.33333334}
- serializedVersion: 3
time: 0.06666667
value: {x: 1.5, y: 1.5, z: 1.5}
inSlope: {x: 0, y: 0, z: 0}
outSlope: {x: 0, y: 0, z: 0}
tangentMode: 0
weightedMode: 0
inWeight: {x: 0.33333334, y: 0.33333334, z: 0.33333334}
outWeight: {x: 0.33333334, y: 0.33333334, z: 0.33333334}
- serializedVersion: 3
time: 0.5
value: {x: 1, y: 1, z: 1}
inSlope: {x: 0, y: 0, z: 0}
outSlope: {x: 0, y: 0, z: 0}
tangentMode: 0
weightedMode: 0
inWeight: {x: 0.33333334, y: 0.33333334, z: 0.33333334}
outWeight: {x: 0.33333334, y: 0.33333334, z: 0.33333334}
m_PreInfinity: 2
m_PostInfinity: 2
m_RotationOrder: 4
path:
m_FloatCurves: []
m_PPtrCurves: []
m_SampleRate: 30
m_WrapMode: 0
m_Bounds:
m_Center: {x: 0, y: 0, z: 0}
m_Extent: {x: 0, y: 0, z: 0}
m_ClipBindingConstant:
genericBindings: []
pptrCurveMapping: []
m_AnimationClipSettings:
serializedVersion: 2
m_AdditiveReferencePoseClip: {fileID: 0}
m_AdditiveReferencePoseTime: 0
m_StartTime: 0
m_StopTime: 0.5
m_OrientationOffsetY: 0
m_Level: 0
m_CycleOffset: 0
m_HasAdditiveReferencePose: 0
m_LoopTime: 0
m_LoopBlend: 0
m_LoopBlendOrientation: 0
m_LoopBlendPositionY: 0
m_LoopBlendPositionXZ: 0
m_KeepOriginalOrientation: 0
m_KeepOriginalPositionY: 1
m_KeepOriginalPositionXZ: 0
m_HeightFromFeet: 0
m_Mirror: 0
m_EditorCurves:
- curve:
serializedVersion: 2
m_Curve:
- serializedVersion: 3
time: 0
value: 1
inSlope: 0
outSlope: 0
tangentMode: 136
weightedMode: 0
inWeight: 0.33333334
outWeight: 0.33333334
- serializedVersion: 3
time: 0.06666667
value: 1.5
inSlope: 0
outSlope: 0
tangentMode: 136
weightedMode: 0
inWeight: 0.33333334
outWeight: 0.33333334
- serializedVersion: 3
time: 0.5
value: 1
inSlope: 0
outSlope: 0
tangentMode: 136
weightedMode: 0
inWeight: 0.33333334
outWeight: 0.33333334
m_PreInfinity: 2
m_PostInfinity: 2
m_RotationOrder: 4
attribute: m_LocalScale.x
path:
classID: 224
script: {fileID: 0}
- curve:
serializedVersion: 2
m_Curve:
- serializedVersion: 3
time: 0
value: 1
inSlope: 0
outSlope: 0
tangentMode: 136
weightedMode: 0
inWeight: 0.33333334
outWeight: 0.33333334
- serializedVersion: 3
time: 0.06666667
value: 1.5
inSlope: 0
outSlope: 0
tangentMode: 136
weightedMode: 0
inWeight: 0.33333334
outWeight: 0.33333334
- serializedVersion: 3
time: 0.5
value: 1
inSlope: 0
outSlope: 0
tangentMode: 136
weightedMode: 0
inWeight: 0.33333334
outWeight: 0.33333334
m_PreInfinity: 2
m_PostInfinity: 2
m_RotationOrder: 4
attribute: m_LocalScale.y
path:
classID: 224
script: {fileID: 0}
- curve:
serializedVersion: 2
m_Curve:
- serializedVersion: 3
time: 0
value: 1
inSlope: 0
outSlope: 0
tangentMode: 136
weightedMode: 0
inWeight: 0.33333334
outWeight: 0.33333334
- serializedVersion: 3
time: 0.06666667
value: 1.5
inSlope: 0
outSlope: 0
tangentMode: 136
weightedMode: 0
inWeight: 0.33333334
outWeight: 0.33333334
- serializedVersion: 3
time: 0.5
value: 1
inSlope: 0
outSlope: 0
tangentMode: 136
weightedMode: 0
inWeight: 0.33333334
outWeight: 0.33333334
m_PreInfinity: 2
m_PostInfinity: 2
m_RotationOrder: 4
attribute: m_LocalScale.z
path:
classID: 224
script: {fileID: 0}
m_EulerEditorCurves: []
m_HasGenericRootTransform: 0
m_HasMotionFloatCurves: 0
m_Events: []
--- !u!1102 &1102311490129699446
AnimatorState:
serializedVersion: 5
m_ObjectHideFlags: 1
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_Name: UIParticle_Demo_Pop
m_Speed: 1
m_CycleOffset: 0
m_Transitions: []
m_StateMachineBehaviours: []
m_Position: {x: 50, y: 50, z: 0}
m_IKOnFeet: 0
m_WriteDefaultValues: 1
m_Mirror: 0
m_SpeedParameterActive: 0
m_MirrorParameterActive: 0
m_CycleOffsetParameterActive: 0
m_TimeParameterActive: 0
m_Motion: {fileID: 74513151621551130}
m_Tag:
m_SpeedParameter:
m_MirrorParameter:
m_CycleOffsetParameter:
m_TimeParameter:
--- !u!1107 &1107303963999173640
AnimatorStateMachine:
serializedVersion: 5
m_ObjectHideFlags: 1
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_Name: Base Layer
m_ChildStates:
- serializedVersion: 1
m_State: {fileID: 1102311490129699446}
m_Position: {x: 240, y: 96, z: 0}
m_ChildStateMachines: []
m_AnyStateTransitions: []
m_EntryTransitions: []
m_StateMachineTransitions: {}
m_StateMachineBehaviours: []
m_AnyStatePosition: {x: 50, y: 20, z: 0}
m_EntryPosition: {x: 50, y: 120, z: 0}
m_ExitPosition: {x: 800, y: 120, z: 0}
m_ParentStateMachinePosition: {x: 800, y: 20, z: 0}
m_DefaultState: {fileID: 1102311490129699446}

View File

@@ -1,8 +0,0 @@
fileFormatVersion: 2
guid: caa1268363f2e40dbb845db5e8e1b22a
NativeFormatImporter:
externalObjects: {}
mainObjectFileID: 9100000
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -1,215 +0,0 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!91 &9100000
AnimatorController:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_Name: UIParticle_Demo_Wave
serializedVersion: 5
m_AnimatorParameters: []
m_AnimatorLayers:
- serializedVersion: 5
m_Name: Base Layer
m_StateMachine: {fileID: 1107303963999173640}
m_Mask: {fileID: 0}
m_Motions: []
m_Behaviours: []
m_BlendingMode: 0
m_SyncedLayerIndex: -1
m_DefaultWeight: 0
m_IKPass: 0
m_SyncedLayerAffectsTiming: 0
m_Controller: {fileID: 9100000}
--- !u!74 &74084382941425094
AnimationClip:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_Name: UIParticle_Demo_Wave
serializedVersion: 6
m_Legacy: 0
m_Compressed: 0
m_UseHighQualityCurve: 1
m_RotationCurves: []
m_CompressedRotationCurves: []
m_EulerCurves: []
m_PositionCurves: []
m_ScaleCurves: []
m_FloatCurves:
- curve:
serializedVersion: 2
m_Curve:
- serializedVersion: 3
time: 0
value: 0
inSlope: 0
outSlope: 200
tangentMode: 69
weightedMode: 0
inWeight: 0.33333334
outWeight: 0.33333334
- serializedVersion: 3
time: 0.5
value: 100
inSlope: 0
outSlope: 0
tangentMode: 136
weightedMode: 0
inWeight: 0.33333334
outWeight: 0.33333334
- serializedVersion: 3
time: 1.5
value: -100
inSlope: 0
outSlope: 0
tangentMode: 136
weightedMode: 0
inWeight: 0.33333334
outWeight: 0.33333334
- serializedVersion: 3
time: 2
value: 0
inSlope: 200
outSlope: 0
tangentMode: 69
weightedMode: 0
inWeight: 0.33333334
outWeight: 0.33333334
m_PreInfinity: 2
m_PostInfinity: 2
m_RotationOrder: 4
attribute: m_AnchoredPosition.y
path:
classID: 224
script: {fileID: 0}
m_PPtrCurves: []
m_SampleRate: 30
m_WrapMode: 0
m_Bounds:
m_Center: {x: 0, y: 0, z: 0}
m_Extent: {x: 0, y: 0, z: 0}
m_ClipBindingConstant:
genericBindings: []
pptrCurveMapping: []
m_AnimationClipSettings:
serializedVersion: 2
m_AdditiveReferencePoseClip: {fileID: 0}
m_AdditiveReferencePoseTime: 0
m_StartTime: 0
m_StopTime: 2
m_OrientationOffsetY: 0
m_Level: 0
m_CycleOffset: 0
m_HasAdditiveReferencePose: 0
m_LoopTime: 1
m_LoopBlend: 0
m_LoopBlendOrientation: 0
m_LoopBlendPositionY: 0
m_LoopBlendPositionXZ: 0
m_KeepOriginalOrientation: 0
m_KeepOriginalPositionY: 1
m_KeepOriginalPositionXZ: 0
m_HeightFromFeet: 0
m_Mirror: 0
m_EditorCurves:
- curve:
serializedVersion: 2
m_Curve:
- serializedVersion: 3
time: 0
value: 0
inSlope: 0
outSlope: 200
tangentMode: 69
weightedMode: 0
inWeight: 0.33333334
outWeight: 0.33333334
- serializedVersion: 3
time: 0.5
value: 100
inSlope: 0
outSlope: 0
tangentMode: 136
weightedMode: 0
inWeight: 0.33333334
outWeight: 0.33333334
- serializedVersion: 3
time: 1.5
value: -100
inSlope: 0
outSlope: 0
tangentMode: 136
weightedMode: 0
inWeight: 0.33333334
outWeight: 0.33333334
- serializedVersion: 3
time: 2
value: 0
inSlope: 200
outSlope: 0
tangentMode: 69
weightedMode: 0
inWeight: 0.33333334
outWeight: 0.33333334
m_PreInfinity: 2
m_PostInfinity: 2
m_RotationOrder: 4
attribute: m_AnchoredPosition.y
path:
classID: 224
script: {fileID: 0}
m_EulerEditorCurves: []
m_HasGenericRootTransform: 0
m_HasMotionFloatCurves: 0
m_Events: []
--- !u!1102 &1102311490129699446
AnimatorState:
serializedVersion: 5
m_ObjectHideFlags: 1
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_Name: UIParticle_Demo_Wave
m_Speed: 1
m_CycleOffset: 0
m_Transitions: []
m_StateMachineBehaviours: []
m_Position: {x: 50, y: 50, z: 0}
m_IKOnFeet: 0
m_WriteDefaultValues: 1
m_Mirror: 0
m_SpeedParameterActive: 0
m_MirrorParameterActive: 0
m_CycleOffsetParameterActive: 0
m_TimeParameterActive: 0
m_Motion: {fileID: 74084382941425094}
m_Tag:
m_SpeedParameter:
m_MirrorParameter:
m_CycleOffsetParameter:
m_TimeParameter:
--- !u!1107 &1107303963999173640
AnimatorStateMachine:
serializedVersion: 5
m_ObjectHideFlags: 1
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_Name: Base Layer
m_ChildStates:
- serializedVersion: 1
m_State: {fileID: 1102311490129699446}
m_Position: {x: 240, y: 96, z: 0}
m_ChildStateMachines: []
m_AnyStateTransitions: []
m_EntryTransitions: []
m_StateMachineTransitions: {}
m_StateMachineBehaviours: []
m_AnyStatePosition: {x: 50, y: 20, z: 0}
m_EntryPosition: {x: 50, y: 120, z: 0}
m_ExitPosition: {x: 800, y: 120, z: 0}
m_ParentStateMachinePosition: {x: 800, y: 20, z: 0}
m_DefaultState: {fileID: 1102311490129699446}

View File

Before

Width:  |  Height:  |  Size: 12 KiB

After

Width:  |  Height:  |  Size: 12 KiB

View File

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

View File

@@ -1,8 +0,0 @@
fileFormatVersion: 2
guid: 96e9806111c7f4ad18c9467cbbe2c4fd
NativeFormatImporter:
externalObjects: {}
mainObjectFileID: 2100000
userData:
assetBundleName:
assetBundleVariant:

Binary file not shown.

Before

Width:  |  Height:  |  Size: 21 KiB

View File

@@ -1,132 +0,0 @@
fileFormatVersion: 2
guid: e834c7963556c9b4cbad7f1bee63f597
TextureImporter:
fileIDToRecycleName: {}
externalObjects: {}
serializedVersion: 9
mipmaps:
mipMapMode: 0
enableMipMap: 0
sRGBTexture: 1
linearTexture: 0
fadeOut: 0
borderMipMap: 0
mipMapsPreserveCoverage: 0
alphaTestReferenceValue: 0.5
mipMapFadeDistanceStart: 1
mipMapFadeDistanceEnd: 3
bumpmap:
convertToNormalMap: 0
externalNormalMap: 0
heightScale: 0.25
normalMapFilter: 0
isReadable: 0
streamingMipmaps: 0
streamingMipmapsPriority: 0
grayScaleToAlpha: 0
generateCubemap: 6
cubemapConvolution: 0
seamlessCubemap: 0
textureFormat: 1
maxTextureSize: 2048
textureSettings:
serializedVersion: 2
filterMode: -1
aniso: -1
mipBias: -100
wrapU: 1
wrapV: 1
wrapW: 1
nPOTScale: 0
lightmap: 0
compressionQuality: 50
spriteMode: 1
spriteExtrude: 1
spriteMeshType: 1
alignment: 0
spritePivot: {x: 0.5, y: 0.5}
spritePixelsToUnits: 100
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
spriteGenerateFallbackPhysicsShape: 1
alphaUsage: 1
alphaIsTransparency: 1
spriteTessellationDetail: -1
textureType: 0
textureShape: 1
singleChannelComponent: 0
maxTextureSizeSet: 0
compressionQualitySet: 0
textureFormatSet: 0
platformSettings:
- serializedVersion: 2
buildTarget: DefaultTexturePlatform
maxTextureSize: 64
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
androidETC2FallbackOverride: 0
- serializedVersion: 2
buildTarget: Standalone
maxTextureSize: 64
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
androidETC2FallbackOverride: 0
- serializedVersion: 2
buildTarget: iPhone
maxTextureSize: 64
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
androidETC2FallbackOverride: 0
- serializedVersion: 2
buildTarget: Android
maxTextureSize: 64
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
androidETC2FallbackOverride: 0
- serializedVersion: 2
buildTarget: WebGL
maxTextureSize: 64
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
androidETC2FallbackOverride: 0
spriteSheet:
serializedVersion: 2
sprites: []
outline: []
physicsShape: []
bones: []
spriteID: 78789b3115ea945b6ad75ef039075475
vertices: []
indices:
edges: []
weights: []
spritePackingTag:
pSDRemoveMatte: 0
pSDShowRemoveMatteOption: 0
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -1,84 +0,0 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!21 &2100000
Material:
serializedVersion: 6
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_Name: UIParticle_Demo_Dot
m_Shader: {fileID: 10770, guid: 0000000000000000f000000000000000, type: 0}
m_ShaderKeywords:
m_LightmapFlags: 4
m_EnableInstancingVariants: 0
m_DoubleSidedGI: 0
m_CustomRenderQueue: 3001
stringTagMap: {}
disabledShaderPasses: []
m_SavedProperties:
serializedVersion: 3
m_TexEnvs:
- _BumpMap:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _DetailAlbedoMap:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _DetailMask:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _DetailNormalMap:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _EmissionMap:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _MainTex:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _MetallicGlossMap:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _OcclusionMap:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _ParallaxMap:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
m_Floats:
- _BumpScale: 1
- _ColorMask: 15
- _Cutoff: 0.5
- _DetailNormalMapScale: 1
- _DstBlend: 0
- _GlossMapScale: 1
- _Glossiness: 0.5
- _GlossyReflections: 1
- _Metallic: 0
- _Mode: 0
- _OcclusionStrength: 1
- _Parallax: 0.02
- _SmoothnessTextureChannel: 0
- _SpecularHighlights: 1
- _SrcBlend: 1
- _Stencil: 0
- _StencilComp: 8
- _StencilOp: 0
- _StencilReadMask: 255
- _StencilWriteMask: 255
- _UVSec: 0
- _UseUIAlphaClip: 0
- _ZWrite: 1
m_Colors:
- _Color: {r: 1, g: 1, b: 1, a: 1}
- _EmissionColor: {r: 0, g: 0, b: 0, a: 1}

View File

@@ -1,92 +0,0 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!21 &2100000
Material:
serializedVersion: 6
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_Name: UIParticle_Demo_Flame
m_Shader: {fileID: 4800000, guid: ecfa8f5732b504ef98fba10aa18d0326, type: 3}
m_ShaderKeywords: _EMISSION
m_LightmapFlags: 1
m_EnableInstancingVariants: 0
m_DoubleSidedGI: 0
m_CustomRenderQueue: -1
stringTagMap: {}
disabledShaderPasses: []
m_SavedProperties:
serializedVersion: 3
m_TexEnvs:
- _BumpMap:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _DetailAlbedoMap:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _DetailMask:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _DetailNormalMap:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _EmissionMap:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _MainTex:
m_Texture: {fileID: 2800000, guid: 5b8fd2a34c36a4f1caae000b721312c4, type: 3}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _MetallicGlossMap:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _Normal:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _OcclusionMap:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _ParallaxMap:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
m_Floats:
- _BumpScale: 1
- _ColorMask: 15
- _Cutoff: 0.5
- _DetailNormalMapScale: 1
- _DstBlend: 0
- _GlossMapScale: 1
- _Glossiness: 0.5
- _GlossyReflections: 1
- _Glow: 1
- _InvFade: 3
- _Metallic: 0
- _Mode: 0
- _OcclusionStrength: 1
- _Parallax: 0.02
- _SmoothnessTextureChannel: 0
- _SpecularHighlights: 1
- _SrcBlend: 1
- _Stencil: 0
- _StencilComp: 8
- _StencilOp: 0
- _StencilReadMask: 255
- _StencilWriteMask: 255
- _UVSec: 0
- _UseUIAlphaClip: 0
- _ZWrite: 1
m_Colors:
- _ClipRect: {r: -32767, g: -32767, b: 32767, a: 32767}
- _Color: {r: 1, g: 1, b: 1, a: 1}
- _EmissionColor: {r: 0, g: 0, b: 0, a: 1}
- _TintColor: {r: 1, g: 1, b: 1, a: 0.5}

View File

@@ -1,8 +0,0 @@
fileFormatVersion: 2
guid: 15c6396b976394d68a63d742106293cb
timeCreated: 1471532950
licenseType: Store
NativeFormatImporter:
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -1,68 +0,0 @@
fileFormatVersion: 2
guid: 5b8fd2a34c36a4f1caae000b721312c4
timeCreated: 1474988750
licenseType: Store
TextureImporter:
fileIDToRecycleName: {}
serializedVersion: 4
mipmaps:
mipMapMode: 0
enableMipMap: 1
sRGBTexture: 1
linearTexture: 0
fadeOut: 0
borderMipMap: 0
mipMapFadeDistanceStart: 1
mipMapFadeDistanceEnd: 3
bumpmap:
convertToNormalMap: 0
externalNormalMap: 0
heightScale: 0.25
normalMapFilter: 0
isReadable: 0
grayScaleToAlpha: 0
generateCubemap: 6
cubemapConvolution: 0
seamlessCubemap: 0
textureFormat: 1
maxTextureSize: 2048
textureSettings:
filterMode: -1
aniso: -1
mipBias: -1
wrapMode: -1
nPOTScale: 1
lightmap: 0
compressionQuality: 50
spriteMode: 0
spriteExtrude: 1
spriteMeshType: 1
alignment: 0
spritePivot: {x: 0.5, y: 0.5}
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
spritePixelsToUnits: 100
alphaUsage: 1
alphaIsTransparency: 0
spriteTessellationDetail: -1
textureType: 0
textureShape: 1
maxTextureSizeSet: 0
compressionQualitySet: 0
textureFormatSet: 0
platformSettings:
- buildTarget: DefaultTexturePlatform
maxTextureSize: 2048
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
spriteSheet:
serializedVersion: 2
sprites: []
outline: []
spritePackingTag:
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -1,85 +0,0 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!21 &2100000
Material:
serializedVersion: 6
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_Name: UIParticle_Demo_UIAdditive
m_Shader: {fileID: 4800000, guid: ecfa8f5732b504ef98fba10aa18d0326, type: 3}
m_ShaderKeywords:
m_LightmapFlags: 4
m_EnableInstancingVariants: 0
m_DoubleSidedGI: 0
m_CustomRenderQueue: -1
stringTagMap: {}
disabledShaderPasses: []
m_SavedProperties:
serializedVersion: 3
m_TexEnvs:
- _BumpMap:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _DetailAlbedoMap:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _DetailMask:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _DetailNormalMap:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _EmissionMap:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _MainTex:
m_Texture: {fileID: 2800000, guid: 975570a90d56c477582e12d440dc9931, type: 3}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _MetallicGlossMap:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _OcclusionMap:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _ParallaxMap:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
m_Floats:
- _BumpScale: 1
- _ColorMask: 15
- _Cutoff: 0.5
- _DetailNormalMapScale: 1
- _DstBlend: 0
- _GlossMapScale: 1
- _Glossiness: 0.5
- _GlossyReflections: 1
- _Metallic: 0
- _Mode: 0
- _OcclusionStrength: 1
- _Parallax: 0.02
- _SmoothnessTextureChannel: 0
- _SpecularHighlights: 1
- _SrcBlend: 1
- _Stencil: 0
- _StencilComp: 8
- _StencilOp: 0
- _StencilReadMask: 255
- _StencilWriteMask: 255
- _UVSec: 0
- _UseUIAlphaClip: 0
- _ZWrite: 1
m_Colors:
- _ClipRect: {r: -32767, g: -32767, b: 32767, a: 32767}
- _Color: {r: 1, g: 1, b: 1, a: 1}
- _EmissionColor: {r: 0, g: 0, b: 0, a: 1}

View File

@@ -1,95 +0,0 @@
fileFormatVersion: 2
guid: cc4bae8d676c44e0faffd572cc7599a0
ModelImporter:
serializedVersion: 23
fileIDToRecycleName:
100000: o_ring_00
100002: //RootNode
400000: o_ring_00
400002: //RootNode
2100000: lambert2
2300000: o_ring_00
3300000: o_ring_00
4300000: o_ring_00
externalObjects: {}
materials:
importMaterials: 1
materialName: 0
materialSearch: 1
materialLocation: 1
animations:
legacyGenerateAnimations: 4
bakeSimulation: 0
resampleCurves: 1
optimizeGameObjects: 0
motionNodeName:
rigImportErrors:
rigImportWarnings:
animationImportErrors:
animationImportWarnings:
animationRetargetingWarnings:
animationDoRetargetingWarnings: 0
importAnimatedCustomProperties: 0
importConstraints: 0
animationCompression: 1
animationRotationError: 0.5
animationPositionError: 0.5
animationScaleError: 0.5
animationWrapMode: 0
extraExposedTransformPaths: []
extraUserProperties: []
clipAnimations: []
isReadable: 1
meshes:
lODScreenPercentages: []
globalScale: 1
meshCompression: 0
addColliders: 0
importVisibility: 1
importBlendShapes: 1
importCameras: 1
importLights: 1
swapUVChannels: 0
generateSecondaryUV: 0
useFileUnits: 1
optimizeMeshForGPU: 1
keepQuads: 0
weldVertices: 1
preserveHierarchy: 0
indexFormat: 0
secondaryUVAngleDistortion: 8
secondaryUVAreaDistortion: 15.000001
secondaryUVHardAngle: 88
secondaryUVPackMargin: 4
useFileScale: 1
previousCalculatedGlobalScale: 1
hasPreviousCalculatedGlobalScale: 0
tangentSpace:
normalSmoothAngle: 60
normalImportMode: 0
tangentImportMode: 3
normalCalculationMode: 4
importAnimation: 1
copyAvatar: 0
humanDescription:
serializedVersion: 2
human: []
skeleton: []
armTwist: 0.5
foreArmTwist: 0.5
upperLegTwist: 0.5
legTwist: 0.5
armStretch: 0.05
legStretch: 0.05
feetSpacing: 0
rootMotionBoneName:
hasTranslationDoF: 0
hasExtraRoot: 0
skeletonHasParents: 1
lastHumanDescriptionAvatarSource: {instanceID: 0}
animationType: 0
humanoidOversampling: 1
additionalBone: 0
userData:
assetBundleName:
assetBundleVariant:

File diff suppressed because it is too large Load Diff

View File

@@ -1,8 +0,0 @@
fileFormatVersion: 2
guid: fd2938b6280d84e328d330be2aedd18f
NativeFormatImporter:
externalObjects: {}
mainObjectFileID: 100100000
userData:
assetBundleName:
assetBundleVariant:

File diff suppressed because it is too large Load Diff

View File

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

View File

@@ -1,31 +0,0 @@
using UnityEngine;
using UnityEngine.Serialization;
namespace Coffee.UIExtensions.Demo
{
public class CopyItemOnStart : MonoBehaviour
{
[FormerlySerializedAs("origin")]
[SerializeField]
private GameObject m_Origin;
[FormerlySerializedAs("count")]
[SerializeField]
private int m_Count;
private void Start()
{
if (!m_Origin) return;
m_Origin.SetActive(false);
var parent = m_Origin.transform.parent;
for (var i = 0; i < m_Count; i++)
{
var go = Instantiate(m_Origin, parent, false);
go.name = $"{m_Origin.name} {i + 1}";
go.hideFlags = HideFlags.DontSave;
go.SetActive(true);
}
}
}
}

View File

@@ -1,93 +0,0 @@
using System;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.Serialization;
public class UIElementDragger : MonoBehaviour, IBeginDragHandler, IDragHandler, IEndDragHandler
{
[SerializeField]
private Target m_Target;
[SerializeField]
private Transform m_CustomTarget;
[FormerlySerializedAs("ex2")]
[SerializeField]
private bool m_UseCanvasScale;
private Canvas _canvas;
private RectTransform _rectTransform;
private void OnEnable()
{
_rectTransform = GetComponent<RectTransform>();
_canvas = GetComponentInParent<Canvas>();
}
public void OnBeginDrag(PointerEventData eventData)
{
}
public void OnDrag(PointerEventData eventData)
{
var delta = (Vector3)GetLocalDelta(eventData.delta);
switch (m_Target)
{
case Target.Self:
_rectTransform.localPosition += delta;
break;
case Target.Parent:
_rectTransform.parent.localPosition += delta;
break;
case Target.Custom:
_rectTransform.localPosition += delta;
if (m_CustomTarget)
{
if (m_UseCanvasScale)
{
delta.Scale(_canvas.rootCanvas.transform.localScale);
}
m_CustomTarget.localPosition += delta;
}
break;
}
}
public void OnEndDrag(PointerEventData eventData)
{
}
private Vector2 GetLocalDelta(Vector2 evDelta)
{
switch (_canvas.renderMode)
{
case RenderMode.ScreenSpaceOverlay:
{
var zero = transform.InverseTransformPoint(Vector2.zero);
var delta = transform.InverseTransformPoint(evDelta);
return delta - zero;
}
case RenderMode.ScreenSpaceCamera:
case RenderMode.WorldSpace:
{
RectTransformUtility.ScreenPointToLocalPointInRectangle(_rectTransform, Vector2.zero,
_canvas.worldCamera, out var zero);
RectTransformUtility.ScreenPointToLocalPointInRectangle(_rectTransform, evDelta,
_canvas.worldCamera, out var delta);
return delta - zero;
}
default:
throw new NotSupportedException();
}
}
private enum Target
{
Self,
Parent,
Custom
}
}

View File

@@ -1,177 +0,0 @@
using UnityEngine;
using UnityEngine.Serialization;
using UnityEngine.UI;
namespace Coffee.UIExtensions.Demo
{
public class UIParticle_Demo : MonoBehaviour
{
[FormerlySerializedAs("root")]
[SerializeField]
private Canvas m_RootCanvas;
private int _height;
private int _score;
private int _width;
private void Start()
{
_width = Screen.width;
_height = Screen.height;
}
public void ResizeScreen()
{
switch (Application.platform)
{
case RuntimePlatform.OSXPlayer:
case RuntimePlatform.WindowsPlayer:
case RuntimePlatform.LinuxPlayer:
if (Screen.width == _width && Screen.height == _height)
{
Screen.SetResolution(_height, _width, Screen.fullScreen);
}
else if (Screen.width == _height && Screen.height == _width)
{
Screen.SetResolution(Mathf.Min(_width, _height), Mathf.Min(_width, _height), Screen.fullScreen);
}
else
{
Screen.SetResolution(_width, _height, Screen.fullScreen);
}
break;
}
}
public void FullScreen()
{
Screen.fullScreen = !Screen.fullScreen;
}
public void EnableAnimations(bool flag)
{
foreach (var animator in FindObjectsOfType<Animator>())
{
animator.enabled = flag;
}
}
public void UIParticle_MeshSharing(bool flag)
{
foreach (var uip in m_RootCanvas.GetComponentsInChildren<UIParticle>(true))
{
uip.meshSharing = flag
? UIParticle.MeshSharing.Auto
: UIParticle.MeshSharing.None;
}
}
public void UIParticle_RandomGroup(bool flag)
{
foreach (var uip in m_RootCanvas.GetComponentsInChildren<UIParticle>(true))
{
uip.groupMaxId = flag
? 4
: 0;
}
}
public void UIParticle_Scale(float scale)
{
foreach (var uip in FindObjectsOfType<UIParticle>())
{
uip.scale = scale;
}
}
public void ParticleSystem_WorldSpaseSimulation(bool flag)
{
foreach (var p in FindObjectsOfType<ParticleSystem>())
{
var main = p.main;
main.simulationSpace = flag
? ParticleSystemSimulationSpace.World
: ParticleSystemSimulationSpace.Local;
}
}
public void ParticleSystem_WorldSpaseSimulation(ParticleSystem ps)
{
foreach (var p in ps.GetComponentsInChildren<ParticleSystem>())
{
var main = p.main;
main.simulationSpace = ParticleSystemSimulationSpace.World;
p.Clear();
}
}
public void ParticleSystem_LocalSpaseSimulation(ParticleSystem ps)
{
foreach (var p in ps.GetComponentsInChildren<ParticleSystem>())
{
var main = p.main;
main.simulationSpace = ParticleSystemSimulationSpace.Local;
p.Clear();
}
}
public void ParticleSystem_Emit(ParticleSystem ps)
{
ps.Emit(5);
}
public void ParticleSystem_SetScale(float scale)
{
foreach (var ps in FindObjectsOfType<ParticleSystem>())
{
ps.transform.localScale = new Vector3(scale, scale, scale);
}
}
public void UIParticleAttractor_Linear(UIParticleAttractor attractor)
{
attractor.movement = UIParticleAttractor.Movement.Linear;
}
public void UIParticleAttractor_Smooth(UIParticleAttractor attractor)
{
attractor.movement = UIParticleAttractor.Movement.Smooth;
}
public void UIParticleAttractor_Sphere(UIParticleAttractor attractor)
{
attractor.movement = UIParticleAttractor.Movement.Sphere;
}
public void UIParticleAttractor_OnAttract(Text scoreText)
{
_score++;
scoreText.text = _score.ToString();
scoreText.GetComponent<Animator>().Play(0);
}
public void Canvas_WorldSpace(bool flag)
{
if (!flag) return;
m_RootCanvas.renderMode = RenderMode.ScreenSpaceCamera;
m_RootCanvas.renderMode = RenderMode.WorldSpace;
m_RootCanvas.transform.rotation = Quaternion.Euler(new Vector3(0, 10, 0));
}
public void Canvas_CameraSpace(bool flag)
{
if (!flag) return;
m_RootCanvas.renderMode = RenderMode.ScreenSpaceCamera;
}
public void Canvas_Overlay(bool flag)
{
if (!flag) return;
m_RootCanvas.renderMode = RenderMode.ScreenSpaceOverlay;
}
}
}

View File

@@ -1,40 +0,0 @@
using UnityEngine;
using UnityEngine.Serialization;
namespace Coffee.UIExtensions.Demo
{
public class UIParticle_Demo_UIParticleController : MonoBehaviour
{
[FormerlySerializedAs("root")]
[SerializeField]
private Transform m_RootTransform;
public void UIParticle_MeshSharing(bool flag)
{
foreach (var uip in m_RootTransform.GetComponentsInChildren<UIParticle>(true))
{
uip.meshSharing = flag
? UIParticle.MeshSharing.Auto
: UIParticle.MeshSharing.None;
}
}
public void UIParticle_RandomGroup(bool flag)
{
foreach (var uip in m_RootTransform.GetComponentsInChildren<UIParticle>(true))
{
uip.groupMaxId = flag
? 4
: 0;
}
}
public void UIParticle_Scale(float scale)
{
foreach (var uip in m_RootTransform.GetComponentsInChildren<UIParticle>(true))
{
uip.scale = scale;
}
}
}
}

View File

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

View File

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

View File

@@ -1,48 +0,0 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!687078895 &4343727234628468602
SpriteAtlas:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_Name: UIParticle_Demo
m_EditorData:
serializedVersion: 2
textureSettings:
serializedVersion: 2
anisoLevel: 1
compressionQuality: 50
maxTextureSize: 2048
textureCompression: 0
filterMode: 1
generateMipMaps: 0
readable: 0
crunchedCompression: 0
sRGB: 1
platformSettings: []
packingSettings:
serializedVersion: 2
padding: 4
blockOffset: 1
allowAlphaSplitting: 0
enableRotation: 1
enableTightPacking: 1
variantMultiplier: 1
packables:
- {fileID: 102900000, guid: 0251dca70242c4171a1dde2b4eef3367, type: 3}
totalSpriteSurfaceArea: 44845
bindAsDefault: 1
m_MasterAtlas: {fileID: 0}
m_PackedSprites:
- {fileID: 21300000, guid: 642c2160c66664114a5ec8f014456c3e, type: 3}
- {fileID: 21300000, guid: 8194ff59e335b4069b502b66d02131fa, type: 3}
- {fileID: 21300000, guid: 925f66fdcc9764b579413b7408c718f2, type: 3}
- {fileID: 21300000, guid: 077b84be6d052c34d933c79ef500be13, type: 3}
m_PackedSpriteNamesToIndex:
- UIParticle_Demo_Move
- UIParticle_Demo_Star
- UIParticle_Demo_Unity-chan
- UIParticle_Demo_Light_Frame
m_Tag: UIParticle_Demo
m_IsVariant: 0

View File

@@ -1,8 +0,0 @@
fileFormatVersion: 2
guid: 6f4c242a0c8414734aaa4019486b8695
NativeFormatImporter:
externalObjects: {}
mainObjectFileID: 4343727234628468602
userData:
assetBundleName:
assetBundleVariant:

Binary file not shown.

Before

Width:  |  Height:  |  Size: 754 B

View File

@@ -1,88 +0,0 @@
fileFormatVersion: 2
guid: 642c2160c66664114a5ec8f014456c3e
TextureImporter:
fileIDToRecycleName: {}
externalObjects: {}
serializedVersion: 9
mipmaps:
mipMapMode: 0
enableMipMap: 0
sRGBTexture: 1
linearTexture: 0
fadeOut: 0
borderMipMap: 0
mipMapsPreserveCoverage: 0
alphaTestReferenceValue: 0.5
mipMapFadeDistanceStart: 1
mipMapFadeDistanceEnd: 3
bumpmap:
convertToNormalMap: 0
externalNormalMap: 0
heightScale: 0.25
normalMapFilter: 0
isReadable: 0
streamingMipmaps: 0
streamingMipmapsPriority: 0
grayScaleToAlpha: 0
generateCubemap: 6
cubemapConvolution: 0
seamlessCubemap: 0
textureFormat: 1
maxTextureSize: 2048
textureSettings:
serializedVersion: 2
filterMode: -1
aniso: -1
mipBias: -100
wrapU: 1
wrapV: 1
wrapW: -1
nPOTScale: 0
lightmap: 0
compressionQuality: 50
spriteMode: 1
spriteExtrude: 1
spriteMeshType: 1
alignment: 0
spritePivot: {x: 0.5, y: 0.5}
spritePixelsToUnits: 100
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
spriteGenerateFallbackPhysicsShape: 1
alphaUsage: 1
alphaIsTransparency: 1
spriteTessellationDetail: -1
textureType: 8
textureShape: 1
singleChannelComponent: 0
maxTextureSizeSet: 0
compressionQualitySet: 0
textureFormatSet: 0
platformSettings:
- serializedVersion: 2
buildTarget: DefaultTexturePlatform
maxTextureSize: 32
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
androidETC2FallbackOverride: 0
spriteSheet:
serializedVersion: 2
sprites: []
outline: []
physicsShape: []
bones: []
spriteID: 193ecdf6ca56940a2aa3da9c9e9faf6f
vertices: []
indices:
edges: []
weights: []
spritePackingTag:
pSDRemoveMatte: 0
pSDShowRemoveMatteOption: 0
userData:
assetBundleName:
assetBundleVariant:

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.6 KiB

View File

@@ -1,88 +0,0 @@
fileFormatVersion: 2
guid: 8194ff59e335b4069b502b66d02131fa
TextureImporter:
fileIDToRecycleName: {}
externalObjects: {}
serializedVersion: 9
mipmaps:
mipMapMode: 0
enableMipMap: 0
sRGBTexture: 1
linearTexture: 0
fadeOut: 0
borderMipMap: 0
mipMapsPreserveCoverage: 0
alphaTestReferenceValue: 0.5
mipMapFadeDistanceStart: 1
mipMapFadeDistanceEnd: 3
bumpmap:
convertToNormalMap: 0
externalNormalMap: 0
heightScale: 0.25
normalMapFilter: 0
isReadable: 0
streamingMipmaps: 0
streamingMipmapsPriority: 0
grayScaleToAlpha: 0
generateCubemap: 6
cubemapConvolution: 0
seamlessCubemap: 0
textureFormat: 7
maxTextureSize: 1024
textureSettings:
serializedVersion: 2
filterMode: -1
aniso: 0
mipBias: -100
wrapU: 1
wrapV: 1
wrapW: 1
nPOTScale: 0
lightmap: 0
compressionQuality: 50
spriteMode: 1
spriteExtrude: 1
spriteMeshType: 1
alignment: 0
spritePivot: {x: 0.5, y: 0.5}
spritePixelsToUnits: 100
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
spriteGenerateFallbackPhysicsShape: 1
alphaUsage: 0
alphaIsTransparency: 1
spriteTessellationDetail: -1
textureType: 8
textureShape: 1
singleChannelComponent: 0
maxTextureSizeSet: 0
compressionQualitySet: 0
textureFormatSet: 0
platformSettings:
- serializedVersion: 2
buildTarget: DefaultTexturePlatform
maxTextureSize: 64
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 0
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
androidETC2FallbackOverride: 0
spriteSheet:
serializedVersion: 2
sprites: []
outline: []
physicsShape: []
bones: []
spriteID: 4bb482a97bbcc410db8aca13bc4ced8d
vertices: []
indices:
edges: []
weights: []
spritePackingTag:
pSDRemoveMatte: 0
pSDShowRemoveMatteOption: 0
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -5,8 +5,7 @@ Material:
serializedVersion: 6
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_PrefabInternal: {fileID: 0}
m_Name: UIAdditive
m_Shader: {fileID: 4800000, guid: ecfa8f5732b504ef98fba10aa18d0326, type: 3}
m_ShaderKeywords:
@@ -40,7 +39,7 @@ Material:
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _MainTex:
m_Texture: {fileID: 10300, guid: 0000000000000000f000000000000000, type: 0}
m_Texture: {fileID: 2800000, guid: 975570a90d56c477582e12d440dc9931, type: 3}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _MetallicGlossMap:
@@ -80,6 +79,6 @@ Material:
- _UseUIAlphaClip: 0
- _ZWrite: 1
m_Colors:
- _ClipRect: {r: -32767, g: -32767, b: 32767, a: 32767}
- _Color: {r: 1, g: 1, b: 1, a: 1}
- _EmissionColor: {r: 0, g: 0, b: 0, a: 1}
m_BuildTextureStacks: []

View File

@@ -0,0 +1,335 @@
/// Credit glennpow, Zarlang
/// Sourced from - http://forum.unity3d.com/threads/free-script-particle-systems-in-ui-screen-space-overlay.406862/
/// Updated by Zarlang with a more robust implementation, including TextureSheet annimation support
using UnityEngine;
using UnityEngine.UI;
namespace Coffee.UIExtensions.Demos
{
#if UNITY_5_3_OR_NEWER
[ExecuteAlways]
[RequireComponent(typeof(CanvasRenderer), typeof(ParticleSystem))]
public class UIParticleSystem_Demo : MaskableGraphic
{
[Tooltip("Having this enabled run the system in LateUpdate rather than in Update making it faster but less precise (more clunky)")]
public bool fixedTime = true;
private Transform _transform;
private ParticleSystem pSystem;
private ParticleSystem.Particle[] particles;
private UIVertex[] _quad = new UIVertex[4];
private Vector4 imageUV = Vector4.zero;
private ParticleSystem.TextureSheetAnimationModule textureSheetAnimation;
private int textureSheetAnimationFrames;
private Vector2 textureSheetAnimationFrameSize;
private ParticleSystemRenderer pRenderer;
private Material currentMaterial;
private Texture currentTexture;
#if UNITY_5_5_OR_NEWER
private ParticleSystem.MainModule mainModule;
#endif
public override Texture mainTexture
{
get
{
return currentTexture;
}
}
protected bool Initialize()
{
// initialize members
if (_transform == null)
{
_transform = transform;
}
if (pSystem == null)
{
pSystem = GetComponent<ParticleSystem>();
if (pSystem == null)
{
return false;
}
#if UNITY_5_5_OR_NEWER
mainModule = pSystem.main;
if (pSystem.main.maxParticles > 14000)
{
mainModule.maxParticles = 14000;
}
#else
if (pSystem.maxParticles > 14000)
pSystem.maxParticles = 14000;
#endif
pRenderer = pSystem.GetComponent<ParticleSystemRenderer>();
if (pRenderer != null)
pRenderer.enabled = false;
//Shader foundShader = Shader.Find("UI Extensions/Particles/Additive");
//Material pMaterial = new Material(foundShader);
//if (material == null)
//material = pMaterial;
currentMaterial = material;
if (currentMaterial && currentMaterial.HasProperty("_MainTex"))
{
currentTexture = currentMaterial.mainTexture;
if (currentTexture == null)
currentTexture = Texture2D.whiteTexture;
}
material = currentMaterial;
// automatically set scaling
#if UNITY_5_5_OR_NEWER
mainModule.scalingMode = ParticleSystemScalingMode.Hierarchy;
#else
pSystem.scalingMode = ParticleSystemScalingMode.Hierarchy;
#endif
particles = null;
}
#if UNITY_5_5_OR_NEWER
if (particles == null)
particles = new ParticleSystem.Particle[pSystem.main.maxParticles];
#else
if (particles == null)
particles = new ParticleSystem.Particle[pSystem.maxParticles];
#endif
imageUV = new Vector4(0, 0, 1, 1);
// prepare texture sheet animation
textureSheetAnimation = pSystem.textureSheetAnimation;
textureSheetAnimationFrames = 0;
textureSheetAnimationFrameSize = Vector2.zero;
if (textureSheetAnimation.enabled)
{
textureSheetAnimationFrames = textureSheetAnimation.numTilesX * textureSheetAnimation.numTilesY;
textureSheetAnimationFrameSize = new Vector2(1f / textureSheetAnimation.numTilesX, 1f / textureSheetAnimation.numTilesY);
}
return true;
}
protected override void Awake()
{
base.Awake();
if (!Initialize())
enabled = false;
}
protected override void OnPopulateMesh(VertexHelper vh)
{
#if UNITY_EDITOR
if (!Application.isPlaying)
{
if (!Initialize())
{
return;
}
}
#endif
// prepare vertices
vh.Clear();
if (!gameObject.activeInHierarchy)
{
return;
}
Vector2 temp = Vector2.zero;
Vector2 corner1 = Vector2.zero;
Vector2 corner2 = Vector2.zero;
// iterate through current particles
int count = pSystem.GetParticles(particles);
for (int i = 0; i < count; ++i)
{
ParticleSystem.Particle particle = particles[i];
// get particle properties
#if UNITY_5_5_OR_NEWER
Vector2 position = (mainModule.simulationSpace == ParticleSystemSimulationSpace.Local ? particle.position : _transform.InverseTransformPoint(particle.position));
#else
Vector2 position = (pSystem.simulationSpace == ParticleSystemSimulationSpace.Local ? particle.position : _transform.InverseTransformPoint(particle.position));
#endif
float rotation = -particle.rotation * Mathf.Deg2Rad;
float rotation90 = rotation + Mathf.PI / 2;
Color32 color = particle.GetCurrentColor(pSystem);
float size = particle.GetCurrentSize(pSystem) * 0.5f;
// apply scale
#if UNITY_5_5_OR_NEWER
if (mainModule.scalingMode == ParticleSystemScalingMode.Shape)
position /= canvas.scaleFactor;
#else
if (pSystem.scalingMode == ParticleSystemScalingMode.Shape)
position /= canvas.scaleFactor;
#endif
// apply texture sheet animation
Vector4 particleUV = imageUV;
if (textureSheetAnimation.enabled)
{
#if UNITY_5_5_OR_NEWER
float frameProgress = 1 - (particle.remainingLifetime / particle.startLifetime);
if (textureSheetAnimation.frameOverTime.curveMin != null)
{
frameProgress = textureSheetAnimation.frameOverTime.curveMin.Evaluate(1 - (particle.remainingLifetime / particle.startLifetime));
}
else if (textureSheetAnimation.frameOverTime.curve != null)
{
frameProgress = textureSheetAnimation.frameOverTime.curve.Evaluate(1 - (particle.remainingLifetime / particle.startLifetime));
}
else if (textureSheetAnimation.frameOverTime.constant > 0)
{
frameProgress = textureSheetAnimation.frameOverTime.constant - (particle.remainingLifetime / particle.startLifetime);
}
#else
float frameProgress = 1 - (particle.lifetime / particle.startLifetime);
#endif
frameProgress = Mathf.Repeat(frameProgress * textureSheetAnimation.cycleCount, 1);
int frame = 0;
switch (textureSheetAnimation.animation)
{
case ParticleSystemAnimationType.WholeSheet:
frame = Mathf.FloorToInt(frameProgress * textureSheetAnimationFrames);
break;
case ParticleSystemAnimationType.SingleRow:
frame = Mathf.FloorToInt(frameProgress * textureSheetAnimation.numTilesX);
int row = textureSheetAnimation.rowIndex;
// if (textureSheetAnimation.useRandomRow) { // FIXME - is this handled internally by rowIndex?
// row = Random.Range(0, textureSheetAnimation.numTilesY, using: particle.randomSeed);
// }
frame += row * textureSheetAnimation.numTilesX;
break;
}
frame %= textureSheetAnimationFrames;
particleUV.x = (frame % textureSheetAnimation.numTilesX) * textureSheetAnimationFrameSize.x;
particleUV.y = Mathf.FloorToInt(frame / textureSheetAnimation.numTilesX) * textureSheetAnimationFrameSize.y;
particleUV.z = particleUV.x + textureSheetAnimationFrameSize.x;
particleUV.w = particleUV.y + textureSheetAnimationFrameSize.y;
}
temp.x = particleUV.x;
temp.y = particleUV.y;
_quad[0] = UIVertex.simpleVert;
_quad[0].color = color;
_quad[0].uv0 = temp;
temp.x = particleUV.x;
temp.y = particleUV.w;
_quad[1] = UIVertex.simpleVert;
_quad[1].color = color;
_quad[1].uv0 = temp;
temp.x = particleUV.z;
temp.y = particleUV.w;
_quad[2] = UIVertex.simpleVert;
_quad[2].color = color;
_quad[2].uv0 = temp;
temp.x = particleUV.z;
temp.y = particleUV.y;
_quad[3] = UIVertex.simpleVert;
_quad[3].color = color;
_quad[3].uv0 = temp;
if (rotation == 0)
{
// no rotation
corner1.x = position.x - size;
corner1.y = position.y - size;
corner2.x = position.x + size;
corner2.y = position.y + size;
temp.x = corner1.x;
temp.y = corner1.y;
_quad[0].position = temp;
temp.x = corner1.x;
temp.y = corner2.y;
_quad[1].position = temp;
temp.x = corner2.x;
temp.y = corner2.y;
_quad[2].position = temp;
temp.x = corner2.x;
temp.y = corner1.y;
_quad[3].position = temp;
}
else
{
// apply rotation
Vector2 right = new Vector2(Mathf.Cos(rotation), Mathf.Sin(rotation)) * size;
Vector2 up = new Vector2(Mathf.Cos(rotation90), Mathf.Sin(rotation90)) * size;
_quad[0].position = position - right - up;
_quad[1].position = position - right + up;
_quad[2].position = position + right + up;
_quad[3].position = position + right - up;
}
vh.AddUIVertexQuad(_quad);
}
}
void Update()
{
if (!fixedTime && Application.isPlaying)
{
pSystem.Simulate(Time.unscaledDeltaTime, false, false, true);
SetAllDirty();
if ((currentMaterial != null && currentTexture != currentMaterial.mainTexture) ||
(material != null && currentMaterial != null && material.shader != currentMaterial.shader))
{
pSystem = null;
Initialize();
}
}
}
void LateUpdate()
{
if (!Application.isPlaying)
{
SetAllDirty();
}
else
{
if (fixedTime)
{
pSystem.Simulate(Time.unscaledDeltaTime, false, false, true);
SetAllDirty();
if ((currentMaterial != null && currentTexture != currentMaterial.mainTexture) ||
(material != null && currentMaterial != null && material.shader != currentMaterial.shader))
{
pSystem = null;
Initialize();
}
}
}
if (material == currentMaterial)
return;
pSystem = null;
Initialize();
}
}
#endif
}

View File

@@ -1,5 +1,5 @@
fileFormatVersion: 2
guid: 00e55ae1441ff4583859c55384964d86
guid: f5f85388e938d9e4599afc6d9441ed57
MonoImporter:
externalObjects: {}
serializedVersion: 2

View File

@@ -0,0 +1,10 @@
{
"name": "Coffee.UIParticle.Demo",
"references": [
"Coffee.UIParticle"
],
"optionalUnityReferences": [],
"includePlatforms": [],
"excludePlatforms": [],
"allowUnsafeCode": false
}

View File

@@ -0,0 +1,111 @@
using UnityEngine;
using UnityEngine.SceneManagement;
using UnityEngine.UI;
using System.Collections.Generic;
namespace Coffee.UIExtensions.Demo
{
public class UIParticle_Demo : MonoBehaviour
{
[SerializeField] ParticleSystem [] m_ParticleSystems = new ParticleSystem [0];
[SerializeField] List<Transform> m_ScalingByTransforms = new List<Transform> ();
[SerializeField] List<UIParticle> m_ScalingByUIParticles = new List<UIParticle> ();
public void SetTimeScale (float scale)
{
Time.timeScale = scale;
}
public void EnableTrailRibbon (bool ribbonMode)
{
foreach (var p in m_ParticleSystems)
{
var trails = p.trails;
trails.mode = ribbonMode ? ParticleSystemTrailMode.Ribbon : ParticleSystemTrailMode.PerParticle;
}
}
public void EnableSprite (bool enabled)
{
foreach (var p in m_ParticleSystems)
{
var tex = p.textureSheetAnimation;
tex.enabled = enabled;
}
}
public void EnableMask (bool enabled)
{
foreach (var m in FindObjectsOfType<Mask> ())
{
m.enabled = enabled;
}
}
public void EnableMask2D (bool enabled)
{
foreach (var m in FindObjectsOfType<RectMask2D> ())
{
m.enabled = enabled;
}
}
public void SetScale (float scale)
{
m_ScalingByTransforms.ForEach (x => x.localScale = Vector3.one * (10 * scale));
m_ScalingByUIParticles.ForEach (x => x.scale = scale);
}
public void SetUIParticleScale (float scale)
{
foreach (var uip in FindObjectsOfType<UIParticle> ())
{
uip.scale = scale;
}
}
public void LoadScene (string name)
{
SceneManager.LoadScene (name);
}
public void PlayAllParticleEffect ()
{
foreach (var animator in FindObjectsOfType<Animator> ())
{
animator.Play ("Play");
}
foreach (var particle in FindObjectsOfType<ParticleSystem> ())
{
particle.Play ();
}
}
public void SetWorldSpase (bool flag)
{
if (flag)
{
GetComponent<Canvas> ().renderMode = RenderMode.ScreenSpaceCamera;
GetComponent<Canvas> ().renderMode = RenderMode.WorldSpace;
transform.rotation = Quaternion.Euler (new Vector3 (0, 6, 0));
}
}
public void SetScreenSpase (bool flag)
{
if (flag)
{
GetComponent<Canvas> ().renderMode = RenderMode.ScreenSpaceCamera;
}
}
public void SetOverlay (bool flag)
{
if (flag)
{
GetComponent<Canvas> ().renderMode = RenderMode.ScreenSpaceOverlay;
}
}
}
}

View File

@@ -0,0 +1,33 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!84 &8400000
RenderTexture:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInternal: {fileID: 0}
m_Name: UIParticle_Demo
m_ImageContentsHash:
serializedVersion: 2
Hash: 00000000000000000000000000000000
m_ForcedFallbackFormat: 4
m_DownscaleFallback: 0
m_Width: 256
m_Height: 256
m_AntiAliasing: 1
m_DepthFormat: 0
m_ColorFormat: 0
m_MipMap: 0
m_GenerateMips: 1
m_SRGB: 0
m_UseDynamicScale: 0
m_BindMS: 0
m_TextureSettings:
serializedVersion: 2
m_FilterMode: 1
m_Aniso: 0
m_MipBias: 0
m_WrapU: 1
m_WrapV: 1
m_WrapW: 1
m_Dimension: 2
m_VolumeDepth: 1

View File

@@ -1,8 +1,8 @@
fileFormatVersion: 2
guid: 8e7d928ccc1b7404d80e0d0205434aeb
guid: ab4cc8f5f51c14175af41c4daa68cbf5
NativeFormatImporter:
externalObjects: {}
mainObjectFileID: 9100000
mainObjectFileID: 8400000
userData:
assetBundleName:
assetBundleVariant:

File diff suppressed because it is too large Load Diff

View File

@@ -1,5 +1,5 @@
fileFormatVersion: 2
guid: 1da1f7e678e2d4e449f6d46d2d4c4116
guid: 5d682dd3e44264ff69bd02590123ea73
PrefabImporter:
externalObjects: {}
userData:

View File

Before

Width:  |  Height:  |  Size: 585 KiB

After

Width:  |  Height:  |  Size: 585 KiB

View File

@@ -5,9 +5,8 @@ Material:
serializedVersion: 6
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_Name: UIParticle_Demo_Animatable
m_PrefabInternal: {fileID: 0}
m_Name: UIParticle_Demo_Spread
m_Shader: {fileID: 4800000, guid: ecfa8f5732b504ef98fba10aa18d0326, type: 3}
m_ShaderKeywords:
m_LightmapFlags: 4
@@ -40,7 +39,7 @@ Material:
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _MainTex:
m_Texture: {fileID: 2800000, guid: e834c7963556c9b4cbad7f1bee63f597, type: 3}
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _MetallicGlossMap:
@@ -64,6 +63,7 @@ Material:
- _GlossMapScale: 1
- _Glossiness: 0.5
- _GlossyReflections: 1
- _InvFade: 1
- _Metallic: 0
- _Mode: 0
- _OcclusionStrength: 1
@@ -77,9 +77,9 @@ Material:
- _StencilReadMask: 255
- _StencilWriteMask: 255
- _UVSec: 0
- _UseUIAlphaClip: 0
- _ZWrite: 1
m_Colors:
- _ClipRect: {r: -32767, g: -32767, b: 32767, a: 32767}
- _Color: {r: 1, g: 1, b: 1, a: 1}
- _EmissionColor: {r: 0, g: 0, b: 0, a: 1}
- _TintColor: {r: 1, g: 1, b: 1, a: 1}

View File

@@ -1,5 +1,5 @@
fileFormatVersion: 2
guid: b35a584a784274746b87deef91c15c5c
guid: 356b9d0e2cad849c3b53c7e9e1680cb7
NativeFormatImporter:
externalObjects: {}
mainObjectFileID: 2100000

View File

Before

Width:  |  Height:  |  Size: 34 KiB

After

Width:  |  Height:  |  Size: 34 KiB

View File

@@ -1,9 +1,8 @@
using System;
using UnityEngine;
using UnityEngine;
namespace Coffee.UIExtensions
{
[Serializable]
[System.Serializable]
public class AnimatableProperty : ISerializationCallbackReceiver
{
public enum ShaderPropertyType
@@ -12,22 +11,16 @@ namespace Coffee.UIExtensions
Vector,
Float,
Range,
Texture
Texture,
}
[SerializeField] private string m_Name = "";
[SerializeField] private ShaderPropertyType m_Type = ShaderPropertyType.Vector;
[SerializeField] string m_Name = "";
[SerializeField] ShaderPropertyType m_Type = ShaderPropertyType.Vector;
public int id { get; private set; }
public ShaderPropertyType type => m_Type;
void ISerializationCallbackReceiver.OnBeforeSerialize()
public ShaderPropertyType type
{
}
void ISerializationCallbackReceiver.OnAfterDeserialize()
{
id = Shader.PropertyToID(m_Name);
get { return m_Type; }
}
public void UpdateMaterialProperties(Material material, MaterialPropertyBlock mpb)
@@ -38,38 +31,35 @@ namespace Coffee.UIExtensions
{
case ShaderPropertyType.Color:
var color = mpb.GetColor(id);
if (color != default)
{
if (color != default(Color))
material.SetColor(id, color);
}
break;
case ShaderPropertyType.Vector:
var vector = mpb.GetVector(id);
if (vector != default)
{
if (vector != default(Vector4))
material.SetVector(id, vector);
}
break;
case ShaderPropertyType.Float:
case ShaderPropertyType.Range:
var value = mpb.GetFloat(id);
if (!Mathf.Approximately(value, 0))
{
if (value != default(float))
material.SetFloat(id, value);
}
break;
case ShaderPropertyType.Texture:
var tex = mpb.GetTexture(id);
if (tex != default(Texture))
{
material.SetTexture(id, tex);
}
break;
}
}
public void OnBeforeSerialize()
{
}
public void OnAfterDeserialize()
{
id = Shader.PropertyToID(m_Name);
}
}
}

101
Scripts/BakingCamera.cs Normal file
View File

@@ -0,0 +1,101 @@
using UnityEngine;
namespace Coffee.UIParticleExtensions
{
[AddComponentMenu("")]
internal class BakingCamera : MonoBehaviour
{
static BakingCamera s_Instance;
private static readonly Vector3 s_OrthoPosition = new Vector3(0, 0, -1000);
private static readonly Quaternion s_OrthoRotation = Quaternion.identity;
#if UNITY_2018_3_OR_NEWER && UNITY_EDITOR
static BakingCamera s_InstanceForPrefab;
private static BakingCamera InstanceForPrefab
{
get
{
// If current scene is prefab mode, create OverlayCamera for editor.
#if UNITY_2021_2_OR_NEWER
var prefabStage = UnityEditor.SceneManagement.PrefabStageUtility.GetCurrentPrefabStage();
#else
var prefabStage = UnityEditor.Experimental.SceneManagement.PrefabStageUtility.GetCurrentPrefabStage();
#endif
if (prefabStage == null || !prefabStage.scene.isLoaded) return null;
if (s_InstanceForPrefab) return s_InstanceForPrefab;
s_InstanceForPrefab = Create();
s_InstanceForPrefab.name += " (For Prefab Stage)";
UnityEngine.SceneManagement.SceneManager.MoveGameObjectToScene(s_InstanceForPrefab.gameObject, prefabStage.scene);
return s_InstanceForPrefab;
}
}
#endif
private static BakingCamera Instance
{
get
{
#if UNITY_2018_3_OR_NEWER && UNITY_EDITOR
var inst = InstanceForPrefab;
if (inst) return inst;
#endif
// Find instance in scene, or create new one.
return s_Instance
? s_Instance
: (s_Instance = Create());
}
}
private Camera _camera;
private static BakingCamera Create()
{
var gameObject = new GameObject(typeof(BakingCamera).Name);
// This camera object is just for internal use
gameObject.hideFlags = HideFlags.HideAndDontSave;
var inst = gameObject.AddComponent<BakingCamera>();
inst._camera = gameObject.AddComponent<Camera>();
inst._camera.enabled = false;
inst._camera.orthographic = true;
// Turn camera off because particle mesh baker will use only camera matrix
gameObject.SetActive(false);
return inst;
}
private void Awake()
{
if (this == s_Instance)
DontDestroyOnLoad(gameObject);
}
public static Camera GetCamera(Canvas canvas)
{
if (!canvas) return Camera.main;
canvas = canvas.rootCanvas;
// Adjust camera orthographic size to canvas size
// for canvas-based coordinates of particles' size and speed.
var size = ((RectTransform) canvas.transform).rect.size;
Instance._camera.orthographicSize = Mathf.Max(size.x, size.y) * canvas.scaleFactor;
var camera = canvas.worldCamera;
var transform = Instance.transform;
var rotation = canvas.renderMode != RenderMode.ScreenSpaceOverlay && camera
? camera.transform.rotation
: s_OrthoRotation;
transform.SetPositionAndRotation(s_OrthoPosition, rotation);
Instance._camera.orthographic = true;
Instance._camera.farClipPlane = 2000f;
return Instance._camera;
}
}
}

View File

@@ -1,5 +1,5 @@
fileFormatVersion: 2
guid: 0e66d2d1ba43c4cc4bc3e754e403297b
guid: 999f0ea10cb5f48ed89190a0ca83dd53
MonoImporter:
externalObjects: {}
serializedVersion: 2

View File

@@ -0,0 +1,63 @@
using System.Collections.Generic;
using UnityEngine;
namespace Coffee.UIParticleExtensions
{
internal class CombineInstanceEx
{
private int count;
public long hash = -1;
public int index = -1;
private readonly List<CombineInstance> combineInstances = new List<CombineInstance>(32);
public Mesh mesh;
public Matrix4x4 transform;
public void Combine()
{
switch (count)
{
case 0:
return;
case 1:
mesh = combineInstances[0].mesh;
transform = combineInstances[0].transform;
return;
default:
{
var cis = CombineInstanceArrayPool.Get(combineInstances);
mesh = MeshPool.Rent();
mesh.CombineMeshes(cis, true, true);
transform = Matrix4x4.identity;
cis.Clear();
return;
}
}
}
public void Clear()
{
for (var i = 0; i < combineInstances.Count; i++)
{
var inst = combineInstances[i];
MeshPool.Return(inst.mesh);
inst.mesh = null;
combineInstances[i] = inst;
}
combineInstances.Clear();
MeshPool.Return(mesh);
mesh = null;
count = 0;
hash = -1;
index = -1;
}
public void Push(Mesh mesh, Matrix4x4 transform)
{
combineInstances.Add(new CombineInstance {mesh = mesh, transform = transform});
count++;
}
}
}

View File

@@ -1,5 +1,5 @@
fileFormatVersion: 2
guid: 01a6a172129d6453eb661239d2b1e850
guid: 0328b9fb8360e4f8e8a842f87d330466
MonoImporter:
externalObjects: {}
serializedVersion: 2

View File

@@ -0,0 +1,123 @@
using UnityEditor;
using UnityEngine;
using System.Collections.Generic;
using System.Linq;
using ShaderPropertyType = Coffee.UIExtensions.AnimatableProperty.ShaderPropertyType;
namespace Coffee.UIExtensions
{
internal class AnimatedPropertiesEditor
{
private static readonly List<string> s_ActiveNames = new List<string>();
private static readonly System.Text.StringBuilder s_Sb = new System.Text.StringBuilder();
private static readonly HashSet<string> s_Names = new HashSet<string>();
private string _name;
private ShaderPropertyType _type;
static string CollectActiveNames(SerializedProperty sp, List<string> result)
{
result.Clear();
for (var i = 0; i < sp.arraySize; i++)
{
var spName = sp.GetArrayElementAtIndex(i).FindPropertyRelative("m_Name");
if (spName == null) continue;
result.Add(spName.stringValue);
}
s_Sb.Length = 0;
if (result.Count == 0)
{
s_Sb.Append("Nothing");
}
else
{
result.Aggregate(s_Sb, (a, b) => s_Sb.AppendFormat("{0}, ", b));
s_Sb.Length -= 2;
}
return s_Sb.ToString();
}
public static void DrawAnimatableProperties(SerializedProperty sp, Material[] mats)
{
bool isClicked;
using (new EditorGUILayout.HorizontalScope(GUILayout.ExpandWidth(false)))
{
var r = EditorGUI.PrefixLabel(EditorGUILayout.GetControlRect(true), new GUIContent(sp.displayName, sp.tooltip));
var text = sp.hasMultipleDifferentValues ? "-" : CollectActiveNames(sp, s_ActiveNames);
isClicked = GUI.Button(r, text, EditorStyles.popup);
}
if (!isClicked) return;
var gm = new GenericMenu();
gm.AddItem(new GUIContent("Nothing"), s_ActiveNames.Count == 0, () =>
{
sp.ClearArray();
sp.serializedObject.ApplyModifiedProperties();
});
if (!sp.hasMultipleDifferentValues)
{
for (var i = 0; i < sp.arraySize; i++)
{
var p = sp.GetArrayElementAtIndex(i);
var name = p.FindPropertyRelative("m_Name").stringValue;
var type = (ShaderPropertyType) p.FindPropertyRelative("m_Type").intValue;
AddMenu(gm, sp, new AnimatedPropertiesEditor {_name = name, _type = type}, false);
}
}
s_Names.Clear();
foreach (var mat in mats)
{
if (!mat || !mat.shader) continue;
for (var i = 0; i < ShaderUtil.GetPropertyCount(mat.shader); i++)
{
var pName = ShaderUtil.GetPropertyName(mat.shader, i);
var type = (ShaderPropertyType) ShaderUtil.GetPropertyType(mat.shader, i);
var name = string.Format("{0} ({1})", pName, type);
if (s_Names.Contains(name)) continue;
s_Names.Add(name);
AddMenu(gm, sp, new AnimatedPropertiesEditor {_name = pName, _type = type}, true);
if (type != ShaderPropertyType.Texture) continue;
AddMenu(gm, sp, new AnimatedPropertiesEditor {_name = pName + "_ST", _type = ShaderPropertyType.Vector}, true);
AddMenu(gm, sp, new AnimatedPropertiesEditor {_name = pName + "_HDR", _type = ShaderPropertyType.Vector}, true);
AddMenu(gm, sp, new AnimatedPropertiesEditor {_name = pName + "_TexelSize", _type = ShaderPropertyType.Vector}, true);
}
}
gm.ShowAsContext();
}
private static void AddMenu(GenericMenu menu, SerializedProperty sp, AnimatedPropertiesEditor property, bool add)
{
if (add && s_ActiveNames.Contains(property._name)) return;
menu.AddItem(new GUIContent(string.Format("{0} ({1})", property._name, property._type)), s_ActiveNames.Contains(property._name), () =>
{
var index = s_ActiveNames.IndexOf(property._name);
if (0 <= index)
{
sp.DeleteArrayElementAtIndex(index);
}
else
{
sp.InsertArrayElementAtIndex(sp.arraySize);
var p = sp.GetArrayElementAtIndex(sp.arraySize - 1);
p.FindPropertyRelative("m_Name").stringValue = property._name;
p.FindPropertyRelative("m_Type").intValue = (int) property._type;
}
sp.serializedObject.ApplyModifiedProperties();
});
}
}
}

Some files were not shown because too many files have changed in this diff Show More