You've already forked ParticleEffectForUGUI
mirror of
https://github.com/mob-sakai/ParticleEffectForUGUI.git
synced 2026-05-14 20:20:06 +00:00
Compare commits
71 Commits
a92d0b9280
...
4.9.1
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
025efcbc5d | ||
|
|
162ee53180 | ||
|
|
4dfcb9075e | ||
|
|
7916056868 | ||
|
|
b87a0a02af | ||
|
|
3052cab41b | ||
|
|
a439248e1a | ||
|
|
686fff8690 | ||
|
|
3638df524f | ||
|
|
592d871da2 | ||
|
|
4d0cfd3510 | ||
|
|
4c5251a5ba | ||
|
|
cbb37b0b3a | ||
|
|
3c54f6dc8d | ||
|
|
d3532b9708 | ||
|
|
2ac8a1175b | ||
|
|
9a37e64b20 | ||
|
|
bc0c2e4e63 | ||
|
|
929c0d686b | ||
|
|
1674e850e0 | ||
|
|
c43ba67a9b | ||
|
|
4c285fde14 | ||
|
|
22795fca9a | ||
|
|
1aca69bbb7 | ||
|
|
3619b4ff94 | ||
|
|
cc3e95d8c7 | ||
|
|
5c28e9a2f3 | ||
|
|
b82f79c2de | ||
|
|
f029b7508e | ||
|
|
5c41c39847 | ||
|
|
49f46d5c9e | ||
|
|
628b9582b2 | ||
|
|
e8c9873201 | ||
|
|
fa6881a028 | ||
|
|
e0c8f6ade8 | ||
|
|
612015f7cf | ||
|
|
09c2c95f3b | ||
|
|
3454273095 | ||
|
|
e82b35466b | ||
|
|
50ba446cff | ||
|
|
d4ffadf599 | ||
|
|
4a940d8e31 | ||
|
|
6d8dee0b06 | ||
|
|
67b384a1fe | ||
|
|
990baacdf9 | ||
|
|
f73a6777c4 | ||
|
|
65da5d35f5 | ||
|
|
25a9cdb400 | ||
|
|
c6b2950a75 | ||
|
|
841e449f78 | ||
|
|
9d04e41cde | ||
|
|
f1e672470c | ||
|
|
9d1b6a81ee | ||
|
|
e32077fb0d | ||
|
|
293dc43db7 | ||
|
|
2b5166dcd9 | ||
|
|
ee780c4996 | ||
|
|
e840631fb3 | ||
|
|
a5fdfce554 | ||
|
|
8028b2a770 | ||
|
|
b45dc77312 | ||
|
|
5dab4f21c7 | ||
|
|
f17ecafae7 | ||
|
|
5892df1ce1 | ||
|
|
f0fb205212 | ||
|
|
70e917107d | ||
|
|
eaae94ce00 | ||
|
|
7430c39f52 | ||
|
|
5fc44b82bc | ||
|
|
128990acc6 | ||
|
|
4790db6b93 |
25
.github/ISSUE_TEMPLATE/bug_report.md
vendored
25
.github/ISSUE_TEMPLATE/bug_report.md
vendored
@@ -10,39 +10,26 @@ assignees: mob-sakai
|
|||||||
NOTE: Your issue may already be reported! Please search on the [issue tracker](../) before creating one.
|
NOTE: Your issue may already be reported! Please search on the [issue tracker](../) before creating one.
|
||||||
|
|
||||||
**Describe the bug**
|
**Describe the bug**
|
||||||
|
|
||||||
A clear and concise description of what the bug is.
|
A clear and concise description of what the bug is.
|
||||||
|
|
||||||
**To Reproduce**
|
**To Reproduce**
|
||||||
|
|
||||||
Steps to reproduce the behavior:
|
Steps to reproduce the behavior:
|
||||||
|
|
||||||
1. Go to '...'
|
1. Go to '...'
|
||||||
2. Click on '....'
|
2. Click on '....'
|
||||||
3. Scroll down to '....'
|
3. Scroll down to '....'
|
||||||
4. See error
|
4. See error
|
||||||
|
|
||||||
**Expected behavior**
|
**Expected behavior**
|
||||||
|
|
||||||
A clear and concise description of what you expected to happen.
|
A clear and concise description of what you expected to happen.
|
||||||
|
|
||||||
**Screenshots**
|
**Screenshots**
|
||||||
|
|
||||||
If applicable, add screenshots to help explain your problem.
|
If applicable, add screenshots to help explain your problem.
|
||||||
|
|
||||||
**Environment (please complete the following)**
|
**Environment (please complete the following information):**
|
||||||
|
- Version [e.g. 4.0.0]
|
||||||
- Package version [e.g. 4.2.0, 3.3.14]
|
- Platform: [e.g. Editor(Windows/Mac), Standalone(Windows/Mac), iOS, Android, WebGL]
|
||||||
- Platform: [e.g. Editor(Windows/Mac), Standalone(Windows/Mac), iOS, Android, WebGL]
|
- Unity version: [e.g. 2022.3.0f1]
|
||||||
- Unity version: [e.g. 2021.3.7f1]
|
- Build options: [e.g. IL2CPP, .Net 4.x, LWRP]
|
||||||
- Project options: [e.g. Mono/IL2CPP, .Net Standard 2.1/.Net 4.x, URP/HDRP, GraphicAPIs]
|
|
||||||
|
|
||||||
**Additional context**
|
**Additional context**
|
||||||
|
Add any other context about the problem here.
|
||||||
Please add any other context about the issue here.
|
|
||||||
It will help us resolve the issue.
|
|
||||||
|
|
||||||
- Error messages and crash dump
|
|
||||||
- Screenshots, gif animations and movie files
|
|
||||||
- Reproducible minimal project
|
|
||||||
- The entire project (zipped Assets, Packages, ProjectSettings) is preferred over `.unitypackage`
|
|
||||||
|
|||||||
6
.github/ISSUE_TEMPLATE/feature_request.md
vendored
6
.github/ISSUE_TEMPLATE/feature_request.md
vendored
@@ -10,17 +10,13 @@ assignees: mob-sakai
|
|||||||
NOTE: Your issue may already be reported! Please search on the [issue tracker](../) before creating one.
|
NOTE: Your issue may already be reported! Please search on the [issue tracker](../) before creating one.
|
||||||
|
|
||||||
**Is your feature request related to a problem? Please describe.**
|
**Is your feature request related to a problem? Please describe.**
|
||||||
|
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
|
||||||
A clear and concise description of what the issue is. (e.g. I'm always frustrated when [...])
|
|
||||||
|
|
||||||
**Describe the solution you'd like**
|
**Describe the solution you'd like**
|
||||||
|
|
||||||
A clear and concise description of what you want to happen.
|
A clear and concise description of what you want to happen.
|
||||||
|
|
||||||
**Describe alternatives you've considered**
|
**Describe alternatives you've considered**
|
||||||
|
|
||||||
A clear and concise description of any alternative solutions or features you've considered.
|
A clear and concise description of any alternative solutions or features you've considered.
|
||||||
|
|
||||||
**Additional context**
|
**Additional context**
|
||||||
|
|
||||||
Add any other context or screenshots about the feature request here.
|
Add any other context or screenshots about the feature request here.
|
||||||
|
|||||||
9
.github/pull_request_template.md
vendored
Normal file
9
.github/pull_request_template.md
vendored
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
---
|
||||||
|
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
24
.github/workflows/release.yml
vendored
@@ -1,24 +0,0 @@
|
|||||||
name: release
|
|
||||||
|
|
||||||
on:
|
|
||||||
push:
|
|
||||||
branches:
|
|
||||||
- preview
|
|
||||||
- main
|
|
||||||
- v*.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 }}
|
|
||||||
69
.github/workflows/test.yml
vendored
69
.github/workflows/test.yml
vendored
@@ -1,69 +0,0 @@
|
|||||||
# Secrets
|
|
||||||
# UNITY_LICENSE:
|
|
||||||
name: test
|
|
||||||
|
|
||||||
on:
|
|
||||||
push:
|
|
||||||
branches:
|
|
||||||
- develop
|
|
||||||
tags:
|
|
||||||
- "!*"
|
|
||||||
pull_request:
|
|
||||||
types:
|
|
||||||
- opened
|
|
||||||
- synchronize
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
setup:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
outputs:
|
|
||||||
versions: ${{ steps.setup.outputs.versions }}
|
|
||||||
steps:
|
|
||||||
- id: setup
|
|
||||||
run: |
|
|
||||||
VERSIONS=`npx unity-changeset list --versions --all --latest-patch --min 2018.3 --json`
|
|
||||||
echo "==== Target Unity Versions ===="
|
|
||||||
echo "${VERSIONS}"
|
|
||||||
echo "::set-output name=versions::${VERSIONS}"
|
|
||||||
|
|
||||||
test:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
needs: setup
|
|
||||||
strategy:
|
|
||||||
fail-fast: false
|
|
||||||
matrix:
|
|
||||||
version: ${{ fromJson(needs.setup.outputs.versions) }}
|
|
||||||
|
|
||||||
steps:
|
|
||||||
# Checkout sandbox project
|
|
||||||
- uses: actions/checkout@v3
|
|
||||||
with:
|
|
||||||
ref: sandbox
|
|
||||||
submodules: true
|
|
||||||
fetch-depth: 0
|
|
||||||
|
|
||||||
# Update package submodule
|
|
||||||
- name: "Update package submodule"
|
|
||||||
working-directory: Packages/dev
|
|
||||||
run: git checkout ${{ github.sha }}
|
|
||||||
|
|
||||||
# Cache
|
|
||||||
- uses: actions/cache@v3
|
|
||||||
with:
|
|
||||||
path: Library
|
|
||||||
key: Library-${{ matrix.version }}-${{ github.sha }}
|
|
||||||
restore-keys: |
|
|
||||||
Library-${{ matrix.version }}-
|
|
||||||
Library-
|
|
||||||
|
|
||||||
# Run tests
|
|
||||||
- name: "Run tests"
|
|
||||||
uses: game-ci/unity-test-runner@v2
|
|
||||||
with:
|
|
||||||
customImage: mobsakai/unity3d:${{ matrix.version }}
|
|
||||||
customParameters: -nographics
|
|
||||||
# unityVersion: ${{ matrix.version }}
|
|
||||||
checkName: ${{ matrix.version }} Test Results
|
|
||||||
githubToken: ${{ github.token }}
|
|
||||||
env:
|
|
||||||
UNITY_LICENSE: ${{ secrets.UNITY_LICENSE }}
|
|
||||||
@@ -1,14 +1,12 @@
|
|||||||
{
|
{
|
||||||
"branches": [
|
"branches": [
|
||||||
"+([0-9])?(.{+([0-9]),x}).x",
|
"release",
|
||||||
"master",
|
"release-4.x",
|
||||||
"main",
|
|
||||||
{
|
{
|
||||||
"name": "preview",
|
"name": "release-preview",
|
||||||
"prerelease": true
|
"prerelease": "preview"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"tagFormat": "${version}",
|
|
||||||
"plugins": [
|
"plugins": [
|
||||||
"@semantic-release/commit-analyzer",
|
"@semantic-release/commit-analyzer",
|
||||||
"@semantic-release/release-notes-generator",
|
"@semantic-release/release-notes-generator",
|
||||||
|
|||||||
162
CHANGELOG.md
162
CHANGELOG.md
@@ -1,3 +1,165 @@
|
|||||||
|
## [4.9.1](https://github.com/mob-sakai/ParticleEffectForUGUI/compare/v4.9.0...v4.9.1) (2024-08-07)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* ParticleSystem trails gain offset on parent canvas change ([2a1cd50](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/2a1cd502b452b5b56edf8bcfe91adf99d1bb5147)), closes [#323](https://github.com/mob-sakai/ParticleEffectForUGUI/issues/323)
|
||||||
|
|
||||||
|
# [4.9.0](https://github.com/mob-sakai/ParticleEffectForUGUI/compare/v4.8.1...v4.9.0) (2024-07-18)
|
||||||
|
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* ParticleAttractor supports multiple ParticleSystems ([3834780](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/3834780fdb43443fe6e1ef89df54d26a24d62a91))
|
||||||
|
|
||||||
|
## [4.8.1](https://github.com/mob-sakai/ParticleEffectForUGUI/compare/v4.8.0...v4.8.1) (2024-06-27)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* remove debug code ([669deb4](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/669deb41d4ac589d9db93b29bc8e95383e7f28a5))
|
||||||
|
|
||||||
|
# [4.8.0](https://github.com/mob-sakai/ParticleEffectForUGUI/compare/v4.7.2...v4.8.0) (2024-06-27)
|
||||||
|
|
||||||
|
|
||||||
|
### 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)
|
## [4.5.2](https://github.com/mob-sakai/ParticleEffectForUGUI/compare/4.5.1...4.5.2) (2024-01-18)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -19,11 +19,24 @@ When fixing a bug it is fine to submit a pull request right away.
|
|||||||
|
|
||||||
Steps to be performed to submit a pull request:
|
Steps to be performed to submit a pull request:
|
||||||
|
|
||||||
1. Fork the repository and create your branch from `develop`.
|
1. Fork the repository.
|
||||||
2. If you have fixed a bug or added code that should be tested, add tests.
|
2. Clone the repository.
|
||||||
3. Click `Window > Generals > Test Runner` to test
|
3. Checkout `develop` branch.
|
||||||
4. Commit with a massage based on [Angular Commit Message Conventions](https://gist.github.com/stephenparish/9941e89d80e2bc58a153).
|
4. Develop the package.
|
||||||
5. Fill out the description, link any related issues and submit your pull request.
|
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.
|
||||||
|
|
||||||
#### License
|
#### License
|
||||||
|
|
||||||
|
|||||||
@@ -31,35 +31,35 @@ namespace Coffee.UIExtensions
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
result.Aggregate(s_Sb, (a, b) => s_Sb.AppendFormat("{0}, ", b));
|
result.Aggregate(s_Sb, (a, b) =>
|
||||||
|
{
|
||||||
|
s_Sb.Append(b);
|
||||||
|
return s_Sb.Append(", ");
|
||||||
|
});
|
||||||
s_Sb.Length -= 2;
|
s_Sb.Length -= 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
return s_Sb.ToString();
|
return s_Sb.ToString();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void Draw(SerializedProperty sp, Material[] mats)
|
public static void Draw(SerializedProperty sp, List<Material> mats)
|
||||||
{
|
{
|
||||||
bool isClicked;
|
var pos = EditorGUILayout.GetControlRect(true);
|
||||||
using (new EditorGUILayout.HorizontalScope(GUILayout.ExpandWidth(false)))
|
var label = new GUIContent(sp.displayName, sp.tooltip);
|
||||||
{
|
var rect = EditorGUI.PrefixLabel(pos, label);
|
||||||
var pos = EditorGUILayout.GetControlRect(true);
|
var text = sp.hasMultipleDifferentValues
|
||||||
var label = new GUIContent(sp.displayName, sp.tooltip);
|
? "-"
|
||||||
var rect = EditorGUI.PrefixLabel(pos, label);
|
: CollectActiveNames(sp, s_ActiveNames);
|
||||||
var text = sp.hasMultipleDifferentValues
|
|
||||||
? "-"
|
|
||||||
: CollectActiveNames(sp, s_ActiveNames);
|
|
||||||
isClicked = GUI.Button(rect, text, EditorStyles.popup);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!isClicked) return;
|
if (!GUI.Button(rect, text, EditorStyles.popup)) return;
|
||||||
|
|
||||||
var gm = new GenericMenu();
|
var gm = new GenericMenu();
|
||||||
gm.AddItem(s_ContentNothing, s_ActiveNames.Count == 0, () =>
|
gm.AddItem(s_ContentNothing, s_ActiveNames.Count == 0, x =>
|
||||||
{
|
{
|
||||||
sp.ClearArray();
|
var current = (SerializedProperty)x;
|
||||||
sp.serializedObject.ApplyModifiedProperties();
|
current.ClearArray();
|
||||||
});
|
current.serializedObject.ApplyModifiedProperties();
|
||||||
|
}, sp);
|
||||||
|
|
||||||
if (!sp.hasMultipleDifferentValues)
|
if (!sp.hasMultipleDifferentValues)
|
||||||
{
|
{
|
||||||
@@ -73,7 +73,7 @@ namespace Coffee.UIExtensions
|
|||||||
}
|
}
|
||||||
|
|
||||||
s_Names.Clear();
|
s_Names.Clear();
|
||||||
for (var j = 0; j < mats.Length; j++)
|
for (var j = 0; j < mats.Count; j++)
|
||||||
{
|
{
|
||||||
var mat = mats[j];
|
var mat = mats[j];
|
||||||
if (!mat || !mat.shader) continue;
|
if (!mat || !mat.shader) continue;
|
||||||
@@ -82,8 +82,7 @@ namespace Coffee.UIExtensions
|
|||||||
{
|
{
|
||||||
var name = ShaderUtil.GetPropertyName(mat.shader, i);
|
var name = ShaderUtil.GetPropertyName(mat.shader, i);
|
||||||
var type = (AnimatableProperty.ShaderPropertyType)ShaderUtil.GetPropertyType(mat.shader, i);
|
var type = (AnimatableProperty.ShaderPropertyType)ShaderUtil.GetPropertyType(mat.shader, i);
|
||||||
if (s_Names.Contains(name)) continue;
|
if (!s_Names.Add(name)) continue;
|
||||||
s_Names.Add(name);
|
|
||||||
|
|
||||||
AddMenu(gm, sp, new ShaderProperty(name, type), true);
|
AddMenu(gm, sp, new ShaderProperty(name, type), true);
|
||||||
|
|
||||||
@@ -1,24 +1,25 @@
|
|||||||
|
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
|
#if UNITY_2021_2_OR_NEWER
|
||||||
using UnityEditor.Overlays;
|
using UnityEditor.Overlays;
|
||||||
#else
|
#else
|
||||||
|
using System;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
|
using Object = UnityEngine.Object;
|
||||||
#endif
|
#endif
|
||||||
#if UNITY_2021_2_OR_NEWER
|
#if UNITY_2021_2_OR_NEWER
|
||||||
using UnityEditor.SceneManagement;
|
using UnityEditor.SceneManagement;
|
||||||
#elif UNITY_2018_3_OR_NEWER
|
#elif UNITY_2018_3_OR_NEWER
|
||||||
using UnityEditor.Experimental.SceneManagement;
|
using UnityEditor.Experimental.SceneManagement;
|
||||||
#endif
|
#endif
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text.RegularExpressions;
|
|
||||||
using Coffee.UIParticleExtensions;
|
|
||||||
using UnityEditor;
|
|
||||||
using UnityEditor.UI;
|
|
||||||
using UnityEditorInternal;
|
|
||||||
using UnityEngine;
|
|
||||||
using UnityEngine.UI;
|
|
||||||
using Object = UnityEngine.Object;
|
|
||||||
|
|
||||||
namespace Coffee.UIExtensions
|
namespace Coffee.UIExtensions
|
||||||
{
|
{
|
||||||
@@ -26,41 +27,24 @@ namespace Coffee.UIExtensions
|
|||||||
[CanEditMultipleObjects]
|
[CanEditMultipleObjects]
|
||||||
internal class UIParticleEditor : GraphicEditor
|
internal class UIParticleEditor : GraphicEditor
|
||||||
{
|
{
|
||||||
#if UNITY_2021_2_OR_NEWER
|
|
||||||
#if UNITY_2022_1_OR_NEWER
|
|
||||||
[Overlay(typeof(SceneView), "Scene View/UI Particles", "UI Particles", true,
|
|
||||||
defaultDockPosition = DockPosition.Bottom,
|
|
||||||
defaultDockZone = DockZone.Floating,
|
|
||||||
defaultLayout = Layout.Panel)]
|
|
||||||
#else
|
|
||||||
[Overlay(typeof(SceneView), "Scene View/UI Particles", "UI Particles", true)]
|
|
||||||
#endif
|
|
||||||
private class UIParticleOverlay : IMGUIOverlay, ITransientOverlay
|
|
||||||
{
|
|
||||||
public bool visible => s_SerializedObject != null;
|
|
||||||
|
|
||||||
public override void OnGUI()
|
|
||||||
{
|
|
||||||
if (visible)
|
|
||||||
{
|
|
||||||
WindowFunction(null, null);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
//################################
|
//################################
|
||||||
// Constant or Static Members.
|
// 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_ContentRenderingOrder = new GUIContent("Rendering Order");
|
||||||
private static readonly GUIContent s_ContentRefresh = new GUIContent("Refresh");
|
private static readonly GUIContent s_ContentRefresh = new GUIContent("Refresh");
|
||||||
private static readonly GUIContent s_ContentFix = new GUIContent("Fix");
|
private static readonly GUIContent s_ContentFix = new GUIContent("Fix");
|
||||||
private static readonly GUIContent s_ContentMaterial = new GUIContent("Material");
|
|
||||||
private static readonly GUIContent s_ContentTrailMaterial = new GUIContent("Trail Material");
|
|
||||||
private static readonly GUIContent s_Content3D = new GUIContent("3D");
|
private static readonly GUIContent s_Content3D = new GUIContent("3D");
|
||||||
private static readonly GUIContent s_ContentRandom = new GUIContent("Random");
|
private static readonly GUIContent s_ContentRandom = new GUIContent("Random");
|
||||||
private static readonly GUIContent s_ContentScale = new GUIContent("Scale");
|
private static readonly GUIContent s_ContentScale = new GUIContent("Scale");
|
||||||
private static SerializedObject s_SerializedObject;
|
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 static bool s_XYZMode;
|
||||||
|
|
||||||
private SerializedProperty _maskable;
|
private SerializedProperty _maskable;
|
||||||
@@ -71,12 +55,15 @@ namespace Coffee.UIExtensions
|
|||||||
private SerializedProperty _groupMaxId;
|
private SerializedProperty _groupMaxId;
|
||||||
private SerializedProperty _positionMode;
|
private SerializedProperty _positionMode;
|
||||||
private SerializedProperty _autoScalingMode;
|
private SerializedProperty _autoScalingMode;
|
||||||
|
private SerializedProperty _useCustomView;
|
||||||
|
private SerializedProperty _customViewSize;
|
||||||
private ReorderableList _ro;
|
private ReorderableList _ro;
|
||||||
private bool _showMax;
|
private bool _showMax;
|
||||||
|
|
||||||
private static readonly HashSet<Shader> s_Shaders = new HashSet<Shader>();
|
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>();
|
private static readonly List<ParticleSystemVertexStream> s_Streams = new List<ParticleSystemVertexStream>();
|
||||||
|
#endif
|
||||||
private static readonly List<string> s_MaskablePropertyNames = new List<string>
|
private static readonly List<string> s_MaskablePropertyNames = new List<string>
|
||||||
{
|
{
|
||||||
"_Stencil",
|
"_Stencil",
|
||||||
@@ -87,55 +74,6 @@ namespace Coffee.UIExtensions
|
|||||||
"_ColorMask"
|
"_ColorMask"
|
||||||
};
|
};
|
||||||
|
|
||||||
[InitializeOnLoadMethod]
|
|
||||||
private static void Init()
|
|
||||||
{
|
|
||||||
#if !UNITY_2021_2_OR_NEWER
|
|
||||||
var miSceneViewOverlayWindow = Type.GetType("UnityEditor.SceneViewOverlay, UnityEditor")
|
|
||||||
?.GetMethods(BindingFlags.Public | BindingFlags.Static)
|
|
||||||
.First(x => x.Name == "Window" && 5 <= x.GetParameters().Length);
|
|
||||||
var windowFunction = (Action<Object, SceneView>)WindowFunction;
|
|
||||||
var windowFunctionType = Type.GetType("UnityEditor.SceneViewOverlay+WindowFunction, UnityEditor");
|
|
||||||
var windowFunctionDelegate = Delegate.CreateDelegate(windowFunctionType, windowFunction.Method);
|
|
||||||
var windowTitle = new GUIContent(ObjectNames.NicifyVariableName(nameof(UIParticle)));
|
|
||||||
#if UNITY_2019_2_OR_NEWER
|
|
||||||
//public static void Window(GUIContent title, WindowFunction sceneViewFunc, int order, Object target, WindowDisplayOption option, EditorWindow window = null)
|
|
||||||
var sceneViewArgs = new object[] { windowTitle, windowFunctionDelegate, 599, null, 2, null };
|
|
||||||
#else
|
|
||||||
//public static void Window(GUIContent title, WindowFunction sceneViewFunc, int order, Object target, WindowDisplayOption option)
|
|
||||||
var sceneViewArgs = new object[] { windowTitle, windowFunctionDelegate, 599, null, 2 };
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if UNITY_2019_1_OR_NEWER
|
|
||||||
SceneView.duringSceneGui += _ =>
|
|
||||||
#else
|
|
||||||
SceneView.onSceneGUIDelegate += _ =>
|
|
||||||
#endif
|
|
||||||
{
|
|
||||||
if (s_SerializedObject != null)
|
|
||||||
{
|
|
||||||
miSceneViewOverlayWindow.Invoke(null, sceneViewArgs);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
#endif
|
|
||||||
|
|
||||||
SerializedObject CreateSerializeObject()
|
|
||||||
{
|
|
||||||
var uiParticles = Selection.gameObjects.Select(x => x.GetComponent<ParticleSystem>())
|
|
||||||
.Where(x => x)
|
|
||||||
.Select(x => x.GetComponentInParent<UIParticle>(true))
|
|
||||||
.Where(x => x && x.canvas)
|
|
||||||
.Concat(Selection.gameObjects.Select(x => x.GetComponent<UIParticle>())
|
|
||||||
.Where(x => x && x.canvas))
|
|
||||||
.Distinct()
|
|
||||||
.ToArray();
|
|
||||||
return 0 < uiParticles.Length ? new SerializedObject(uiParticles) : null;
|
|
||||||
}
|
|
||||||
|
|
||||||
s_SerializedObject = CreateSerializeObject();
|
|
||||||
Selection.selectionChanged += () => s_SerializedObject = CreateSerializeObject();
|
|
||||||
}
|
|
||||||
|
|
||||||
//################################
|
//################################
|
||||||
// Public/Protected Members.
|
// Public/Protected Members.
|
||||||
//################################
|
//################################
|
||||||
@@ -154,31 +92,43 @@ namespace Coffee.UIExtensions
|
|||||||
_groupMaxId = serializedObject.FindProperty("m_GroupMaxId");
|
_groupMaxId = serializedObject.FindProperty("m_GroupMaxId");
|
||||||
_positionMode = serializedObject.FindProperty("m_PositionMode");
|
_positionMode = serializedObject.FindProperty("m_PositionMode");
|
||||||
_autoScalingMode = serializedObject.FindProperty("m_AutoScalingMode");
|
_autoScalingMode = serializedObject.FindProperty("m_AutoScalingMode");
|
||||||
|
_useCustomView = serializedObject.FindProperty("m_UseCustomView");
|
||||||
|
_customViewSize = serializedObject.FindProperty("m_CustomViewSize");
|
||||||
|
|
||||||
var sp = serializedObject.FindProperty("m_Particles");
|
var sp = serializedObject.FindProperty("m_Particles");
|
||||||
_ro = new ReorderableList(sp.serializedObject, sp, true, true, true, true)
|
_ro = new ReorderableList(sp.serializedObject, sp, true, true, true, true)
|
||||||
{
|
{
|
||||||
elementHeight = EditorGUIUtility.singleLineHeight * 3 + 4,
|
elementHeightCallback = index =>
|
||||||
elementHeightCallback = _ => 3 * (EditorGUIUtility.singleLineHeight + 2),
|
{
|
||||||
|
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, _, __) =>
|
drawElementCallback = (rect, index, _, __) =>
|
||||||
{
|
{
|
||||||
EditorGUI.BeginDisabledGroup(sp.hasMultipleDifferentValues);
|
rect.y += 2;
|
||||||
rect.y += 1;
|
|
||||||
rect.height = EditorGUIUtility.singleLineHeight;
|
rect.height = EditorGUIUtility.singleLineHeight;
|
||||||
var p = sp.GetArrayElementAtIndex(index);
|
var p = sp.GetArrayElementAtIndex(index);
|
||||||
EditorGUI.ObjectField(rect, p, GUIContent.none);
|
EditorGUI.ObjectField(rect, p, GUIContent.none);
|
||||||
|
var ps = p.objectReferenceValue as ParticleSystem;
|
||||||
|
if (!ps || !ps.TryGetComponent<ParticleSystemRenderer>(out var psr)) return;
|
||||||
|
|
||||||
rect.x += 15;
|
rect.x += 15;
|
||||||
rect.width -= 15;
|
rect.width -= 15;
|
||||||
var ps = p.objectReferenceValue as ParticleSystem;
|
var materials = new SerializedObject(psr).FindProperty("m_Materials");
|
||||||
var materials = ps
|
var count = Mathf.Min(materials.arraySize, 2);
|
||||||
? new SerializedObject(ps.GetComponent<ParticleSystemRenderer>()).FindProperty("m_Materials")
|
for (var i = 0; i < count; i++)
|
||||||
: null;
|
{
|
||||||
rect.y += rect.height + 1;
|
rect.y += rect.height + 2;
|
||||||
MaterialField(rect, s_ContentMaterial, materials, 0);
|
EditorGUI.PropertyField(rect, materials.GetArrayElementAtIndex(i), s_ContentMaterials[i]);
|
||||||
rect.y += rect.height + 1;
|
}
|
||||||
MaterialField(rect, s_ContentTrailMaterial, materials, 1);
|
|
||||||
EditorGUI.EndDisabledGroup();
|
if (materials.serializedObject.hasModifiedProperties)
|
||||||
if (materials != null && materials.serializedObject.hasModifiedProperties)
|
|
||||||
{
|
{
|
||||||
materials.serializedObject.ApplyModifiedProperties();
|
materials.serializedObject.ApplyModifiedProperties();
|
||||||
}
|
}
|
||||||
@@ -214,20 +164,6 @@ namespace Coffee.UIExtensions
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void MaterialField(Rect rect, GUIContent label, SerializedProperty sp, int index)
|
|
||||||
{
|
|
||||||
if (sp == null || sp.arraySize <= index)
|
|
||||||
{
|
|
||||||
EditorGUI.BeginDisabledGroup(true);
|
|
||||||
EditorGUI.ObjectField(rect, label, null, typeof(Material), true);
|
|
||||||
EditorGUI.EndDisabledGroup();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
EditorGUI.PropertyField(rect, sp.GetArrayElementAtIndex(index), label);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Implement this function to make a custom inspector.
|
/// Implement this function to make a custom inspector.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -236,6 +172,7 @@ namespace Coffee.UIExtensions
|
|||||||
var current = target as UIParticle;
|
var current = target as UIParticle;
|
||||||
if (!current) return;
|
if (!current) return;
|
||||||
|
|
||||||
|
Profiler.BeginSample("(UIP:E) OnInspectorGUI");
|
||||||
serializedObject.Update();
|
serializedObject.Update();
|
||||||
|
|
||||||
// Maskable
|
// Maskable
|
||||||
@@ -247,13 +184,8 @@ namespace Coffee.UIExtensions
|
|||||||
EditorGUI.EndDisabledGroup();
|
EditorGUI.EndDisabledGroup();
|
||||||
|
|
||||||
// AnimatableProperties
|
// AnimatableProperties
|
||||||
var mats = current.particles
|
current.GetMaterials(s_TempMaterials);
|
||||||
.Where(x => x)
|
AnimatablePropertyEditor.Draw(_animatableProperties, s_TempMaterials);
|
||||||
.Select(x => x.GetComponent<ParticleSystemRenderer>().sharedMaterial)
|
|
||||||
.Where(x => x)
|
|
||||||
.ToArray();
|
|
||||||
|
|
||||||
AnimatablePropertyEditor.Draw(_animatableProperties, mats);
|
|
||||||
|
|
||||||
// Mesh sharing
|
// Mesh sharing
|
||||||
EditorGUI.BeginChangeCheck();
|
EditorGUI.BeginChangeCheck();
|
||||||
@@ -261,9 +193,12 @@ namespace Coffee.UIExtensions
|
|||||||
if (EditorGUI.EndChangeCheck())
|
if (EditorGUI.EndChangeCheck())
|
||||||
{
|
{
|
||||||
serializedObject.ApplyModifiedProperties();
|
serializedObject.ApplyModifiedProperties();
|
||||||
foreach (var uip in targets.OfType<UIParticle>())
|
foreach (var t in targets)
|
||||||
{
|
{
|
||||||
uip.ResetGroupId();
|
if (t is UIParticle uip)
|
||||||
|
{
|
||||||
|
uip.ResetGroupId();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -271,16 +206,29 @@ namespace Coffee.UIExtensions
|
|||||||
EditorGUILayout.PropertyField(_positionMode);
|
EditorGUILayout.PropertyField(_positionMode);
|
||||||
|
|
||||||
// Auto Scaling
|
// Auto Scaling
|
||||||
DrawAutoScaling(_autoScalingMode, targets.OfType<UIParticle>());
|
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.
|
// Target ParticleSystems.
|
||||||
EditorGUI.BeginChangeCheck();
|
EditorGUI.BeginChangeCheck();
|
||||||
EditorGUI.BeginDisabledGroup(targets.OfType<UIParticle>().Any(x => !x.canvas));
|
|
||||||
_ro.DoLayoutList();
|
_ro.DoLayoutList();
|
||||||
EditorGUI.EndDisabledGroup();
|
|
||||||
serializedObject.ApplyModifiedProperties();
|
serializedObject.ApplyModifiedProperties();
|
||||||
|
|
||||||
if (EditorGUI.EndChangeCheck())
|
if (EditorGUI.EndChangeCheck())
|
||||||
{
|
{
|
||||||
|
EditorApplication.QueuePlayerLoopUpdate();
|
||||||
foreach (var uip in targets.OfType<UIParticle>())
|
foreach (var uip in targets.OfType<UIParticle>())
|
||||||
{
|
{
|
||||||
uip.RefreshParticles(uip.particles);
|
uip.RefreshParticles(uip.particles);
|
||||||
@@ -288,7 +236,8 @@ namespace Coffee.UIExtensions
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Non-UI built-in shader is not supported.
|
// Non-UI built-in shader is not supported.
|
||||||
foreach (var mat in current.materials)
|
Profiler.BeginSample("(UIP:E) Non-UI built-in shader is not supported.");
|
||||||
|
foreach (var mat in s_TempMaterials)
|
||||||
{
|
{
|
||||||
if (!mat || !mat.shader) continue;
|
if (!mat || !mat.shader) continue;
|
||||||
var shader = mat.shader;
|
var shader = mat.shader;
|
||||||
@@ -301,15 +250,18 @@ namespace Coffee.UIExtensions
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Profiler.EndSample();
|
||||||
|
|
||||||
// Does the shader support UI masks?
|
// Does the shader support UI masks?
|
||||||
|
Profiler.BeginSample("(UIP:E) Does the shader support UI masks?");
|
||||||
if (current.maskable && current.GetComponentInParent<Mask>(false))
|
if (current.maskable && current.GetComponentInParent<Mask>(false))
|
||||||
{
|
{
|
||||||
foreach (var mat in current.materials)
|
foreach (var mat in s_TempMaterials)
|
||||||
{
|
{
|
||||||
if (!mat || !mat.shader) continue;
|
if (!mat || !mat.shader) continue;
|
||||||
var shader = mat.shader;
|
var shader = mat.shader;
|
||||||
if (s_Shaders.Contains(shader)) continue;
|
if (!s_Shaders.Add(shader)) continue;
|
||||||
s_Shaders.Add(shader);
|
|
||||||
foreach (var propName in s_MaskablePropertyNames)
|
foreach (var propName in s_MaskablePropertyNames)
|
||||||
{
|
{
|
||||||
if (mat.HasProperty(propName)) continue;
|
if (mat.HasProperty(propName)) continue;
|
||||||
@@ -323,15 +275,21 @@ namespace Coffee.UIExtensions
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
s_TempMaterials.Clear();
|
||||||
s_Shaders.Clear();
|
s_Shaders.Clear();
|
||||||
|
Profiler.EndSample();
|
||||||
|
|
||||||
// UIParticle for trail should be removed.
|
// UIParticle for trail should be removed.
|
||||||
var label = "This UIParticle component should be removed. The UIParticle for trails is no longer needed.";
|
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))
|
if (FixButton(current.m_IsTrail, label))
|
||||||
|
#pragma warning restore CS0612
|
||||||
{
|
{
|
||||||
DestroyUIParticle(current);
|
DestroyUIParticle(current);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if UNITY_2018 || UNITY_2019
|
||||||
|
// (2018, 2019) Check to use 'TEXCOORD*.zw' components as custom vertex stream.
|
||||||
var allPsRenderers = targets.OfType<UIParticle>()
|
var allPsRenderers = targets.OfType<UIParticle>()
|
||||||
.SelectMany(x => x.particles)
|
.SelectMany(x => x.particles)
|
||||||
.Where(x => x)
|
.Where(x => x)
|
||||||
@@ -357,14 +315,18 @@ namespace Coffee.UIExtensions
|
|||||||
s_Streams.Clear();
|
s_Streams.Clear();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
Profiler.EndSample();
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool IsBuiltInObject(Object obj)
|
private static bool IsBuiltInObject(Object obj)
|
||||||
{
|
{
|
||||||
return AssetDatabase.TryGetGUIDAndLocalFileIdentifier(obj, out var guid, out long _)
|
return AssetDatabase.IsMainAsset(obj)
|
||||||
&& Regex.IsMatch(guid, "^0{16}.0{15}$", RegexOptions.Compiled);
|
&& AssetDatabase.TryGetGUIDAndLocalFileIdentifier(obj, out var guid, out long _)
|
||||||
|
&& s_RegexBuiltInGuid.IsMatch(guid);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if UNITY_2018 || UNITY_2019
|
||||||
private static int GetUsedComponentCount(ParticleSystemVertexStream s)
|
private static int GetUsedComponentCount(ParticleSystemVertexStream s)
|
||||||
{
|
{
|
||||||
switch (s)
|
switch (s)
|
||||||
@@ -423,6 +385,7 @@ namespace Coffee.UIExtensions
|
|||||||
|
|
||||||
return 3;
|
return 3;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
private static bool DrawMeshSharing(SerializedProperty spMeshSharing, SerializedProperty spGroupId,
|
private static bool DrawMeshSharing(SerializedProperty spMeshSharing, SerializedProperty spGroupId,
|
||||||
SerializedProperty spGroupMaxId, bool showMax)
|
SerializedProperty spGroupMaxId, bool showMax)
|
||||||
@@ -454,7 +417,7 @@ namespace Coffee.UIExtensions
|
|||||||
{
|
{
|
||||||
EditorGUI.BeginDisabledGroup(true);
|
EditorGUI.BeginDisabledGroup(true);
|
||||||
var obj = UIParticleUpdater.GetPrimary(spGroupId.intValue);
|
var obj = UIParticleUpdater.GetPrimary(spGroupId.intValue);
|
||||||
EditorGUILayout.ObjectField("Primary", obj, typeof(UIParticle), false);
|
EditorGUILayout.ObjectField(s_ContentPrimary, obj, typeof(UIParticle), false);
|
||||||
EditorGUI.EndDisabledGroup();
|
EditorGUI.EndDisabledGroup();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -464,50 +427,9 @@ namespace Coffee.UIExtensions
|
|||||||
return showMax;
|
return showMax;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void DrawAutoScaling(SerializedProperty prop, IEnumerable<UIParticle> uiParticles)
|
private static void DrawAutoScaling(SerializedProperty prop)
|
||||||
{
|
{
|
||||||
var isTransformMode = prop.intValue == (int)UIParticle.AutoScalingMode.Transform;
|
|
||||||
EditorGUI.BeginChangeCheck();
|
|
||||||
EditorGUILayout.PropertyField(prop);
|
EditorGUILayout.PropertyField(prop);
|
||||||
if (!EditorGUI.EndChangeCheck() || !isTransformMode) return;
|
|
||||||
|
|
||||||
// on changed true->false, reset scale.
|
|
||||||
EditorApplication.delayCall += () =>
|
|
||||||
{
|
|
||||||
foreach (var uip in uiParticles)
|
|
||||||
{
|
|
||||||
if (!uip) continue;
|
|
||||||
uip.transform.localScale = Vector3.one;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void WindowFunction(Object target, SceneView sceneView)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
if (s_SerializedObject == null || !s_SerializedObject.targetObject) return;
|
|
||||||
var uiParticles = s_SerializedObject.targetObjects.OfType<UIParticle>();
|
|
||||||
if (uiParticles.Any(x => !x || !x.canvas)) return;
|
|
||||||
|
|
||||||
s_SerializedObject.Update();
|
|
||||||
using (new EditorGUILayout.VerticalScope(GUILayout.Width(220f)))
|
|
||||||
{
|
|
||||||
var labelWidth = EditorGUIUtility.labelWidth;
|
|
||||||
EditorGUIUtility.labelWidth = 100;
|
|
||||||
EditorGUILayout.PropertyField(s_SerializedObject.FindProperty("m_Enabled"));
|
|
||||||
s_XYZMode = DrawFloatOrVector3Field(s_SerializedObject.FindProperty("m_Scale3D"), s_XYZMode);
|
|
||||||
EditorGUILayout.PropertyField(s_SerializedObject.FindProperty("m_PositionMode"));
|
|
||||||
DrawAutoScaling(s_SerializedObject.FindProperty("m_AutoScalingMode"), uiParticles);
|
|
||||||
EditorGUIUtility.labelWidth = labelWidth;
|
|
||||||
}
|
|
||||||
|
|
||||||
s_SerializedObject.ApplyModifiedProperties();
|
|
||||||
}
|
|
||||||
catch
|
|
||||||
{
|
|
||||||
// ignored
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void DestroyUIParticle(UIParticle p, bool ignoreCurrent = false)
|
private void DestroyUIParticle(UIParticle p, bool ignoreCurrent = false)
|
||||||
@@ -523,7 +445,7 @@ namespace Coffee.UIExtensions
|
|||||||
if (stage != null && stage.scene.isLoaded)
|
if (stage != null && stage.scene.isLoaded)
|
||||||
{
|
{
|
||||||
#if UNITY_2020_1_OR_NEWER
|
#if UNITY_2020_1_OR_NEWER
|
||||||
string prefabAssetPath = stage.assetPath;
|
var prefabAssetPath = stage.assetPath;
|
||||||
#else
|
#else
|
||||||
var prefabAssetPath = stage.prefabAssetPath;
|
var prefabAssetPath = stage.prefabAssetPath;
|
||||||
#endif
|
#endif
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
fileFormatVersion: 2
|
fileFormatVersion: 2
|
||||||
guid: ca0fd7c7ead2c49b1ae139b7963de126
|
guid: 7a55e246f37df405bac88eac692e3a86
|
||||||
folderAsset: yes
|
folderAsset: yes
|
||||||
DefaultImporter:
|
DefaultImporter:
|
||||||
externalObjects: {}
|
externalObjects: {}
|
||||||
BIN
Icons/UIParticleIcon.png
Normal file
BIN
Icons/UIParticleIcon.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 418 B |
@@ -1,9 +1,9 @@
|
|||||||
fileFormatVersion: 2
|
fileFormatVersion: 2
|
||||||
guid: fc4e1d816001842709cf8a393c69dd14
|
guid: 5f0675613942149309588d556e33d990
|
||||||
TextureImporter:
|
TextureImporter:
|
||||||
fileIDToRecycleName: {}
|
internalIDToNameTable: []
|
||||||
externalObjects: {}
|
externalObjects: {}
|
||||||
serializedVersion: 9
|
serializedVersion: 12
|
||||||
mipmaps:
|
mipmaps:
|
||||||
mipMapMode: 0
|
mipMapMode: 0
|
||||||
enableMipMap: 0
|
enableMipMap: 0
|
||||||
@@ -20,27 +20,30 @@ TextureImporter:
|
|||||||
externalNormalMap: 0
|
externalNormalMap: 0
|
||||||
heightScale: 0.25
|
heightScale: 0.25
|
||||||
normalMapFilter: 0
|
normalMapFilter: 0
|
||||||
|
flipGreenChannel: 0
|
||||||
isReadable: 0
|
isReadable: 0
|
||||||
streamingMipmaps: 0
|
streamingMipmaps: 0
|
||||||
streamingMipmapsPriority: 0
|
streamingMipmapsPriority: 0
|
||||||
|
vTOnly: 0
|
||||||
|
ignoreMipmapLimit: 0
|
||||||
grayScaleToAlpha: 0
|
grayScaleToAlpha: 0
|
||||||
generateCubemap: 6
|
generateCubemap: 6
|
||||||
cubemapConvolution: 0
|
cubemapConvolution: 0
|
||||||
seamlessCubemap: 0
|
seamlessCubemap: 0
|
||||||
textureFormat: -1
|
textureFormat: 1
|
||||||
maxTextureSize: 2048
|
maxTextureSize: 2048
|
||||||
textureSettings:
|
textureSettings:
|
||||||
serializedVersion: 2
|
serializedVersion: 2
|
||||||
filterMode: -1
|
filterMode: 1
|
||||||
aniso: -1
|
aniso: 1
|
||||||
mipBias: -100
|
mipBias: 0
|
||||||
wrapU: 1
|
wrapU: 1
|
||||||
wrapV: 1
|
wrapV: 1
|
||||||
wrapW: 1
|
wrapW: 0
|
||||||
nPOTScale: 0
|
nPOTScale: 0
|
||||||
lightmap: 0
|
lightmap: 0
|
||||||
compressionQuality: 50
|
compressionQuality: 50
|
||||||
spriteMode: 1
|
spriteMode: 0
|
||||||
spriteExtrude: 1
|
spriteExtrude: 1
|
||||||
spriteMeshType: 1
|
spriteMeshType: 1
|
||||||
alignment: 0
|
alignment: 0
|
||||||
@@ -51,16 +54,22 @@ TextureImporter:
|
|||||||
alphaUsage: 1
|
alphaUsage: 1
|
||||||
alphaIsTransparency: 1
|
alphaIsTransparency: 1
|
||||||
spriteTessellationDetail: -1
|
spriteTessellationDetail: -1
|
||||||
textureType: 8
|
textureType: 2
|
||||||
textureShape: 1
|
textureShape: 1
|
||||||
singleChannelComponent: 0
|
singleChannelComponent: 0
|
||||||
|
flipbookRows: 1
|
||||||
|
flipbookColumns: 1
|
||||||
maxTextureSizeSet: 0
|
maxTextureSizeSet: 0
|
||||||
compressionQualitySet: 0
|
compressionQualitySet: 0
|
||||||
textureFormatSet: 0
|
textureFormatSet: 0
|
||||||
|
ignorePngGamma: 0
|
||||||
|
applyGammaDecoding: 0
|
||||||
|
swizzle: 50462976
|
||||||
|
cookieLightType: 0
|
||||||
platformSettings:
|
platformSettings:
|
||||||
- serializedVersion: 2
|
- serializedVersion: 3
|
||||||
buildTarget: DefaultTexturePlatform
|
buildTarget: DefaultTexturePlatform
|
||||||
maxTextureSize: 2048
|
maxTextureSize: 64
|
||||||
resizeAlgorithm: 0
|
resizeAlgorithm: 0
|
||||||
textureFormat: -1
|
textureFormat: -1
|
||||||
textureCompression: 1
|
textureCompression: 1
|
||||||
@@ -68,8 +77,10 @@ TextureImporter:
|
|||||||
crunchedCompression: 0
|
crunchedCompression: 0
|
||||||
allowsAlphaSplitting: 0
|
allowsAlphaSplitting: 0
|
||||||
overridden: 0
|
overridden: 0
|
||||||
|
ignorePlatformSupport: 0
|
||||||
androidETC2FallbackOverride: 0
|
androidETC2FallbackOverride: 0
|
||||||
- serializedVersion: 2
|
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||||
|
- serializedVersion: 3
|
||||||
buildTarget: Standalone
|
buildTarget: Standalone
|
||||||
maxTextureSize: 2048
|
maxTextureSize: 2048
|
||||||
resizeAlgorithm: 0
|
resizeAlgorithm: 0
|
||||||
@@ -79,31 +90,11 @@ TextureImporter:
|
|||||||
crunchedCompression: 0
|
crunchedCompression: 0
|
||||||
allowsAlphaSplitting: 0
|
allowsAlphaSplitting: 0
|
||||||
overridden: 0
|
overridden: 0
|
||||||
|
ignorePlatformSupport: 0
|
||||||
androidETC2FallbackOverride: 0
|
androidETC2FallbackOverride: 0
|
||||||
- serializedVersion: 2
|
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||||
buildTarget: iPhone
|
- serializedVersion: 3
|
||||||
maxTextureSize: 2048
|
buildTarget: Server
|
||||||
resizeAlgorithm: 0
|
|
||||||
textureFormat: -1
|
|
||||||
textureCompression: 1
|
|
||||||
compressionQuality: 50
|
|
||||||
crunchedCompression: 0
|
|
||||||
allowsAlphaSplitting: 0
|
|
||||||
overridden: 0
|
|
||||||
androidETC2FallbackOverride: 0
|
|
||||||
- serializedVersion: 2
|
|
||||||
buildTarget: Android
|
|
||||||
maxTextureSize: 2048
|
|
||||||
resizeAlgorithm: 0
|
|
||||||
textureFormat: -1
|
|
||||||
textureCompression: 1
|
|
||||||
compressionQuality: 50
|
|
||||||
crunchedCompression: 0
|
|
||||||
allowsAlphaSplitting: 0
|
|
||||||
overridden: 0
|
|
||||||
androidETC2FallbackOverride: 0
|
|
||||||
- serializedVersion: 2
|
|
||||||
buildTarget: WebGL
|
|
||||||
maxTextureSize: 2048
|
maxTextureSize: 2048
|
||||||
resizeAlgorithm: 0
|
resizeAlgorithm: 0
|
||||||
textureFormat: -1
|
textureFormat: -1
|
||||||
@@ -112,21 +103,25 @@ TextureImporter:
|
|||||||
crunchedCompression: 0
|
crunchedCompression: 0
|
||||||
allowsAlphaSplitting: 0
|
allowsAlphaSplitting: 0
|
||||||
overridden: 0
|
overridden: 0
|
||||||
|
ignorePlatformSupport: 0
|
||||||
androidETC2FallbackOverride: 0
|
androidETC2FallbackOverride: 0
|
||||||
|
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||||
spriteSheet:
|
spriteSheet:
|
||||||
serializedVersion: 2
|
serializedVersion: 2
|
||||||
sprites: []
|
sprites: []
|
||||||
outline: []
|
outline: []
|
||||||
physicsShape: []
|
physicsShape: []
|
||||||
bones: []
|
bones: []
|
||||||
spriteID: de8a1691f8aae4be18d66008040aa1a7
|
spriteID:
|
||||||
|
internalID: 0
|
||||||
vertices: []
|
vertices: []
|
||||||
indices:
|
indices:
|
||||||
edges: []
|
edges: []
|
||||||
weights: []
|
weights: []
|
||||||
spritePackingTag:
|
secondaryTextures: []
|
||||||
|
nameFileIdTable: {}
|
||||||
|
mipmapLimitGroupName:
|
||||||
pSDRemoveMatte: 0
|
pSDRemoveMatte: 0
|
||||||
pSDShowRemoveMatteOption: 0
|
|
||||||
userData:
|
userData:
|
||||||
assetBundleName:
|
assetBundleName:
|
||||||
assetBundleVariant:
|
assetBundleVariant:
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
Copyright 2018-2023 mob-sakai
|
Copyright 2018-2024 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:
|
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:
|
||||||
|
|
||||||
|
|||||||
526
README.md
526
README.md
@@ -1,218 +1,228 @@
|
|||||||
Particle Effect For UGUI (UI Particle)
|
# <img alt="UIParticleIcon" src="https://github.com/mob-sakai/ParticleEffectForUGUI/assets/12690315/d76e105e-a840-4f61-a1f6-8cf311c0812d" width="26"/> Particle Effect For UGUI (UI Particle) <!-- omit in toc -->
|
||||||
===
|
|
||||||
|
|
||||||
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://openupm.com/packages/com.coffee.ui-particle/)
|
[](https://openupm.com/packages/com.coffee.ui-particle/)
|
||||||
[](https://github.com/mob-sakai/ParticleEffectForUGUI/releases)
|
[](https://github.com/mob-sakai/ParticleEffectForUGUI/releases)
|
||||||
[)](https://github.com/mob-sakai/ParticleEffectForUGUI/releases)
|
[](https://github.com/mob-sakai/ParticleEffectForUGUI/blob/main/LICENSE.md)
|
||||||
[](https://github.com/mob-sakai/ParticleEffectForUGUI/releases) [](https://github.com/mob-sakai/ParticleEffectForUGUI/blob/master/LICENSE.txt)
|

|
||||||
|

|
||||||
|

|
||||||
|

|
||||||
[](http://makeapullrequest.com)
|
[](http://makeapullrequest.com)
|
||||||
|
[](https://github.com/mob-sakai/ParticleEffectForUGUI/subscription)
|
||||||
|
[](https://twitter.com/intent/follow?screen_name=mob_sakai)
|
||||||
|
|
||||||
|
<< [📝 Description](#-description-) | [📌 Key Features](#-key-features) | [🎮 Demo](#-demo) | [⚙ Installation](#-installation) | [🚀 Usage](#-usage) | [🛠 Development Note](#-development-note) | [🤝 Contributing](#-contributing) >>
|
||||||
|
|
||||||
<< [Description](#Description) | [Demo](#demo) | [Installation](#installation) | [Usage](#usage) | [Development Note](#development-note) | [Change log](https://github.com/mob-sakai/ParticleEffectForUGUI/blob/upm/CHANGELOG.md) >>
|
## 📝 Description <!-- omit in toc -->
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<br><br><br><br>
|
|
||||||
|
|
||||||
## Description
|
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
This plugin uses new APIs `MeshBake/MashTrailBake` (added with Unity 2018.2) to render particles by CanvasRenderer.
|
This package uses the new APIs `MeshBake/MeshTrailBake` (introduced in Unity 2018.2) to render particles through `CanvasRenderer`.
|
||||||
You can mask and sort particles for uGUI without Camera, RenderTexture, Canvas.
|
You can render, mask, and sort your `ParticleSystems` for UI without the need for an additional `Camera`, `RenderTexture`, or `Canvas`.
|
||||||
|
|
||||||
Compares this "Baking mesh" approach with the conventional approach:
|
- [📌 Key Features](#-key-features)
|
||||||
[Performance test results](https://github.com/mob-sakai/ParticleEffectForUGUI/issues/193#issuecomment-1160028374)
|
- [🎮 Demo](#-demo)
|
||||||
|
- [⚙ Installation](#-installation)
|
||||||
|Approach|Good|Bad|Screenshot|
|
- [Install via OpenUPM](#install-via-openupm)
|
||||||
|-|-|-|-|
|
- [Install via UPM (with Package Manager UI)](#install-via-upm-with-package-manager-ui)
|
||||||
|Baking mesh<br>**\(UIParticle\)**|Rendered as is.<br>Maskable.<br>Sortable.<br>Less objects.|[Not support `TEXCOORD*.zw` components for custom vertex stream](https://github.com/mob-sakai/ParticleEffectForUGUI/issues/191#issuecomment-1043409186)|<img src="https://user-images.githubusercontent.com/12690315/41765089-0302b9a2-763e-11e8-88b3-b6ffa306bbb0.gif" width="500px">|
|
- [Install via UPM (Manually)](#install-via-upm-manually)
|
||||||
|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">|
|
- [Install as Embedded Package](#install-as-embedded-package)
|
||||||
|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">|
|
- [🚀 Usage](#-usage)
|
||||||
|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">|
|
- [Component: UIParticle](#component-uiparticle)
|
||||||
|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">|
|
- [Basic Usage](#basic-usage)
|
||||||
|
- [Usage with Your Existing ParticleSystem Prefab](#usage-with-your-existing-particlesystem-prefab)
|
||||||
|Approach|FPS on Editor|FPS on iPhone6|FPS on Xperia XZ|
|
- [Usage with `Mask` or `RectMask2D` Component](#usage-with-mask-or-rectmask2d-component)
|
||||||
|--|--|--|--|
|
- [Usage with Script](#usage-with-script)
|
||||||
|Particle System|43|57|22|
|
- [Component: UIParticleAttractor](#component-uiparticleattractor)
|
||||||
|UIParticleSystem|4|3|0 (unmeasurable)|
|
- [🛠 Development Note](#-development-note)
|
||||||
|Sorting By Canvas|43|44|18|
|
- [Compares the Baking mesh approach with the conventional approach](#compares-the-baking-mesh-approach-with-the-conventional-approach)
|
||||||
|UIParticle|17|12|4|
|
- [Performance test results](#performance-test-results)
|
||||||
|UIParticle with MeshSharing|44|45|30|
|
- [🔍 FAQ: Why Are My UIParticles Not Displayed Correctly?](#-faq-why-are-my-uiparticles-not-displayed-correctly)
|
||||||
|
- [Shader Limitation](#shader-limitation)
|
||||||
|
- [Built-in shaders are not supported](#built-in-shaders-are-not-supported)
|
||||||
|
- [(Unity 2018 or 2019) UV.zw components will be discarded](#unity-2018-or-2019-uvzw-components-will-be-discarded)
|
||||||
|
- [(Unity 2018 or 2019) Custom vertex streams](#unity-2018-or-2019-custom-vertex-streams)
|
||||||
|
- [Overheads](#overheads)
|
||||||
|
- [How to Make a Custom Shader to Support `Mask` and `RectMask2D` Component](#how-to-make-a-custom-shader-to-support-mask-and-rectmask2d-component)
|
||||||
|
- [🤝 Contributing](#-contributing)
|
||||||
|
- [Issues](#issues)
|
||||||
|
- [Pull Requests](#pull-requests)
|
||||||
|
- [Support](#support)
|
||||||
|
- [License](#license)
|
||||||
|
- [Author](#author)
|
||||||
|
- [See Also](#see-also)
|
||||||
|
|
||||||
<br><br>
|
<br><br>
|
||||||
|
|
||||||
#### Features
|
## 📌 Key Features
|
||||||
|
|
||||||
* Easy to use: the package is out-of-the-box
|
* **Easy to use:** The package is ready to use out of the box.
|
||||||
* Sort particle effects and UI by sibling index
|
* **Sortable:** Sort particle effects and other UI elements by sibling index.
|
||||||
* No Camera, RenderTexture or Canvas are required
|
* **Maskable:** Supports `Mask` or `RectMask2D`.
|
||||||
* Masking by Mask or RectMask2D
|
* **No extra components required:** No need for an additional `Camera`, `RenderTexture`, or `Canvas`.
|
||||||
* Support Trail module
|
* **Trail module support:** Fully supports the Trail module.
|
||||||
* Support CanvasGroup alpha
|
* **CanvasGroup alpha support:** Integrates with `CanvasGroup` alpha.
|
||||||
* No allocations
|
* **No allocations:** Efficiently renders particles without allocations.
|
||||||
* Support overlay, camera space and world space
|
* **Any canvas render mode support:** Works with overlay, camera space, and world space.
|
||||||
* Support Universal Render Pipeline (URP) and High Definition Render Pipeline (HDRP)
|
* **Any Render pipeline support:** Compatible with Universal Render Pipeline (URP) and High Definition Render Pipeline (HDRP).
|
||||||
* Support disabling `Enter Play Mode Options > Reload Domain`
|
* **Disabling domain reload support:** Supports disabling `Enter Play Mode Options > Reload Domain`.
|
||||||
* Support changing material property with AnimationClip (AnimatableProperty)
|
* **Animatable material properties:** Supports changing material properties with AnimationClip (AnimatableProperty).
|
||||||

|

|
||||||
* [4.0.0+] Support 8+ materials
|
* **Multiple materials:** Supports 8+ materials.
|
||||||
* [4.0.0+] Correct world space particle position when changing window size for standalone platforms (Windows, MacOSX and Linux)
|
* **Correct positioning:** Adjusts world space particle positions correctly when changing window size for standalone platforms (Windows, MacOSX, and Linux).
|
||||||
* [4.0.0+] Adaptive scaling for UI
|
* **Adaptive scaling:** Provides adaptive scaling for UI (AutoScalingMode).
|
||||||
* [4.0.0+] Mesh sharing group to improve performance
|
* **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"/>
|
||||||
* [4.0.0+] Particle attractor component
|
* **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"/>
|
||||||
* [4.1.0+] Relative/Absolute particle position mode
|
* **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.
|
||||||
|

|
||||||
|
|
||||||
|
<br><br>
|
||||||
|
|
||||||
<br><br><br><br>
|
## 🎮 Demo
|
||||||
|
|
||||||
## Demo
|
* [WebGL Demo](https://mob-sakai.github.io/demos/UIParticle_Demo/index.html)
|
||||||
|
|
||||||
* [WebGL Demo](https://mob-sakai.github.io/demos/UIParticle_Demo/index.html)
|
|
||||||
> 
|
> 
|
||||||
|
|
||||||
* [WebGL Demo (Cartoon FX & War FX)](https://mob-sakai.github.io/Demos/ParticleEffectForUGUI_CFX)
|
* [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
|
* [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
|
[CFX]: https://assetstore.unity.com/packages/vfx/particles/cartoon-fx-free-109565
|
||||||
|
|
||||||
[WFX]: https://assetstore.unity.com/packages/vfx/particles/war-fx-5669
|
[WFX]: https://assetstore.unity.com/packages/vfx/particles/war-fx-5669
|
||||||
|
|
||||||
[JMO]: https://assetstore.unity.com/publishers/1669
|
[JMO]: https://assetstore.unity.com/publishers/1669
|
||||||
|
|
||||||
|
<br><br>
|
||||||
|
|
||||||
<br><br><br><br>
|
## ⚙ Installation
|
||||||
|
|
||||||
## Installation
|
_This package requires **Unity 2018.3 or later**._
|
||||||
|
|
||||||
### Requirement
|
#### Install via OpenUPM
|
||||||
|
|
||||||
Unity 2018.2 or later
|
- 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.9.0
|
||||||
|
```
|
||||||
|
|
||||||
### Install via OpenUPM
|
#### Install via UPM (with Package Manager UI)
|
||||||
|
|
||||||
This package is available on [OpenUPM](https://openupm.com).
|
- Click `Window > Package Manager` to open Package Manager UI.
|
||||||
It's recommended to install it via [openupm-cli](https://github.com/openupm/openupm-cli).
|
- Click `+ > Add package from git URL...` and input the repository URL: `https://github.com/mob-sakai/ParticleEffectForUGUI.git`
|
||||||
```
|

|
||||||
openupm add com.coffee.ui-particle
|
- To update the package, change suffix `#{version}` to the target version.
|
||||||
```
|
- e.g. `https://github.com/mob-sakai/ParticleEffectForUGUI.git#4.9.0`
|
||||||
|
|
||||||
### Install via Package Manager Window (using Git URL)
|
#### Install via UPM (Manually)
|
||||||
|
|
||||||
1. Select `Window/Package Manager` menu to open `Package Manager` window.
|
- Open the `Packages/manifest.json` file in your project. Then add this package somewhere in the `dependencies` block:
|
||||||
2. Click `+` and `Install package from git URL...`
|
```json
|
||||||

|
{
|
||||||
3. Input `https://github.com/mob-sakai/ParticleEffectForUGUI.git` and click `Install`
|
"dependencies": {
|
||||||

|
"com.coffee.ui-particle": "https://github.com/mob-sakai/ParticleEffectForUGUI.git",
|
||||||
|
...
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
- To update the package, change suffix `#{version}` to the target version.
|
||||||
|
- e.g. `"com.coffee.ui-particle": "https://github.com/mob-sakai/ParticleEffectForUGUI.git#4.9.0",`
|
||||||
|
|
||||||
Or, use [UpmGitExtension](https://github.com/mob-sakai/UpmGitExtension) to install and update the package.
|
#### Install as Embedded Package
|
||||||
|
|
||||||
### Install via manifest.json (using Git URL)
|
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.
|
||||||
1. Open `Packages/manifest.json` in your project.
|

|
||||||
2. Add this line below `"dependencies": {`
|
- If you want to fix bugs or add features, install it as an embedded package.
|
||||||
* `"com.coffee.ui-particle": "https://github.com/mob-sakai/ParticleEffectForUGUI.git",`
|
- To update the package, you need to re-download it and replace the contents.
|
||||||

|
|
||||||
3. To update the package, change suffix `#{version}`.
|
|
||||||
* `"com.coffee.ui-particle": "https://github.com/mob-sakai/ParticleEffectForUGUI.git#4.2.0",`
|
|
||||||
|
|
||||||
### Install as an embed package
|
|
||||||
|
|
||||||
1. Download a source code zip file from [Releases](https://github.com/mob-sakai/ParticleEffectForUGUI/releases) page
|
|
||||||
2. Extract it and place it under `Packages` directory in your 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
|
|
||||||

|
|
||||||
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.
|
|
||||||
|
|
||||||

|
|
||||||
|
|
||||||
| Properties | Description |
|
|
||||||
| -- | -- |
|
|
||||||
| Maskable | Does this graphic allow masking. |
|
|
||||||
| 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. |
|
|
||||||
| Mesh Sharing | Particle simulation results are shared within the same group.<br>A large number of the same effects can be displayed with a small load.<br>When the `Random` toggle is enabled, it will be grouped randomaly. |
|
|
||||||
| Position Mode | **Absolute:** Emit from the world position of the `ParticleSystem`.<br>**Relative:** Emit from the scaled position of the `ParticleSystem`. |
|
|
||||||
| Auto Scaling | Transform.lossyScale (=world scale) will be set to `(1, 1, 1)` on update.<br>It prevents the root-Canvas scale from affecting the hierarchy-scaled `ParticleSystem`. |
|
|
||||||
| Rendering Order | The ParticleSystem list to be rendered.<br>You can change the order and the materials. |
|
|
||||||
|
|
||||||
NOTE: Press `Refresh` button to reconstruct rendering order based on children ParticleSystem's sorting order and z position.
|
|
||||||
|
|
||||||
<br><br>
|
<br><br>
|
||||||
|
|
||||||
### Basically usage
|
## 🚀 Usage
|
||||||
|
|
||||||
1. Select `Game Object/UI/ParticleSystem` to create UIParticle with a ParticleSystem.
|
### Component: UIParticle
|
||||||

|
|
||||||
2. Adjust the ParticleSystem as you like.
|
`UIParticle` controls the ParticleSystems that are attached to its own game objects and child game objects.
|
||||||

|
|
||||||
|

|
||||||
|
|
||||||
|
- **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.
|
||||||
|
|
||||||
<br><br>
|
<br><br>
|
||||||
|
|
||||||
### With your existing ParticleSystem prefab
|
### Basic Usage
|
||||||
|
|
||||||
1. Select `Game Object/UI/ParticleSystem (Empty)` to create UIParticle.
|
1. Select `GameObject/UI/ParticleSystem` to create UIParticle with a ParticleSystem.
|
||||||

|

|
||||||
2. Drag & drop your ParticleSystem prefab on UIParticle.
|
2. Adjust the ParticleSystem as you like.
|
||||||

|

|
||||||
|
|
||||||
<br><br>
|
<br>
|
||||||
|
|
||||||
### With `Mask` or `RectMask2D` component
|
### Usage with Your Existing ParticleSystem Prefab
|
||||||
|
|
||||||
If you want to mask particles, set a stencil supported shader (such as `UI/UIAdditive`) to material for ParticleSystem.
|
1. Select `GameObject/UI/ParticleSystem (Empty)` to create UIParticle.
|
||||||
If you use some custom shaders, see [How to make a custom shader to support Mask/RectMask2D component](#how-to-make-a-custom-shader-to-support-maskrectmask2d-component) section.
|

|
||||||
|
2. Drag and drop your ParticleSystem prefab onto UIParticle.
|
||||||
|

|
||||||
|
|
||||||
|
<br>
|
||||||
|
|
||||||
|
### Usage 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.
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
|
|
||||||
<br><br>
|
<br><br>
|
||||||
|
|
||||||
### Script usage
|
### Usage with Script
|
||||||
|
|
||||||
```cs
|
```cs
|
||||||
// Instant ParticleSystem prefab with UIParticle on runtime.
|
// Instantiate ParticleSystem prefab with UIParticle on runtime.
|
||||||
var go = GameObject.Instantiate(prefab);
|
var go = GameObject.Instantiate(prefab);
|
||||||
var uiParticle = go.AddComponent<UIParticle>();
|
var uiParticle = go.AddComponent<UIParticle>();
|
||||||
|
uiParticle.scale = 100;
|
||||||
|
|
||||||
// Control by ParticleSystem.
|
// Control by ParticleSystem.
|
||||||
particleSystem.Play();
|
particleSystem.Play();
|
||||||
@@ -225,50 +235,115 @@ uiParticle.Stop();
|
|||||||
|
|
||||||
<br><br>
|
<br><br>
|
||||||
|
|
||||||
### UIParticleAttractor component
|
### Component: UIParticleAttractor
|
||||||
|
|
||||||
`UIParticleAttractor` attracts particles generated by the specified ParticleSystem.
|
`UIParticleAttractor` attracts particles generated by the specified ParticleSystem.
|
||||||
|
|
||||||

|

|
||||||

|

|
||||||
|
|
||||||
| Properties | Description |
|
- **Particle Systems**: Attracts particles generated by the specified ParticleSystems.
|
||||||
| -- | -- |
|
- **Destination Radius**: Once the particle is within the radius, the particle lifetime will become 0, and `OnAttracted`
|
||||||
| Particle System | Attracts particles generated by the specified particle system. |
|
will be called.
|
||||||
| Distination 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.
|
||||||
| Delay Rate | Delay to start attracting.<br>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
|
||||||
| Max Speed | Maximum speed of attracting.<br> If this value is too small, attracting may not be completed by the end of the lifetime and `OnAttracted` may not be called. |
|
the lifetime, and `OnAttracted` may not be called.
|
||||||
| Movement | Attracting movement type. (Linear, Smooth, Sphere) |
|
- **Movement**: Attracting movement type. (`Linear`, `Smooth`, `Sphere`)
|
||||||
| Update Mode | **Normal:** Update with scaled delta time.<br>**Unscaled Time:** Update with unscaled delta time. |
|
- **Update Mode**: Update mode.
|
||||||
| OnAttracted | An event called when attracting is complete (per particle). |
|
- **Normal:** Update with scaled delta time.
|
||||||
|
- **Unscaled Time:** Update with unscaled delta time.
|
||||||
|
- **OnAttracted**: An event called when attracting is complete (per particle).
|
||||||
|
|
||||||
<br><br><br><br>
|
<br><br>
|
||||||
|
|
||||||
## Development Note
|
## 🛠 Development Note
|
||||||
|
|
||||||
### FAQ: Why are my particle effects not displayed correctly?
|
### Compares the Baking mesh approach with the conventional approach
|
||||||
|
|
||||||
|
- **Baking mesh approach (=UIParticle)**
|
||||||
|

|
||||||
|
- ✅ Rendered as is.
|
||||||
|
- ✅ Maskable.
|
||||||
|
- ✅ Sortable.
|
||||||
|
- ✅ Less objects.
|
||||||
|
|
||||||
|
- **Do nothing (=Plain ParticleSystem)**
|
||||||
|

|
||||||
|
- ✅ Rendered as is.
|
||||||
|
- ❌ Looks like a glitch.
|
||||||
|
- ❌ Not maskable.
|
||||||
|
- ❌ Not sortable.
|
||||||
|
|
||||||
|
- **Convert particle to UIVertex (=[UIParticleSystem][UIParticleSystem])**
|
||||||
|

|
||||||
|
- ✅ 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 )**
|
||||||
|

|
||||||
|
- ✅ Rendered as is.
|
||||||
|
- ✅ Sortable.
|
||||||
|
- ❌ You must to manage sorting orders.
|
||||||
|
- ❌ Not maskable.
|
||||||
|
- ❌ More batches.
|
||||||
|
- ❌ Requires Canvas.
|
||||||
|
|
||||||
|
- **Use RenderTexture**
|
||||||
|

|
||||||
|
- ✅ 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:
|
If `ParticleSystem` alone displays particles correctly but `UIParticle` does not, please check the following points:
|
||||||
|
|
||||||
* [Shader Limitation](https://github.com/mob-sakai/ParticleEffectForUGUI#shader-limitation)
|
- [Shader Limitation](#shader-limitation)
|
||||||
* Most cases can be solved by using `UI/Additive` or `UI/Default`.
|
- `UIParticle` does not support all built-in shaders except for `UI/Default`.
|
||||||
* Particles are masked
|
- Most cases can be solved by using `UI/Additive` or `UI/Default`.
|
||||||
* `UIParticle` is maskable.
|
- Particles are not masked
|
||||||
* Set `Mask` or `RectMask2D` component properly.
|
- `UIParticle` is maskable.
|
||||||
* Particles are too small
|
- Set `Mask` or `RectMask2D` component properly.
|
||||||
* If particles are small enough, they will not appear on the screen.
|
- [Use maskable/clipable shader](#how-to-make-a-custom-shader-to-support-maskrectmask2d-component) (such
|
||||||
* Increase the `Scale` value.
|
as `UI/Additive` or `UI/Default`)
|
||||||
* If you don't want to change the apparent size depending on the resolution, try `Auto Scaling` option.
|
- Particles are too small
|
||||||
* Particles are too many
|
- If particles are small enough, they will not appear on the screen.
|
||||||
* No more than 65535 vertices can be displayed (for mesh combination limitations).
|
- Increase the `Scale` value.
|
||||||
* Please set `Emission` module and `Max Particles` of ParticleSystem properly.
|
- If you don't want to change the apparent size depending on the resolution, try the `Auto Scaling` option.
|
||||||
* Particles are emitted off-screen.
|
- Particles are too many
|
||||||
* When `Position Mode = Relative`, particles are emitted from scaled position of the ParticleSystem, not from the screen point of the ParticleSystem.
|
- No more than 65535 vertices can be displayed (for mesh combination limitations).
|
||||||
* Place the ParticleSystem in the proper position or try `Position Mode = Absolute`.
|
- Please set `Emission` module and `Max Particles` of ParticleSystem properly.
|
||||||
* Attaching `UIParticle` to the same object as `ParticleSystem`
|
- Particles are emitted off-screen.
|
||||||
* `Transform.localScale` will be overridden by `Auto Scaling` option.
|
- When `Position Mode = Relative`, particles are emitted from the scaled position of the ParticleSystem, not from
|
||||||
* It is recommended to place `ParticleSystem` under `UIParticle`.
|
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>
|
<br>
|
||||||
|
|
||||||
@@ -282,35 +357,37 @@ The use of UI shaders is recommended.
|
|||||||
|
|
||||||
#### Built-in shaders are not supported
|
#### Built-in shaders are not supported
|
||||||
|
|
||||||
UIParticle does not support all built-in shaders except for `UI/Default`.
|
`UIParticle` does not support all built-in shaders except for `UI/Default`.
|
||||||
If their use is detected, an error is displayed in the inspector.
|
If their use is detected, an error is displayed in the inspector.
|
||||||
Use UI shaders instead.
|
Use UI shaders instead.
|
||||||
|
|
||||||
#### (2019.4 or earlier) UV.zw components will be discarded
|
#### (Unity 2018 or 2019) UV.zw components will be discarded
|
||||||
|
|
||||||
UIParticleRenderer renders the particles based on UIVertex.
|
UIParticleRenderer renders the particles based on UIVertex.
|
||||||
Therefore, only xy components is available for each UV in the shader. (zw components will be discarded).
|
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.
|
So unfortunately, UIParticles will not work well with some shaders.
|
||||||
|
|
||||||
#### (2019.4 or earlier) Custom vertex streams
|
#### (Unity 2018 or 2019) Custom vertex streams
|
||||||
|
|
||||||
When using custom vertex streams, you can fill zw components with "unnecessary" data.
|
When using custom vertex streams, you can fill zw components with "unnecessary" data.
|
||||||
https://github.com/mob-sakai/ParticleEffectForUGUI/issues/191
|
Refer to [this issue](https://github.com/mob-sakai/ParticleEffectForUGUI/issues/191) for more information.
|
||||||
|
|
||||||
|
|
||||||
<br>
|
<br>
|
||||||
|
|
||||||
### Overheads
|
### Overheads
|
||||||
|
|
||||||
UIParticle has some overheads and the batching depends on uGUI.
|
UIParticle has some overheads, and the batching depends on uGUI.
|
||||||
When improving performance, keep the following in mind:
|
When improving performance, keep the following in mind:
|
||||||
- If you are displaying a large number of the same effect, consider `Mesh Sharing` feature in [UIParticle Component](#uiparticle-component).
|
|
||||||
- If you don't like the uniform output, consider `Random Group` feature.
|
|
||||||

|
|
||||||
- If you are using multiple materials, you will have more draw calls.
|
|
||||||
- Consider single material, atlasing the sprites, and using `Sprite` mode in the `Texture Sheet Animation` module in ParticleSystem.
|
|
||||||
|
|
||||||
### How to make a custom shader to support Mask/RectMask2D component
|
- 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.
|
||||||
|

|
||||||
|
- 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` and `RectMask2D` Component
|
||||||
|
|
||||||
<details>
|
<details>
|
||||||
<summary>Shader tips</summary>
|
<summary>Shader tips</summary>
|
||||||
@@ -402,54 +479,49 @@ Shader "Your/Custom/Shader"
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
</details>
|
</details>
|
||||||
|
|
||||||
|
<br><br>
|
||||||
|
|
||||||
<br><br><br><br>
|
## 🤝 Contributing
|
||||||
|
|
||||||
## Contributing
|
|
||||||
|
|
||||||
### Issues
|
### Issues
|
||||||
|
|
||||||
Issues are very valuable to this project.
|
Issues are incredibly valuable to this project:
|
||||||
|
|
||||||
- Ideas are a valuable source of contributions others can make
|
- Ideas provide a valuable source of contributions that others can make.
|
||||||
- Problems show where this project is lacking
|
- Problems help identify areas where this project needs improvement.
|
||||||
- With a question you show where contributors can improve the user experience
|
- Questions indicate where contributors can enhance the user experience.
|
||||||
|
|
||||||
### Pull Requests
|
### Pull Requests
|
||||||
|
|
||||||
Pull requests are, a great way to get your ideas into this repository.
|
Pull requests offer a fantastic way to contribute your ideas to this repository.
|
||||||
See [CONTRIBUTING.md](/../../blob/develop/CONTRIBUTING.md).
|
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.
|
||||||
|
|
||||||
### Support
|
### Support
|
||||||
|
|
||||||
This is an open source project that I am developing in my spare time.
|
This is an open-source project developed during my spare time.
|
||||||
If you like it, please support me.
|
If you appreciate it, consider supporting me.
|
||||||
With your support, I can spend more time on development. :)
|
Your support allows me to dedicate more time to development. 😊
|
||||||
|
|
||||||
[](https://www.patreon.com/join/mob_sakai?)
|
[](https://www.patreon.com/join/2343451?)
|
||||||
[](https://github.com/users/mob-sakai/sponsorship)
|
[](https://github.com/users/mob-sakai/sponsorship)
|
||||||
|
|
||||||
|
<br><br>
|
||||||
|
|
||||||
<br><br><br><br>
|
|
||||||
|
|
||||||
## License
|
## License
|
||||||
|
|
||||||
* MIT
|
* MIT
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
## Author
|
## Author
|
||||||
|
|
||||||
*  [mob-sakai](https://github.com/mob-sakai) [](https://twitter.com/intent/follow?screen_name=mob_sakai) 
|
*  [mob-sakai](https://github.com/mob-sakai) [](https://twitter.com/intent/follow?screen_name=mob_sakai) 
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
## See Also
|
## See Also
|
||||||
|
|
||||||
* GitHub page : https://github.com/mob-sakai/ParticleEffectForUGUI
|
* GitHub page : https://github.com/mob-sakai/ParticleEffectForUGUI
|
||||||
* Releases : https://github.com/mob-sakai/ParticleEffectForUGUI/releases
|
* Releases : https://github.com/mob-sakai/ParticleEffectForUGUI/releases
|
||||||
* Issue tracker : https://github.com/mob-sakai/ParticleEffectForUGUI/issues
|
* Issue tracker : https://github.com/mob-sakai/ParticleEffectForUGUI/issues
|
||||||
* Change log : https://github.com/mob-sakai/ParticleEffectForUGUI/blob/upm/CHANGELOG.md
|
* Change log : https://github.com/mob-sakai/ParticleEffectForUGUI/blob/main/CHANGELOG.md
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
using System;
|
using System;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
|
|
||||||
namespace Coffee.UIExtensions
|
namespace Coffee.UIExtensions
|
||||||
@@ -19,10 +19,7 @@ namespace Coffee.UIExtensions
|
|||||||
[SerializeField] private ShaderPropertyType m_Type = ShaderPropertyType.Vector;
|
[SerializeField] private ShaderPropertyType m_Type = ShaderPropertyType.Vector;
|
||||||
public int id { get; private set; }
|
public int id { get; private set; }
|
||||||
|
|
||||||
public ShaderPropertyType type
|
public ShaderPropertyType type => m_Type;
|
||||||
{
|
|
||||||
get { return m_Type; }
|
|
||||||
}
|
|
||||||
|
|
||||||
void ISerializationCallbackReceiver.OnBeforeSerialize()
|
void ISerializationCallbackReceiver.OnBeforeSerialize()
|
||||||
{
|
{
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
|
|
||||||
namespace Coffee.UIParticleExtensions
|
namespace Coffee.UIParticleExtensions
|
||||||
@@ -28,8 +28,8 @@ namespace Coffee.UIParticleExtensions
|
|||||||
customMat = new Material(baseMat)
|
customMat = new Material(baseMat)
|
||||||
{
|
{
|
||||||
name = $"{baseMat.name}_{id}",
|
name = $"{baseMat.name}_{id}",
|
||||||
hideFlags = HideFlags.HideAndDontSave,
|
hideFlags = HideFlags.DontSave | HideFlags.NotEditable,
|
||||||
mainTexture = texture ? texture : null
|
mainTexture = texture ? texture : baseMat.mainTexture
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
s_Entries.Add(e);
|
s_Entries.Add(e);
|
||||||
@@ -2,7 +2,6 @@ using System;
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Runtime.CompilerServices;
|
using System.Runtime.CompilerServices;
|
||||||
using Coffee.UIParticleExtensions;
|
using Coffee.UIParticleExtensions;
|
||||||
using UnityEditor;
|
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
using UnityEngine.Rendering;
|
using UnityEngine.Rendering;
|
||||||
using UnityEngine.Serialization;
|
using UnityEngine.Serialization;
|
||||||
@@ -21,6 +20,13 @@ namespace Coffee.UIExtensions
|
|||||||
[RequireComponent(typeof(CanvasRenderer))]
|
[RequireComponent(typeof(CanvasRenderer))]
|
||||||
public class UIParticle : MaskableGraphic, ISerializationCallbackReceiver
|
public class UIParticle : MaskableGraphic, ISerializationCallbackReceiver
|
||||||
{
|
{
|
||||||
|
public enum AutoScalingMode
|
||||||
|
{
|
||||||
|
None,
|
||||||
|
UIParticle,
|
||||||
|
Transform
|
||||||
|
}
|
||||||
|
|
||||||
public enum MeshSharing
|
public enum MeshSharing
|
||||||
{
|
{
|
||||||
None,
|
None,
|
||||||
@@ -36,32 +42,28 @@ namespace Coffee.UIExtensions
|
|||||||
Absolute
|
Absolute
|
||||||
}
|
}
|
||||||
|
|
||||||
public enum AutoScalingMode
|
|
||||||
{
|
|
||||||
None,
|
|
||||||
UIParticle,
|
|
||||||
Transform
|
|
||||||
}
|
|
||||||
|
|
||||||
[HideInInspector]
|
[HideInInspector]
|
||||||
[SerializeField]
|
[SerializeField]
|
||||||
|
[Obsolete]
|
||||||
internal bool m_IsTrail;
|
internal bool m_IsTrail;
|
||||||
|
|
||||||
[HideInInspector]
|
[HideInInspector]
|
||||||
[FormerlySerializedAs("m_IgnoreParent")]
|
[FormerlySerializedAs("m_IgnoreParent")]
|
||||||
[SerializeField]
|
[SerializeField]
|
||||||
|
[Obsolete]
|
||||||
private bool m_IgnoreCanvasScaler;
|
private bool m_IgnoreCanvasScaler;
|
||||||
|
|
||||||
[HideInInspector]
|
[HideInInspector]
|
||||||
[SerializeField]
|
[SerializeField]
|
||||||
private bool m_AbsoluteMode;
|
[Obsolete]
|
||||||
|
internal bool m_AbsoluteMode;
|
||||||
|
|
||||||
[Tooltip("Particle effect scale")]
|
[Tooltip("Scale the rendering particles. When the `3D` toggle is enabled, 3D scale (x, y, z) is supported.")]
|
||||||
[SerializeField]
|
[SerializeField]
|
||||||
private Vector3 m_Scale3D = new Vector3(10, 10, 10);
|
private Vector3 m_Scale3D = new Vector3(10, 10, 10);
|
||||||
|
|
||||||
[Tooltip("Animatable material properties.\n" +
|
[Tooltip("If you want to update material properties (e.g. _MainTex_ST, _Color) in AnimationClip, " +
|
||||||
"If you want to change the material properties of the ParticleSystem in Animation, enable it.")]
|
"use this to mark as animatable.")]
|
||||||
[SerializeField]
|
[SerializeField]
|
||||||
internal AnimatableProperty[] m_AnimatableProperties = new AnimatableProperty[0];
|
internal AnimatableProperty[] m_AnimatableProperties = new AnimatableProperty[0];
|
||||||
|
|
||||||
@@ -69,12 +71,13 @@ namespace Coffee.UIExtensions
|
|||||||
[SerializeField]
|
[SerializeField]
|
||||||
private List<ParticleSystem> m_Particles = new List<ParticleSystem>();
|
private List<ParticleSystem> m_Particles = new List<ParticleSystem>();
|
||||||
|
|
||||||
[Tooltip("Mesh sharing.\n" +
|
[Tooltip("Particle simulation results are shared within the same group. " +
|
||||||
"None: disable mesh sharing.\n" +
|
"A large number of the same effects can be displayed with a small load.\n" +
|
||||||
"Auto: automatically select Primary/Replica.\n" +
|
"None: Disable mesh sharing.\n" +
|
||||||
"Primary: provides particle simulation results to the same group.\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" +
|
"Primary Simulator: Primary, but do not render the particle (simulation only).\n" +
|
||||||
"Replica: render simulation results provided by the primary.")]
|
"Replica: Render simulation results provided by the primary.")]
|
||||||
[SerializeField]
|
[SerializeField]
|
||||||
private MeshSharing m_MeshSharing = MeshSharing.None;
|
private MeshSharing m_MeshSharing = MeshSharing.None;
|
||||||
|
|
||||||
@@ -86,26 +89,40 @@ namespace Coffee.UIExtensions
|
|||||||
[SerializeField]
|
[SerializeField]
|
||||||
private int m_GroupMaxId;
|
private int m_GroupMaxId;
|
||||||
|
|
||||||
[Tooltip("Relative: The particles will be emitted from the scaled position of ParticleSystem.\n" +
|
[Tooltip("Emission position mode.\n" +
|
||||||
"Absolute: The particles will be emitted from the world position of ParticleSystem.")]
|
"Relative: The particles will be emitted from the scaled position.\n" +
|
||||||
|
"Absolute: The particles will be emitted from the world position.")]
|
||||||
[SerializeField]
|
[SerializeField]
|
||||||
private PositionMode m_PositionMode = PositionMode.Relative;
|
private PositionMode m_PositionMode = PositionMode.Relative;
|
||||||
|
|
||||||
[SerializeField]
|
[SerializeField]
|
||||||
[Tooltip("Prevent the root-Canvas scale from affecting the hierarchy-scaled ParticleSystem.")]
|
[Obsolete]
|
||||||
private bool m_AutoScaling = true;
|
internal bool m_AutoScaling;
|
||||||
|
|
||||||
[SerializeField]
|
[SerializeField]
|
||||||
[Tooltip("Transform: Transform.lossyScale (=world scale) will be set to (1, 1, 1)." +
|
[Tooltip(
|
||||||
"UIParticle: UIParticle.scale will be adjusted.")]
|
"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;
|
private AutoScalingMode m_AutoScalingMode = AutoScalingMode.Transform;
|
||||||
|
|
||||||
[SerializeField]
|
[SerializeField]
|
||||||
private bool m_ResetScaleOnEnable;
|
[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 readonly List<UIParticleRenderer> _renderers = new List<UIParticleRenderer>();
|
||||||
|
private Camera _bakeCamera;
|
||||||
|
private Canvas _canvas;
|
||||||
private int _groupId;
|
private int _groupId;
|
||||||
private Camera _orthoCamera;
|
private bool _isScaleStored;
|
||||||
|
private Vector3 _storedScale;
|
||||||
private DrivenRectTransformTracker _tracker;
|
private DrivenRectTransformTracker _tracker;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -113,12 +130,13 @@ namespace Coffee.UIExtensions
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public override bool raycastTarget
|
public override bool raycastTarget
|
||||||
{
|
{
|
||||||
get { return false; }
|
get => false;
|
||||||
set { }
|
set { }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 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.
|
||||||
/// None: disable mesh sharing.
|
/// None: disable mesh sharing.
|
||||||
/// Auto: automatically select Primary/Replica.
|
/// Auto: automatically select Primary/Replica.
|
||||||
/// Primary: provides particle simulation results to the same group.
|
/// Primary: provides particle simulation results to the same group.
|
||||||
@@ -127,8 +145,8 @@ namespace Coffee.UIExtensions
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public MeshSharing meshSharing
|
public MeshSharing meshSharing
|
||||||
{
|
{
|
||||||
get { return m_MeshSharing; }
|
get => m_MeshSharing;
|
||||||
set { m_MeshSharing = value; }
|
set => m_MeshSharing = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -137,7 +155,7 @@ namespace Coffee.UIExtensions
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public int groupId
|
public int groupId
|
||||||
{
|
{
|
||||||
get { return _groupId; }
|
get => _groupId;
|
||||||
set
|
set
|
||||||
{
|
{
|
||||||
if (m_GroupId == value) return;
|
if (m_GroupId == value) return;
|
||||||
@@ -151,7 +169,7 @@ namespace Coffee.UIExtensions
|
|||||||
|
|
||||||
public int groupMaxId
|
public int groupMaxId
|
||||||
{
|
{
|
||||||
get { return m_GroupMaxId; }
|
get => m_GroupMaxId;
|
||||||
set
|
set
|
||||||
{
|
{
|
||||||
if (m_GroupMaxId == value) return;
|
if (m_GroupMaxId == value) return;
|
||||||
@@ -161,14 +179,14 @@ namespace Coffee.UIExtensions
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Particle position mode.
|
/// Emission position mode.
|
||||||
/// Relative: The particles will be emitted from the scaled position of the ParticleSystem.
|
/// Relative: The particles will be emitted from the scaled position.
|
||||||
/// Absolute: The particles will be emitted from the world position of the ParticleSystem.
|
/// Absolute: The particles will be emitted from the world position.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public PositionMode positionMode
|
public PositionMode positionMode
|
||||||
{
|
{
|
||||||
get { return m_PositionMode; }
|
get => m_PositionMode;
|
||||||
set { m_PositionMode = value; }
|
set => m_PositionMode = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -176,10 +194,11 @@ namespace Coffee.UIExtensions
|
|||||||
/// Relative: The particles will be emitted from the scaled position of the ParticleSystem.
|
/// 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.
|
/// Absolute: The particles will be emitted from the world position of the ParticleSystem.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
[Obsolete("The absoluteMode is now obsolete. Please use the autoScalingMode instead.", false)]
|
||||||
public bool absoluteMode
|
public bool absoluteMode
|
||||||
{
|
{
|
||||||
get { return m_PositionMode == PositionMode.Absolute; }
|
get => m_PositionMode == PositionMode.Absolute;
|
||||||
set { positionMode = value ? PositionMode.Absolute : PositionMode.Relative; }
|
set => positionMode = value ? PositionMode.Absolute : PositionMode.Relative;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -188,72 +207,80 @@ namespace Coffee.UIExtensions
|
|||||||
[Obsolete("The autoScaling is now obsolete. Please use the autoScalingMode instead.", false)]
|
[Obsolete("The autoScaling is now obsolete. Please use the autoScalingMode instead.", false)]
|
||||||
public bool autoScaling
|
public bool autoScaling
|
||||||
{
|
{
|
||||||
get { return m_AutoScalingMode != AutoScalingMode.None; }
|
get => m_AutoScalingMode != AutoScalingMode.None;
|
||||||
set
|
set => autoScalingMode = value ? AutoScalingMode.Transform : AutoScalingMode.None;
|
||||||
{
|
|
||||||
autoScalingMode = value ? AutoScalingMode.Transform : AutoScalingMode.None;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Auto scaling mode.
|
/// 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).
|
/// Transform: Transform.lossyScale (=world scale) will be set to (1, 1, 1).
|
||||||
|
/// <para/>
|
||||||
/// UIParticle: UIParticle.scale will be adjusted.
|
/// UIParticle: UIParticle.scale will be adjusted.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public AutoScalingMode autoScalingMode
|
public AutoScalingMode autoScalingMode
|
||||||
{
|
{
|
||||||
get { return m_AutoScalingMode; }
|
get => m_AutoScalingMode;
|
||||||
set
|
set
|
||||||
{
|
{
|
||||||
if (m_AutoScalingMode == value) return;
|
if (m_AutoScalingMode == value) return;
|
||||||
m_AutoScalingMode = value;
|
m_AutoScalingMode = value;
|
||||||
UpdateTracker();
|
|
||||||
|
if (autoScalingMode != AutoScalingMode.Transform && _isScaleStored)
|
||||||
|
{
|
||||||
|
transform.localScale = _storedScale;
|
||||||
|
_isScaleStored = false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
internal bool useMeshSharing
|
/// <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 { return m_MeshSharing != MeshSharing.None; }
|
get => m_UseCustomView;
|
||||||
|
set => m_UseCustomView = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
internal bool isPrimary
|
/// <summary>
|
||||||
|
/// Custom view size.
|
||||||
|
/// Change the bake view size.
|
||||||
|
/// </summary>
|
||||||
|
public float customViewSize
|
||||||
{
|
{
|
||||||
get
|
get => m_CustomViewSize;
|
||||||
{
|
set => m_CustomViewSize = Mathf.Max(0.1f, value);
|
||||||
return m_MeshSharing == MeshSharing.Primary
|
|
||||||
|| m_MeshSharing == MeshSharing.PrimarySimulator;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
internal bool canSimulate
|
internal bool useMeshSharing => m_MeshSharing != MeshSharing.None;
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
return m_MeshSharing == MeshSharing.None
|
|
||||||
|| m_MeshSharing == MeshSharing.Auto
|
|
||||||
|| m_MeshSharing == MeshSharing.Primary
|
|
||||||
|| m_MeshSharing == MeshSharing.PrimarySimulator;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
internal bool canRender
|
internal bool isPrimary =>
|
||||||
{
|
m_MeshSharing == MeshSharing.Primary
|
||||||
get
|
|| m_MeshSharing == MeshSharing.PrimarySimulator;
|
||||||
{
|
|
||||||
return m_MeshSharing == MeshSharing.None
|
internal bool canSimulate =>
|
||||||
|| m_MeshSharing == MeshSharing.Auto
|
m_MeshSharing == MeshSharing.None
|
||||||
|| m_MeshSharing == MeshSharing.Primary
|
|| m_MeshSharing == MeshSharing.Auto
|
||||||
|| m_MeshSharing == MeshSharing.Replica;
|
|| 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>
|
/// <summary>
|
||||||
/// Particle effect scale.
|
/// Particle effect scale.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public float scale
|
public float scale
|
||||||
{
|
{
|
||||||
get { return m_Scale3D.x; }
|
get => m_Scale3D.x;
|
||||||
set { m_Scale3D = new Vector3(value, value, value); }
|
set => m_Scale3D = new Vector3(value, value, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -261,43 +288,18 @@ namespace Coffee.UIExtensions
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public Vector3 scale3D
|
public Vector3 scale3D
|
||||||
{
|
{
|
||||||
get { return m_Scale3D; }
|
get => m_Scale3D;
|
||||||
set { m_Scale3D = value; }
|
set => m_Scale3D = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Particle effect scale.
|
/// Particle effect scale.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public Vector3 scale3DForCalc
|
public Vector3 scale3DForCalc => autoScalingMode == AutoScalingMode.Transform
|
||||||
{
|
? m_Scale3D
|
||||||
get { return autoScalingMode == AutoScalingMode.UIParticle ? m_Scale3D.GetScaled(canvasScale) : m_Scale3D; }
|
: m_Scale3D.GetScaled(canvasScale, transform.localScale);
|
||||||
}
|
|
||||||
|
|
||||||
public List<ParticleSystem> particles
|
public List<ParticleSystem> particles => m_Particles;
|
||||||
{
|
|
||||||
get { return m_Particles; }
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Get all base materials to render.
|
|
||||||
/// </summary>
|
|
||||||
public IEnumerable<Material> materials
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
for (var i = 0; i < _renderers.Count; i++)
|
|
||||||
{
|
|
||||||
var r = _renderers[i];
|
|
||||||
if (!r || !r.material) continue;
|
|
||||||
yield return r.material;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public override Material materialForRendering
|
|
||||||
{
|
|
||||||
get { return null; }
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Paused.
|
/// Paused.
|
||||||
@@ -310,8 +312,8 @@ namespace Coffee.UIExtensions
|
|||||||
|
|
||||||
protected override void OnEnable()
|
protected override void OnEnable()
|
||||||
{
|
{
|
||||||
|
_isScaleStored = false;
|
||||||
ResetGroupId();
|
ResetGroupId();
|
||||||
UpdateTracker();
|
|
||||||
UIParticleUpdater.Register(this);
|
UIParticleUpdater.Register(this);
|
||||||
RegisterDirtyMaterialCallback(UpdateRendererMaterial);
|
RegisterDirtyMaterialCallback(UpdateRendererMaterial);
|
||||||
|
|
||||||
@@ -325,13 +327,6 @@ namespace Coffee.UIExtensions
|
|||||||
}
|
}
|
||||||
|
|
||||||
base.OnEnable();
|
base.OnEnable();
|
||||||
|
|
||||||
// Reset scale for upgrade.
|
|
||||||
if (m_ResetScaleOnEnable)
|
|
||||||
{
|
|
||||||
m_ResetScaleOnEnable = false;
|
|
||||||
transform.localScale = Vector3.one;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -339,7 +334,13 @@ namespace Coffee.UIExtensions
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
protected override void OnDisable()
|
protected override void OnDisable()
|
||||||
{
|
{
|
||||||
UpdateTracker();
|
_tracker.Clear();
|
||||||
|
if (autoScalingMode == AutoScalingMode.Transform && _isScaleStored)
|
||||||
|
{
|
||||||
|
transform.localScale = _storedScale;
|
||||||
|
}
|
||||||
|
|
||||||
|
_isScaleStored = false;
|
||||||
UIParticleUpdater.Unregister(this);
|
UIParticleUpdater.Unregister(this);
|
||||||
_renderers.ForEach(r => r.Reset());
|
_renderers.ForEach(r => r.Reset());
|
||||||
UnregisterDirtyMaterialCallback(UpdateRendererMaterial);
|
UnregisterDirtyMaterialCallback(UpdateRendererMaterial);
|
||||||
@@ -354,36 +355,18 @@ namespace Coffee.UIExtensions
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
#if UNITY_EDITOR
|
|
||||||
protected override void OnValidate()
|
|
||||||
{
|
|
||||||
base.OnValidate();
|
|
||||||
UpdateTracker();
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
void ISerializationCallbackReceiver.OnBeforeSerialize()
|
void ISerializationCallbackReceiver.OnBeforeSerialize()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void ISerializationCallbackReceiver.OnAfterDeserialize()
|
void ISerializationCallbackReceiver.OnAfterDeserialize()
|
||||||
{
|
{
|
||||||
|
#pragma warning disable CS0612 // Type or member is obsolete
|
||||||
if (m_IgnoreCanvasScaler || m_AutoScaling)
|
if (m_IgnoreCanvasScaler || m_AutoScaling)
|
||||||
{
|
{
|
||||||
m_IgnoreCanvasScaler = false;
|
m_IgnoreCanvasScaler = false;
|
||||||
m_AutoScaling = false;
|
m_AutoScaling = false;
|
||||||
m_AutoScalingMode = AutoScalingMode.Transform;
|
m_AutoScalingMode = AutoScalingMode.Transform;
|
||||||
m_ResetScaleOnEnable = true;
|
|
||||||
|
|
||||||
#if UNITY_EDITOR
|
|
||||||
EditorApplication.delayCall += () =>
|
|
||||||
{
|
|
||||||
if (!this || !gameObject || !transform || Application.isPlaying) return;
|
|
||||||
transform.localScale = Vector3.one;
|
|
||||||
m_ResetScaleOnEnable = false;
|
|
||||||
EditorUtility.SetDirty(this);
|
|
||||||
};
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_AbsoluteMode)
|
if (m_AbsoluteMode)
|
||||||
@@ -391,31 +374,47 @@ namespace Coffee.UIExtensions
|
|||||||
m_AbsoluteMode = false;
|
m_AbsoluteMode = false;
|
||||||
m_PositionMode = PositionMode.Absolute;
|
m_PositionMode = PositionMode.Absolute;
|
||||||
}
|
}
|
||||||
|
#pragma warning restore CS0612 // Type or member is obsolete
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Play the ParticleSystems.
|
||||||
|
/// </summary>
|
||||||
public void Play()
|
public void Play()
|
||||||
{
|
{
|
||||||
particles.Exec(p => p.Simulate(0, false, true));
|
particles.Exec(p => p.Simulate(0, false, true));
|
||||||
isPaused = false;
|
isPaused = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Pause the ParticleSystems.
|
||||||
|
/// </summary>
|
||||||
public void Pause()
|
public void Pause()
|
||||||
{
|
{
|
||||||
particles.Exec(p => p.Pause());
|
particles.Exec(p => p.Pause());
|
||||||
isPaused = true;
|
isPaused = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Unpause the ParticleSystems.
|
||||||
|
/// </summary>
|
||||||
public void Resume()
|
public void Resume()
|
||||||
{
|
{
|
||||||
isPaused = false;
|
isPaused = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Stop the ParticleSystems.
|
||||||
|
/// </summary>
|
||||||
public void Stop()
|
public void Stop()
|
||||||
{
|
{
|
||||||
particles.Exec(p => p.Stop());
|
particles.Exec(p => p.Stop());
|
||||||
isPaused = true;
|
isPaused = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Start emission of the ParticleSystems.
|
||||||
|
/// </summary>
|
||||||
public void StartEmission()
|
public void StartEmission()
|
||||||
{
|
{
|
||||||
particles.Exec(p =>
|
particles.Exec(p =>
|
||||||
@@ -425,6 +424,9 @@ namespace Coffee.UIExtensions
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Stop emission of the ParticleSystems.
|
||||||
|
/// </summary>
|
||||||
public void StopEmission()
|
public void StopEmission()
|
||||||
{
|
{
|
||||||
particles.Exec(p =>
|
particles.Exec(p =>
|
||||||
@@ -434,24 +436,52 @@ namespace Coffee.UIExtensions
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Clear the particles of the ParticleSystems.
|
||||||
|
/// </summary>
|
||||||
public void Clear()
|
public void Clear()
|
||||||
{
|
{
|
||||||
particles.Exec(p => p.Clear());
|
particles.Exec(p => p.Clear());
|
||||||
isPaused = true;
|
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)
|
public void SetParticleSystemInstance(GameObject instance)
|
||||||
{
|
{
|
||||||
SetParticleSystemInstance(instance, true);
|
SetParticleSystemInstance(instance, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Refresh UIParticle using the ParticleSystem instance.
|
||||||
|
/// </summary>
|
||||||
public void SetParticleSystemInstance(GameObject instance, bool destroyOldParticles)
|
public void SetParticleSystemInstance(GameObject instance, bool destroyOldParticles)
|
||||||
{
|
{
|
||||||
if (!instance) return;
|
if (!instance) return;
|
||||||
|
|
||||||
foreach (Transform child in transform)
|
var childCount = transform.childCount;
|
||||||
|
for (var i = 0; i < childCount; i++)
|
||||||
{
|
{
|
||||||
var go = child.gameObject;
|
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);
|
go.SetActive(false);
|
||||||
if (destroyOldParticles)
|
if (destroyOldParticles)
|
||||||
{
|
{
|
||||||
@@ -466,6 +496,10 @@ namespace Coffee.UIExtensions
|
|||||||
RefreshParticles(instance);
|
RefreshParticles(instance);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Refresh UIParticle using the prefab.
|
||||||
|
/// The prefab is automatically instantiated.
|
||||||
|
/// </summary>
|
||||||
public void SetParticleSystemPrefab(GameObject prefab)
|
public void SetParticleSystemPrefab(GameObject prefab)
|
||||||
{
|
{
|
||||||
if (!prefab) return;
|
if (!prefab) return;
|
||||||
@@ -473,16 +507,31 @@ namespace Coffee.UIExtensions
|
|||||||
SetParticleSystemInstance(Instantiate(prefab.gameObject), true);
|
SetParticleSystemInstance(Instantiate(prefab.gameObject), true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Refresh UIParticle.
|
||||||
|
/// Collect ParticleSystems under the GameObject and refresh the UIParticle.
|
||||||
|
/// </summary>
|
||||||
public void RefreshParticles()
|
public void RefreshParticles()
|
||||||
{
|
{
|
||||||
RefreshParticles(gameObject);
|
RefreshParticles(gameObject);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Refresh UIParticle.
|
||||||
|
/// Collect ParticleSystems under the GameObject and refresh the UIParticle.
|
||||||
|
/// </summary>
|
||||||
private void RefreshParticles(GameObject root)
|
private void RefreshParticles(GameObject root)
|
||||||
{
|
{
|
||||||
if (!root) return;
|
if (!root) return;
|
||||||
root.GetComponentsInChildren(true, particles);
|
root.GetComponentsInChildren(true, particles);
|
||||||
particles.RemoveAll(x => x.GetComponentInParent<UIParticle>(true) != this);
|
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++)
|
for (var i = 0; i < particles.Count; i++)
|
||||||
{
|
{
|
||||||
@@ -497,31 +546,39 @@ namespace Coffee.UIExtensions
|
|||||||
RefreshParticles(particles);
|
RefreshParticles(particles);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void RefreshParticles(List<ParticleSystem> 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
|
// #246: Nullptr exceptions when using nested UIParticle components in hierarchy
|
||||||
_renderers.Clear();
|
_renderers.Clear();
|
||||||
foreach (Transform child in transform)
|
var childCount = transform.childCount;
|
||||||
|
for (var i = 0; i < childCount; i++)
|
||||||
{
|
{
|
||||||
var uiParticleRenderer = child.GetComponent<UIParticleRenderer>();
|
var child = transform.GetChild(i);
|
||||||
|
if (child.TryGetComponent(out UIParticleRenderer uiParticleRenderer))
|
||||||
if (uiParticleRenderer != null)
|
|
||||||
{
|
{
|
||||||
_renderers.Add(uiParticleRenderer);
|
_renderers.Add(uiParticleRenderer);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Reset the UIParticleRenderer components.
|
||||||
for (var i = 0; i < _renderers.Count; i++)
|
for (var i = 0; i < _renderers.Count; i++)
|
||||||
{
|
{
|
||||||
_renderers[i].Reset(i);
|
_renderers[i].Reset(i);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Set the ParticleSystem to the UIParticleRenderer. If the trail is enabled, set it additionally.
|
||||||
var j = 0;
|
var j = 0;
|
||||||
for (var i = 0; i < particles.Count; i++)
|
for (var i = 0; i < particleSystems.Count; i++)
|
||||||
{
|
{
|
||||||
var ps = particles[i];
|
var ps = particleSystems[i];
|
||||||
if (!ps) continue;
|
if (!ps) continue;
|
||||||
GetRenderer(j++).Set(this, ps, false);
|
GetRenderer(j++).Set(this, ps, false);
|
||||||
|
|
||||||
|
// If the trail is enabled, set it additionally.
|
||||||
if (ps.trails.enabled)
|
if (ps.trails.enabled)
|
||||||
{
|
{
|
||||||
GetRenderer(j++).Set(this, ps, true);
|
GetRenderer(j++).Set(this, ps, true);
|
||||||
@@ -531,12 +588,30 @@ namespace Coffee.UIExtensions
|
|||||||
|
|
||||||
internal void UpdateTransformScale()
|
internal void UpdateTransformScale()
|
||||||
{
|
{
|
||||||
|
_tracker.Clear();
|
||||||
canvasScale = canvas.rootCanvas.transform.localScale.Inverse();
|
canvasScale = canvas.rootCanvas.transform.localScale.Inverse();
|
||||||
parentScale = transform.parent.lossyScale;
|
parentScale = transform.parent.lossyScale;
|
||||||
if (autoScalingMode != AutoScalingMode.Transform) return;
|
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();
|
var newScale = parentScale.Inverse();
|
||||||
if (transform.localScale != newScale)
|
if (currentScale != newScale)
|
||||||
{
|
{
|
||||||
transform.localScale = newScale;
|
transform.localScale = newScale;
|
||||||
}
|
}
|
||||||
@@ -549,11 +624,10 @@ namespace Coffee.UIExtensions
|
|||||||
for (var i = 0; i < _renderers.Count; i++)
|
for (var i = 0; i < _renderers.Count; i++)
|
||||||
{
|
{
|
||||||
var r = _renderers[i];
|
var r = _renderers[i];
|
||||||
if (!r)
|
if (r) continue;
|
||||||
{
|
|
||||||
RefreshParticles(particles);
|
RefreshParticles(particles);
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var bakeCamera = GetBakeCamera();
|
var bakeCamera = GetBakeCamera();
|
||||||
@@ -561,17 +635,8 @@ namespace Coffee.UIExtensions
|
|||||||
{
|
{
|
||||||
var r = _renderers[i];
|
var r = _renderers[i];
|
||||||
if (!r) continue;
|
if (!r) continue;
|
||||||
r.UpdateMesh(bakeCamera);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
internal void UpdateParticleCount()
|
r.UpdateMesh(bakeCamera);
|
||||||
{
|
|
||||||
for (var i = 0; i < _renderers.Count; i++)
|
|
||||||
{
|
|
||||||
var r = _renderers[i];
|
|
||||||
if (!r) continue;
|
|
||||||
r.UpdateParticleCount();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -622,61 +687,55 @@ namespace Coffee.UIExtensions
|
|||||||
private Camera GetBakeCamera()
|
private Camera GetBakeCamera()
|
||||||
{
|
{
|
||||||
if (!canvas) return Camera.main;
|
if (!canvas) return Camera.main;
|
||||||
|
if (!useCustomView && canvas.renderMode != RenderMode.ScreenSpaceOverlay && canvas.rootCanvas.worldCamera)
|
||||||
// When render mode is ScreenSpaceCamera or WorldSpace, use world camera.
|
|
||||||
var root = canvas.rootCanvas;
|
|
||||||
if (root.renderMode != RenderMode.ScreenSpaceOverlay)
|
|
||||||
{
|
{
|
||||||
return root.worldCamera ? root.worldCamera : Camera.main;
|
return canvas.rootCanvas.worldCamera;
|
||||||
}
|
}
|
||||||
|
|
||||||
// When render mode is ScreenSpaceOverlay, use ortho-camera.
|
if (_bakeCamera)
|
||||||
if (!_orthoCamera)
|
|
||||||
{
|
{
|
||||||
// Find existing ortho-camera.
|
_bakeCamera.orthographicSize = useCustomView ? customViewSize : 10;
|
||||||
foreach (Transform child in transform)
|
return _bakeCamera;
|
||||||
{
|
}
|
||||||
var cam = child.GetComponent<Camera>();
|
|
||||||
if (cam && cam.name == "[generated] UIParticleOverlayCamera")
|
|
||||||
{
|
|
||||||
_orthoCamera = cam;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create ortho-camera.
|
// Find existing baking camera.
|
||||||
if (!_orthoCamera)
|
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")
|
||||||
{
|
{
|
||||||
var go = new GameObject("[generated] UIParticleOverlayCamera") { hideFlags = HideFlags.DontSave | HideFlags.NotEditable };
|
_bakeCamera = cam;
|
||||||
go.SetActive(false);
|
break;
|
||||||
go.transform.SetParent(transform, false);
|
|
||||||
_orthoCamera = go.AddComponent<Camera>();
|
|
||||||
_orthoCamera.enabled = false;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
// Create baking camera.
|
||||||
var size = ((RectTransform)root.transform).rect.size;
|
if (!_bakeCamera)
|
||||||
_orthoCamera.orthographicSize = Mathf.Max(size.x, size.y) * root.scaleFactor;
|
|
||||||
_orthoCamera.transform.SetPositionAndRotation(new Vector3(0, 0, -1000), Quaternion.identity);
|
|
||||||
_orthoCamera.orthographic = true;
|
|
||||||
_orthoCamera.farClipPlane = 2000f;
|
|
||||||
|
|
||||||
return _orthoCamera;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void UpdateTracker()
|
|
||||||
{
|
|
||||||
#pragma warning disable CS0618 // Type or member is obsolete
|
|
||||||
if (!enabled || !autoScaling || autoScalingMode != AutoScalingMode.Transform)
|
|
||||||
#pragma warning restore CS0618 // Type or member is obsolete
|
|
||||||
{
|
{
|
||||||
_tracker.Clear();
|
var go = new GameObject("[generated] UIParticle BakingCamera");
|
||||||
}
|
go.SetActive(false);
|
||||||
else
|
go.transform.SetParent(transform, false);
|
||||||
{
|
_bakeCamera = go.AddComponent<Camera>();
|
||||||
_tracker.Add(this, rectTransform, DrivenTransformProperties.Scale);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -5,7 +5,7 @@ MonoImporter:
|
|||||||
serializedVersion: 2
|
serializedVersion: 2
|
||||||
defaultReferences: []
|
defaultReferences: []
|
||||||
executionOrder: 0
|
executionOrder: 0
|
||||||
icon: {instanceID: 0}
|
icon: {fileID: 2800000, guid: 5f0675613942149309588d556e33d990, type: 3}
|
||||||
userData:
|
userData:
|
||||||
assetBundleName:
|
assetBundleName:
|
||||||
assetBundleVariant:
|
assetBundleVariant:
|
||||||
333
Runtime/UIParticleAttractor.cs
Normal file
333
Runtime/UIParticleAttractor.cs
Normal file
@@ -0,0 +1,333 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using Coffee.UIParticleExtensions;
|
||||||
|
using UnityEngine;
|
||||||
|
using UnityEngine.Events;
|
||||||
|
|
||||||
|
namespace Coffee.UIExtensions
|
||||||
|
{
|
||||||
|
[ExecuteAlways]
|
||||||
|
public class UIParticleAttractor : MonoBehaviour, ISerializationCallbackReceiver
|
||||||
|
{
|
||||||
|
public enum Movement
|
||||||
|
{
|
||||||
|
Linear,
|
||||||
|
Smooth,
|
||||||
|
Sphere
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum UpdateMode
|
||||||
|
{
|
||||||
|
Normal,
|
||||||
|
UnscaledTime
|
||||||
|
}
|
||||||
|
|
||||||
|
[SerializeField]
|
||||||
|
[HideInInspector]
|
||||||
|
private ParticleSystem m_ParticleSystem;
|
||||||
|
|
||||||
|
[SerializeField]
|
||||||
|
private List<ParticleSystem> m_ParticleSystems = new List<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 List<UIParticle> _uiParticles = new List<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 ParticleSystems to attract. Use <see cref="AddParticleSystem"/> and
|
||||||
|
/// <see cref="RemoveParticleSystem"/> to modify the list.
|
||||||
|
/// </summary>
|
||||||
|
public IReadOnlyList<ParticleSystem> particleSystems => m_ParticleSystems;
|
||||||
|
|
||||||
|
public void AddParticleSystem(ParticleSystem ps)
|
||||||
|
{
|
||||||
|
if (m_ParticleSystems == null)
|
||||||
|
{
|
||||||
|
m_ParticleSystems = new List<ParticleSystem>();
|
||||||
|
}
|
||||||
|
|
||||||
|
var i = m_ParticleSystems.IndexOf(ps);
|
||||||
|
if (0 <= i) return; // Already added: skip
|
||||||
|
|
||||||
|
m_ParticleSystems.Add(ps);
|
||||||
|
_uiParticles.Clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void RemoveParticleSystem(ParticleSystem ps)
|
||||||
|
{
|
||||||
|
if (m_ParticleSystems == null)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var i = m_ParticleSystems.IndexOf(ps);
|
||||||
|
if (i < 0) return; // Not found. skip
|
||||||
|
|
||||||
|
m_ParticleSystems.RemoveAt(i);
|
||||||
|
_uiParticles.Clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void Awake()
|
||||||
|
{
|
||||||
|
UpgradeIfNeeded();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnEnable()
|
||||||
|
{
|
||||||
|
UIParticleUpdater.Register(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnDisable()
|
||||||
|
{
|
||||||
|
UIParticleUpdater.Unregister(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnDestroy()
|
||||||
|
{
|
||||||
|
_uiParticles = null;
|
||||||
|
m_ParticleSystems = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal void Attract()
|
||||||
|
{
|
||||||
|
// Collect UIParticle if needed (same size as m_ParticleSystems)
|
||||||
|
CollectUIParticlesIfNeeded();
|
||||||
|
|
||||||
|
for (var particleIndex = 0; particleIndex < this.m_ParticleSystems.Count; particleIndex++)
|
||||||
|
{
|
||||||
|
var particleSystem = m_ParticleSystems[particleIndex];
|
||||||
|
|
||||||
|
// Skip: The ParticleSystem is not active
|
||||||
|
if (particleSystem == null || !particleSystem.gameObject.activeInHierarchy) continue;
|
||||||
|
|
||||||
|
// Skip: No active particles
|
||||||
|
var count = particleSystem.particleCount;
|
||||||
|
if (count == 0) continue;
|
||||||
|
|
||||||
|
var particles = ParticleSystemExtensions.GetParticleArray(count);
|
||||||
|
particleSystem.GetParticles(particles, count);
|
||||||
|
|
||||||
|
var uiParticle = _uiParticles[particleIndex];
|
||||||
|
var dstPos = this.GetDestinationPosition(uiParticle, particleSystem);
|
||||||
|
for (var i = 0; i < count; i++)
|
||||||
|
{
|
||||||
|
// Attracted
|
||||||
|
var p = particles[i];
|
||||||
|
if (0f < p.remainingLifetime && Vector3.Distance(p.position, dstPos) < this.m_DestinationRadius)
|
||||||
|
{
|
||||||
|
p.remainingLifetime = 0f;
|
||||||
|
particles[i] = p;
|
||||||
|
|
||||||
|
if (this.m_OnAttracted != null)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
this.m_OnAttracted.Invoke();
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
Debug.LogException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Calc attracting time
|
||||||
|
var delayTime = p.startLifetime * this.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 = this.GetAttractedPosition(p.position, dstPos, duration, time);
|
||||||
|
p.velocity *= 0.5f;
|
||||||
|
particles[i] = p;
|
||||||
|
}
|
||||||
|
|
||||||
|
particleSystem.SetParticles(particles, count);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private Vector3 GetDestinationPosition(UIParticle uiParticle, ParticleSystem particleSystem)
|
||||||
|
{
|
||||||
|
var isUI = uiParticle && uiParticle.enabled;
|
||||||
|
var psPos = particleSystem.transform.position;
|
||||||
|
var attractorPos = transform.position;
|
||||||
|
var dstPos = attractorPos;
|
||||||
|
var isLocalSpace = particleSystem.IsLocalSpace();
|
||||||
|
|
||||||
|
if (isLocalSpace)
|
||||||
|
{
|
||||||
|
dstPos = 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 CollectUIParticlesIfNeeded()
|
||||||
|
{
|
||||||
|
if (m_ParticleSystems.Count == 0 || _uiParticles.Count != 0) return;
|
||||||
|
|
||||||
|
// Expand capacity
|
||||||
|
if (_uiParticles.Capacity < m_ParticleSystems.Capacity)
|
||||||
|
{
|
||||||
|
_uiParticles.Capacity = m_ParticleSystems.Capacity;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Find UIParticle that controls the ParticleSystem
|
||||||
|
for (var i = 0; i < m_ParticleSystems.Count; i++)
|
||||||
|
{
|
||||||
|
var ps = m_ParticleSystems[i];
|
||||||
|
if (ps == null)
|
||||||
|
{
|
||||||
|
_uiParticles.Add(null);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
var uiParticle = ps.GetComponentInParent<UIParticle>(true);
|
||||||
|
_uiParticles.Add(uiParticle.particles.Contains(ps) ? uiParticle : null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#if UNITY_EDITOR
|
||||||
|
private void OnValidate()
|
||||||
|
{
|
||||||
|
_uiParticles.Clear();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void ISerializationCallbackReceiver.OnBeforeSerialize()
|
||||||
|
{
|
||||||
|
UpgradeIfNeeded();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ISerializationCallbackReceiver.OnAfterDeserialize()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
private void UpgradeIfNeeded()
|
||||||
|
{
|
||||||
|
// Multiple ParticleSystems support: from 'm_ParticleSystem' to 'm_ParticleSystems'
|
||||||
|
if (m_ParticleSystem != null)
|
||||||
|
{
|
||||||
|
if (!m_ParticleSystems.Contains(m_ParticleSystem))
|
||||||
|
{
|
||||||
|
m_ParticleSystems.Add(m_ParticleSystem);
|
||||||
|
}
|
||||||
|
|
||||||
|
m_ParticleSystem = null;
|
||||||
|
Debug.Log($"Upgraded!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,4 +1,10 @@
|
|||||||
using System;
|
#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 System.Collections.Generic;
|
||||||
using Coffee.UIParticleExtensions;
|
using Coffee.UIParticleExtensions;
|
||||||
using UnityEditor;
|
using UnityEditor;
|
||||||
@@ -25,28 +31,22 @@ namespace Coffee.UIExtensions
|
|||||||
private Material _currentMaterialForRendering;
|
private Material _currentMaterialForRendering;
|
||||||
private bool _delay;
|
private bool _delay;
|
||||||
private int _index;
|
private int _index;
|
||||||
|
private bool _isPrevStored;
|
||||||
private bool _isTrail;
|
private bool _isTrail;
|
||||||
private Bounds _lastBounds;
|
private Bounds _lastBounds;
|
||||||
private Material _modifiedMaterial;
|
private Material _modifiedMaterial;
|
||||||
private UIParticle _parent;
|
private UIParticle _parent;
|
||||||
private ParticleSystem _particleSystem;
|
private ParticleSystem _particleSystem;
|
||||||
private int _prevParticleCount;
|
private float _prevCanvasScale;
|
||||||
private Vector3 _prevPsPos;
|
private Vector3 _prevPsPos;
|
||||||
private Vector3 _prevScale;
|
private Vector3 _prevScale;
|
||||||
private Vector2Int _prevScreenSize;
|
private Vector2Int _prevScreenSize;
|
||||||
private float _prevCanvasScale;
|
private bool _preWarm;
|
||||||
private bool _prewarm;
|
|
||||||
private ParticleSystemRenderer _renderer;
|
private ParticleSystemRenderer _renderer;
|
||||||
|
|
||||||
public override Texture mainTexture
|
public override Texture mainTexture => _isTrail ? null : _particleSystem.GetTextureForSprite();
|
||||||
{
|
|
||||||
get { return _isTrail ? null : _particleSystem.GetTextureForSprite(); }
|
|
||||||
}
|
|
||||||
|
|
||||||
public override bool raycastTarget
|
public override bool raycastTarget => false;
|
||||||
{
|
|
||||||
get { return false; }
|
|
||||||
}
|
|
||||||
|
|
||||||
private Rect rootCanvasRect
|
private Rect rootCanvasRect
|
||||||
{
|
{
|
||||||
@@ -102,7 +102,6 @@ namespace Coffee.UIExtensions
|
|||||||
_parent = null;
|
_parent = null;
|
||||||
_particleSystem = null;
|
_particleSystem = null;
|
||||||
_renderer = null;
|
_renderer = null;
|
||||||
_prevParticleCount = 0;
|
|
||||||
if (0 <= index)
|
if (0 <= index)
|
||||||
{
|
{
|
||||||
_index = index;
|
_index = index;
|
||||||
@@ -112,8 +111,7 @@ namespace Coffee.UIExtensions
|
|||||||
if (this && isActiveAndEnabled)
|
if (this && isActiveAndEnabled)
|
||||||
{
|
{
|
||||||
material = null;
|
material = null;
|
||||||
workerMesh.Clear();
|
canvasRenderer.Clear();
|
||||||
canvasRenderer.SetMesh(workerMesh);
|
|
||||||
_lastBounds = new Bounds();
|
_lastBounds = new Bounds();
|
||||||
enabled = false;
|
enabled = false;
|
||||||
}
|
}
|
||||||
@@ -148,6 +146,7 @@ namespace Coffee.UIExtensions
|
|||||||
ModifiedMaterial.Remove(_modifiedMaterial);
|
ModifiedMaterial.Remove(_modifiedMaterial);
|
||||||
_modifiedMaterial = null;
|
_modifiedMaterial = null;
|
||||||
_currentMaterialForRendering = null;
|
_currentMaterialForRendering = null;
|
||||||
|
_isPrevStored = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static UIParticleRenderer AddRenderer(UIParticle parent, int index)
|
public static UIParticleRenderer AddRenderer(UIParticle parent, int index)
|
||||||
@@ -155,7 +154,7 @@ namespace Coffee.UIExtensions
|
|||||||
// Create renderer object.
|
// Create renderer object.
|
||||||
var go = new GameObject("[generated] UIParticleRenderer", typeof(UIParticleRenderer))
|
var go = new GameObject("[generated] UIParticleRenderer", typeof(UIParticleRenderer))
|
||||||
{
|
{
|
||||||
hideFlags = HideFlags.DontSave | HideFlags.NotEditable,
|
hideFlags = HideFlags.HideAndDontSave,
|
||||||
layer = parent.gameObject.layer
|
layer = parent.gameObject.layer
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -221,20 +220,20 @@ namespace Coffee.UIExtensions
|
|||||||
gameObject.layer = parent.gameObject.layer;
|
gameObject.layer = parent.gameObject.layer;
|
||||||
|
|
||||||
_particleSystem = ps;
|
_particleSystem = ps;
|
||||||
_prewarm = _particleSystem.main.prewarm;
|
_preWarm = _particleSystem.main.prewarm;
|
||||||
|
|
||||||
#if UNITY_EDITOR
|
#if UNITY_EDITOR
|
||||||
if (Application.isPlaying)
|
if (Application.isPlaying)
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
if (_particleSystem.isPlaying || _prewarm)
|
if (_particleSystem.isPlaying || _preWarm)
|
||||||
{
|
{
|
||||||
_particleSystem.Clear();
|
_particleSystem.Clear();
|
||||||
_particleSystem.Pause();
|
_particleSystem.Pause();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_renderer = ps.GetComponent<ParticleSystemRenderer>();
|
ps.TryGetComponent(out _renderer);
|
||||||
_renderer.enabled = false;
|
_renderer.enabled = false;
|
||||||
|
|
||||||
//_emitter = emitter;
|
//_emitter = emitter;
|
||||||
@@ -256,7 +255,6 @@ namespace Coffee.UIExtensions
|
|||||||
_prevScreenSize = new Vector2Int(Screen.width, Screen.height);
|
_prevScreenSize = new Vector2Int(Screen.width, Screen.height);
|
||||||
_prevCanvasScale = canvas ? canvas.scaleFactor : 1f;
|
_prevCanvasScale = canvas ? canvas.scaleFactor : 1f;
|
||||||
_delay = true;
|
_delay = true;
|
||||||
_prevParticleCount = 0;
|
|
||||||
|
|
||||||
canvasRenderer.SetTexture(null);
|
canvasRenderer.SetTexture(null);
|
||||||
|
|
||||||
@@ -331,23 +329,38 @@ namespace Coffee.UIExtensions
|
|||||||
|
|
||||||
// Bake mesh.
|
// Bake mesh.
|
||||||
Profiler.BeginSample("[UIParticleRenderer] Bake Mesh");
|
Profiler.BeginSample("[UIParticleRenderer] Bake Mesh");
|
||||||
if (_isTrail && _parent.canSimulate && 0 < s_CombineInstances[0].mesh.vertexCount)
|
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);
|
_renderer.BakeTrailsMesh(s_CombineInstances[0].mesh, bakeCamera, true);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
else if (_renderer.CanBakeMesh())
|
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);
|
_renderer.BakeMesh(s_CombineInstances[0].mesh, bakeCamera, true);
|
||||||
}
|
#endif
|
||||||
else
|
|
||||||
{
|
|
||||||
s_CombineInstances[0].mesh.Clear(false);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Too many vertices to render.
|
// Too many vertices to render.
|
||||||
if (65535 <= s_CombineInstances[0].mesh.vertexCount)
|
if (65535 <= s_CombineInstances[0].mesh.vertexCount)
|
||||||
{
|
{
|
||||||
s_CombineInstances[0].mesh.Clear(false);
|
|
||||||
Debug.LogErrorFormat(this,
|
Debug.LogErrorFormat(this,
|
||||||
"Too many vertices to render. index={0}, isTrail={1}, vertexCount={2}(>=65535)",
|
"Too many vertices to render. index={0}, isTrail={1}, vertexCount={2}(>=65535)",
|
||||||
_index,
|
_index,
|
||||||
@@ -405,6 +418,7 @@ namespace Coffee.UIExtensions
|
|||||||
c.b = c.b.LinearToGamma();
|
c.b = c.b.LinearToGamma();
|
||||||
s_Colors[i] = c;
|
s_Colors[i] = c;
|
||||||
}
|
}
|
||||||
|
|
||||||
workerMesh.SetColors(s_Colors);
|
workerMesh.SetColors(s_Colors);
|
||||||
Profiler.EndSample();
|
Profiler.EndSample();
|
||||||
}
|
}
|
||||||
@@ -459,7 +473,7 @@ namespace Coffee.UIExtensions
|
|||||||
SetMaterialDirty();
|
SetMaterialDirty();
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
UpdateMaterialProperties();
|
UpdateMaterialProperties();
|
||||||
if (_parent.useMeshSharing)
|
if (_parent.useMeshSharing)
|
||||||
{
|
{
|
||||||
@@ -482,12 +496,6 @@ namespace Coffee.UIExtensions
|
|||||||
s_Renderers.Clear();
|
s_Renderers.Clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
internal void UpdateParticleCount()
|
|
||||||
{
|
|
||||||
if (!_particleSystem) return;
|
|
||||||
_prevParticleCount = _particleSystem.particleCount;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Call to update the geometry of the Graphic onto the CanvasRenderer.
|
/// Call to update the geometry of the Graphic onto the CanvasRenderer.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -512,6 +520,14 @@ namespace Coffee.UIExtensions
|
|||||||
{
|
{
|
||||||
Profiler.BeginSample("[UIParticleRenderer] GetWorldScale");
|
Profiler.BeginSample("[UIParticleRenderer] GetWorldScale");
|
||||||
var scale = _parent.scale3DForCalc.GetScaled(_parent.parentScale);
|
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();
|
Profiler.EndSample();
|
||||||
return scale;
|
return scale;
|
||||||
}
|
}
|
||||||
@@ -546,10 +562,7 @@ namespace Coffee.UIExtensions
|
|||||||
return Matrix4x4.Scale(scale);
|
return Matrix4x4.Scale(scale);
|
||||||
case ParticleSystemSimulationSpace.Custom:
|
case ParticleSystemSimulationSpace.Custom:
|
||||||
return Matrix4x4.Translate(_particleSystem.main.customSimulationSpace.position.GetScaled(scale))
|
return Matrix4x4.Translate(_particleSystem.main.customSimulationSpace.position.GetScaled(scale))
|
||||||
//* Matrix4x4.Translate(wpos)
|
* Matrix4x4.Scale(scale);
|
||||||
* Matrix4x4.Scale(scale)
|
|
||||||
//* Matrix4x4.Translate(-wpos)
|
|
||||||
;
|
|
||||||
default:
|
default:
|
||||||
throw new NotSupportedException();
|
throw new NotSupportedException();
|
||||||
}
|
}
|
||||||
@@ -565,15 +578,16 @@ namespace Coffee.UIExtensions
|
|||||||
var screenSize = new Vector2Int(Screen.width, Screen.height);
|
var screenSize = new Vector2Int(Screen.width, Screen.height);
|
||||||
var isWorldSpace = _particleSystem.IsWorldSpace();
|
var isWorldSpace = _particleSystem.IsWorldSpace();
|
||||||
var canvasScale = _parent.canvas ? _parent.canvas.scaleFactor : 1f;
|
var canvasScale = _parent.canvas ? _parent.canvas.scaleFactor : 1f;
|
||||||
var resolutionChanged = _prevScreenSize != screenSize || _prevCanvasScale != canvasScale;
|
var resolutionChanged = _prevScreenSize != screenSize
|
||||||
if (resolutionChanged && isWorldSpace)
|
|| !Mathf.Approximately(_prevCanvasScale, canvasScale);
|
||||||
|
if (resolutionChanged && isWorldSpace && _isPrevStored)
|
||||||
{
|
{
|
||||||
// Update particle array size and get particles.
|
// Update particle array size and get particles.
|
||||||
var size = _particleSystem.particleCount;
|
var size = _particleSystem.particleCount;
|
||||||
var particles = ParticleSystemExtensions.GetParticleArray(size);
|
var particles = ParticleSystemExtensions.GetParticleArray(size);
|
||||||
_particleSystem.GetParticles(particles, size);
|
_particleSystem.GetParticles(particles, size);
|
||||||
|
|
||||||
// Resolusion resolver:
|
// Resolution resolver:
|
||||||
// (psPos / scale) / (prevPsPos / prevScale) -> psPos * scale.inv * prevPsPos.inv * prevScale
|
// (psPos / scale) / (prevPsPos / prevScale) -> psPos * scale.inv * prevPsPos.inv * prevScale
|
||||||
var modifier = psPos.GetScaled(
|
var modifier = psPos.GetScaled(
|
||||||
scale.Inverse(),
|
scale.Inverse(),
|
||||||
@@ -592,6 +606,7 @@ namespace Coffee.UIExtensions
|
|||||||
_delay = true;
|
_delay = true;
|
||||||
_prevScale = scale;
|
_prevScale = scale;
|
||||||
_prevPsPos = psPos;
|
_prevPsPos = psPos;
|
||||||
|
_isPrevStored = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
_prevCanvasScale = canvas ? canvas.scaleFactor : 1f;
|
_prevCanvasScale = canvas ? canvas.scaleFactor : 1f;
|
||||||
@@ -607,42 +622,25 @@ namespace Coffee.UIExtensions
|
|||||||
? Time.unscaledDeltaTime
|
? Time.unscaledDeltaTime
|
||||||
: Time.deltaTime;
|
: Time.deltaTime;
|
||||||
|
|
||||||
// Prewarm:
|
// Pre-warm:
|
||||||
if (0 < deltaTime && _prewarm)
|
if (0 < deltaTime && _preWarm)
|
||||||
{
|
{
|
||||||
deltaTime += main.duration;
|
deltaTime += main.duration;
|
||||||
_prewarm = false;
|
_preWarm = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// (COMMENT OUT) #231: Sub Emitters option is not work in editor playing
|
|
||||||
/*
|
|
||||||
// Emitted particles found.
|
|
||||||
if (_prevParticleCount != _particleSystem.particleCount)
|
|
||||||
{
|
|
||||||
var size = _particleSystem.particleCount;
|
|
||||||
var particles = ParticleSystemExtensions.GetParticleArray(size);
|
|
||||||
_particleSystem.GetParticles(particles, size);
|
|
||||||
for (var i = _prevParticleCount; i < size; i++)
|
|
||||||
{
|
|
||||||
var p = particles[i];
|
|
||||||
p.position = p.position.GetScaled(scale.Inverse());
|
|
||||||
particles[i] = p;
|
|
||||||
}
|
|
||||||
|
|
||||||
_particleSystem.SetParticles(particles, size);
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
// get world position.
|
// get world position.
|
||||||
var isLocalSpace = _particleSystem.IsLocalSpace();
|
var isLocalSpace = _particleSystem.IsLocalSpace();
|
||||||
var psTransform = _particleSystem.transform;
|
var psTransform = _particleSystem.transform;
|
||||||
|
var originLocalPosition = psTransform.localPosition;
|
||||||
|
var originLocalRotation = psTransform.localRotation;
|
||||||
var originWorldPosition = psTransform.position;
|
var originWorldPosition = psTransform.position;
|
||||||
var originWorldRotation = psTransform.rotation;
|
var originWorldRotation = psTransform.rotation;
|
||||||
var emission = _particleSystem.emission;
|
var emission = _particleSystem.emission;
|
||||||
var rateOverDistance = emission.enabled
|
var rateOverDistance = emission.enabled
|
||||||
&& 0 < emission.rateOverDistance.constant
|
&& 0 < emission.rateOverDistance.constant
|
||||||
&& 0 < emission.rateOverDistanceMultiplier;
|
&& 0 < emission.rateOverDistanceMultiplier;
|
||||||
if (rateOverDistance && !paused)
|
if (rateOverDistance && !paused && _isPrevStored)
|
||||||
{
|
{
|
||||||
// (For rate-over-distance emission,) Move to previous scaled position, simulate (delta = 0).
|
// (For rate-over-distance emission,) Move to previous scaled position, simulate (delta = 0).
|
||||||
var prevScaledPos = isLocalSpace
|
var prevScaledPos = isLocalSpace
|
||||||
@@ -658,7 +656,8 @@ namespace Coffee.UIExtensions
|
|||||||
: originWorldPosition.GetScaled(scale.Inverse());
|
: originWorldPosition.GetScaled(scale.Inverse());
|
||||||
psTransform.SetPositionAndRotation(scaledPos, originWorldRotation);
|
psTransform.SetPositionAndRotation(scaledPos, originWorldRotation);
|
||||||
_particleSystem.Simulate(deltaTime, false, false, false);
|
_particleSystem.Simulate(deltaTime, false, false, false);
|
||||||
psTransform.SetPositionAndRotation(originWorldPosition, originWorldRotation);
|
psTransform.localPosition = originLocalPosition;
|
||||||
|
psTransform.localRotation = originLocalRotation;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if UNITY_EDITOR
|
#if UNITY_EDITOR
|
||||||
@@ -11,10 +11,7 @@ namespace Coffee.UIExtensions
|
|||||||
private static readonly HashSet<int> s_UpdatedGroupIds = new HashSet<int>();
|
private static readonly HashSet<int> s_UpdatedGroupIds = new HashSet<int>();
|
||||||
private static int s_FrameCount;
|
private static int s_FrameCount;
|
||||||
|
|
||||||
public static int uiParticleCount
|
public static int uiParticleCount => s_ActiveParticles.Count;
|
||||||
{
|
|
||||||
get { return s_ActiveParticles.Count; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void Register(UIParticle particle)
|
public static void Register(UIParticle particle)
|
||||||
{
|
{
|
||||||
@@ -42,8 +39,9 @@ namespace Coffee.UIExtensions
|
|||||||
|
|
||||||
#if UNITY_EDITOR
|
#if UNITY_EDITOR
|
||||||
[InitializeOnLoadMethod]
|
[InitializeOnLoadMethod]
|
||||||
|
#else
|
||||||
|
[RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.BeforeSceneLoad)]
|
||||||
#endif
|
#endif
|
||||||
[RuntimeInitializeOnLoadMethod]
|
|
||||||
private static void InitializeOnLoad()
|
private static void InitializeOnLoad()
|
||||||
{
|
{
|
||||||
Canvas.willRenderCanvases -= Refresh;
|
Canvas.willRenderCanvases -= Refresh;
|
||||||
@@ -60,9 +58,8 @@ namespace Coffee.UIExtensions
|
|||||||
for (var i = 0; i < s_ActiveParticles.Count; i++)
|
for (var i = 0; i < s_ActiveParticles.Count; i++)
|
||||||
{
|
{
|
||||||
var uip = s_ActiveParticles[i];
|
var uip = s_ActiveParticles[i];
|
||||||
if (!uip || !uip.canvas || !uip.isPrimary || s_UpdatedGroupIds.Contains(uip.groupId)) continue;
|
if (!uip || !uip.canvas || !uip.isPrimary || !s_UpdatedGroupIds.Add(uip.groupId)) continue;
|
||||||
|
|
||||||
s_UpdatedGroupIds.Add(uip.groupId);
|
|
||||||
uip.UpdateTransformScale();
|
uip.UpdateTransformScale();
|
||||||
uip.UpdateRenderers();
|
uip.UpdateRenderers();
|
||||||
}
|
}
|
||||||
@@ -79,9 +76,8 @@ namespace Coffee.UIExtensions
|
|||||||
{
|
{
|
||||||
uip.UpdateRenderers();
|
uip.UpdateRenderers();
|
||||||
}
|
}
|
||||||
else if (!s_UpdatedGroupIds.Contains(uip.groupId))
|
else if (s_UpdatedGroupIds.Add(uip.groupId))
|
||||||
{
|
{
|
||||||
s_UpdatedGroupIds.Add(uip.groupId);
|
|
||||||
uip.UpdateRenderers();
|
uip.UpdateRenderers();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -93,15 +89,6 @@ namespace Coffee.UIExtensions
|
|||||||
{
|
{
|
||||||
s_ActiveAttractors[i].Attract();
|
s_ActiveAttractors[i].Attract();
|
||||||
}
|
}
|
||||||
|
|
||||||
// UpdateParticleCount.
|
|
||||||
for (var i = 0; i < s_ActiveParticles.Count; i++)
|
|
||||||
{
|
|
||||||
var uip = s_ActiveParticles[i];
|
|
||||||
if (!uip || !uip.canvas) continue;
|
|
||||||
|
|
||||||
uip.UpdateParticleCount();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void GetGroupedRenderers(int groupId, int index, List<UIParticleRenderer> results)
|
public static void GetGroupedRenderers(int groupId, int index, List<UIParticleRenderer> results)
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
@@ -109,6 +109,29 @@ namespace Coffee.UIParticleExtensions
|
|||||||
return s_TmpParticles;
|
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)
|
public static bool CanBakeMesh(this ParticleSystemRenderer self)
|
||||||
{
|
{
|
||||||
// #69: Editor crashes when mesh is set to null when `ParticleSystem.RenderMode = Mesh`
|
// #69: Editor crashes when mesh is set to null when `ParticleSystem.RenderMode = Mesh`
|
||||||
@@ -264,7 +287,7 @@ namespace Coffee.UIParticleExtensions
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#if !UNITY_2021_2_OR_NEWER || UNITY_2020_3_45 || UNITY_2020_3_46 || UNITY_2020_3_47 || UNITY_2020_3_48
|
#if !UNITY_2021_2_OR_NEWER && !UNITY_2020_3_45 && !UNITY_2020_3_46 && !UNITY_2020_3_47 && !UNITY_2020_3_48
|
||||||
public static T GetComponentInParent<T>(this Component self, bool includeInactive) where T : Component
|
public static T GetComponentInParent<T>(this Component self, bool includeInactive) where T : Component
|
||||||
{
|
{
|
||||||
if (!self) return null;
|
if (!self) return null;
|
||||||
@@ -1,8 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: 15e5409f0334e479e91e672ae14567d3
|
|
||||||
folderAsset: yes
|
|
||||||
DefaultImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -1,4 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: 064daa6b97d6846ec9334e98d642f081
|
|
||||||
DefaultImporter:
|
|
||||||
userData:
|
|
||||||
@@ -1,14 +0,0 @@
|
|||||||
{
|
|
||||||
"name": "Coffee.CFX_Demo_With_UIParticle",
|
|
||||||
"references": [
|
|
||||||
"Coffee.UIParticle"
|
|
||||||
],
|
|
||||||
"optionalUnityReferences": [],
|
|
||||||
"includePlatforms": [],
|
|
||||||
"excludePlatforms": [],
|
|
||||||
"allowUnsafeCode": false,
|
|
||||||
"overrideReferences": false,
|
|
||||||
"precompiledReferences": [],
|
|
||||||
"autoReferenced": true,
|
|
||||||
"defineConstraints": []
|
|
||||||
}
|
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: 67b89587ad4f645e18aa12053a6cc9b7
|
|
||||||
AssemblyDefinitionImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
||||||
@@ -1,87 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Reflection;
|
|
||||||
using UnityEngine;
|
|
||||||
using UnityEngine.SceneManagement;
|
|
||||||
using UnityEngine.UI;
|
|
||||||
using Object = UnityEngine.Object;
|
|
||||||
|
|
||||||
namespace Coffee.UIExtensions.Demo
|
|
||||||
{
|
|
||||||
public class CFX_Demo_With_UIParticle : MonoBehaviour
|
|
||||||
{
|
|
||||||
private MonoBehaviour _demo;
|
|
||||||
private Toggle _spawnOnUI;
|
|
||||||
private UIParticle _uiParticle;
|
|
||||||
|
|
||||||
// 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);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 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, Array.Empty<object>()) as GameObject;
|
|
||||||
if (!particle) return;
|
|
||||||
|
|
||||||
particle.transform.localScale = Vector3.one;
|
|
||||||
_uiParticle.SetParticleSystemInstance(particle);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static Object FindObjectOfType(string typeName)
|
|
||||||
{
|
|
||||||
var type = AppDomain.CurrentDomain.GetAssemblies()
|
|
||||||
.SelectMany(x => x.GetTypes())
|
|
||||||
.FirstOrDefault(x => x.Name == typeName);
|
|
||||||
|
|
||||||
return type == null ? null : FindObjectOfType(type);
|
|
||||||
}
|
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,11 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: a845100b226da488ab9037ad254b5860
|
|
||||||
MonoImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
serializedVersion: 2
|
|
||||||
defaultReferences: []
|
|
||||||
executionOrder: 0
|
|
||||||
icon: {instanceID: 0}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -1,7 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: 3432d66abba624d4fad1150154199656
|
|
||||||
PrefabImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
||||||
@@ -1,4 +0,0 @@
|
|||||||
Cartoon FX & War FX Demo
|
|
||||||
===
|
|
||||||
|
|
||||||
Please import assets "Cartoon FX Free" and/or "War FX Free" from Unity asset store.
|
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: 8f3407e8e4c3c4cf0a8717c25bc1c790
|
|
||||||
TextScriptImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -1,4 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: a81f9cd434f104e1fad7ffa20eb7a3d4
|
|
||||||
DefaultImporter:
|
|
||||||
userData:
|
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
using UnityEngine.Serialization;
|
using UnityEngine.Serialization;
|
||||||
|
|
||||||
namespace Coffee.UIExtensions.Demo
|
namespace Coffee.UIExtensions.Demo
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
using System;
|
using System;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
using UnityEngine.EventSystems;
|
using UnityEngine.EventSystems;
|
||||||
using UnityEngine.Serialization;
|
using UnityEngine.Serialization;
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
using UnityEngine.Serialization;
|
using UnityEngine.Serialization;
|
||||||
using UnityEngine.UI;
|
using UnityEngine.UI;
|
||||||
|
|
||||||
@@ -51,7 +51,11 @@ namespace Coffee.UIExtensions.Demo
|
|||||||
|
|
||||||
public void EnableAnimations(bool flag)
|
public void EnableAnimations(bool flag)
|
||||||
{
|
{
|
||||||
|
#if UNITY_2023_1_OR_NEWER
|
||||||
|
foreach (var animator in FindObjectsByType<Animator>(FindObjectsInactive.Include, FindObjectsSortMode.None))
|
||||||
|
#else
|
||||||
foreach (var animator in FindObjectsOfType<Animator>())
|
foreach (var animator in FindObjectsOfType<Animator>())
|
||||||
|
#endif
|
||||||
{
|
{
|
||||||
animator.enabled = flag;
|
animator.enabled = flag;
|
||||||
}
|
}
|
||||||
@@ -79,7 +83,11 @@ namespace Coffee.UIExtensions.Demo
|
|||||||
|
|
||||||
public void UIParticle_Scale(float scale)
|
public void UIParticle_Scale(float scale)
|
||||||
{
|
{
|
||||||
|
#if UNITY_2023_1_OR_NEWER
|
||||||
|
foreach (var uip in FindObjectsByType<UIParticle>(FindObjectsInactive.Include, FindObjectsSortMode.None))
|
||||||
|
#else
|
||||||
foreach (var uip in FindObjectsOfType<UIParticle>())
|
foreach (var uip in FindObjectsOfType<UIParticle>())
|
||||||
|
#endif
|
||||||
{
|
{
|
||||||
uip.scale = scale;
|
uip.scale = scale;
|
||||||
}
|
}
|
||||||
@@ -87,7 +95,11 @@ namespace Coffee.UIExtensions.Demo
|
|||||||
|
|
||||||
public void ParticleSystem_WorldSpaseSimulation(bool flag)
|
public void ParticleSystem_WorldSpaseSimulation(bool flag)
|
||||||
{
|
{
|
||||||
|
#if UNITY_2023_1_OR_NEWER
|
||||||
|
foreach (var p in FindObjectsByType<ParticleSystem>(FindObjectsInactive.Include, FindObjectsSortMode.None))
|
||||||
|
#else
|
||||||
foreach (var p in FindObjectsOfType<ParticleSystem>())
|
foreach (var p in FindObjectsOfType<ParticleSystem>())
|
||||||
|
#endif
|
||||||
{
|
{
|
||||||
var main = p.main;
|
var main = p.main;
|
||||||
main.simulationSpace = flag
|
main.simulationSpace = flag
|
||||||
@@ -123,7 +135,11 @@ namespace Coffee.UIExtensions.Demo
|
|||||||
|
|
||||||
public void ParticleSystem_SetScale(float scale)
|
public void ParticleSystem_SetScale(float scale)
|
||||||
{
|
{
|
||||||
|
#if UNITY_2023_1_OR_NEWER
|
||||||
|
foreach (var ps in FindObjectsByType<ParticleSystem>(FindObjectsInactive.Include, FindObjectsSortMode.None))
|
||||||
|
#else
|
||||||
foreach (var ps in FindObjectsOfType<ParticleSystem>())
|
foreach (var ps in FindObjectsOfType<ParticleSystem>())
|
||||||
|
#endif
|
||||||
{
|
{
|
||||||
ps.transform.localScale = new Vector3(scale, scale, scale);
|
ps.transform.localScale = new Vector3(scale, scale, scale);
|
||||||
}
|
}
|
||||||
@@ -155,26 +171,23 @@ namespace Coffee.UIExtensions.Demo
|
|||||||
{
|
{
|
||||||
if (!flag) return;
|
if (!flag) return;
|
||||||
|
|
||||||
var canvas = FindObjectOfType<Canvas>();
|
m_RootCanvas.renderMode = RenderMode.ScreenSpaceCamera;
|
||||||
canvas.renderMode = RenderMode.ScreenSpaceCamera;
|
m_RootCanvas.renderMode = RenderMode.WorldSpace;
|
||||||
canvas.renderMode = RenderMode.WorldSpace;
|
m_RootCanvas.transform.rotation = Quaternion.Euler(new Vector3(0, 10, 0));
|
||||||
canvas.transform.rotation = Quaternion.Euler(new Vector3(0, 10, 0));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Canvas_CameraSpace(bool flag)
|
public void Canvas_CameraSpace(bool flag)
|
||||||
{
|
{
|
||||||
if (!flag) return;
|
if (!flag) return;
|
||||||
|
|
||||||
var canvas = FindObjectOfType<Canvas>();
|
m_RootCanvas.renderMode = RenderMode.ScreenSpaceCamera;
|
||||||
canvas.renderMode = RenderMode.ScreenSpaceCamera;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Canvas_Overlay(bool flag)
|
public void Canvas_Overlay(bool flag)
|
||||||
{
|
{
|
||||||
if (!flag) return;
|
if (!flag) return;
|
||||||
|
|
||||||
var canvas = FindObjectOfType<Canvas>();
|
m_RootCanvas.renderMode = RenderMode.ScreenSpaceOverlay;
|
||||||
canvas.renderMode = RenderMode.ScreenSpaceOverlay;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
using UnityEngine.Serialization;
|
using UnityEngine.Serialization;
|
||||||
|
|
||||||
namespace Coffee.UIExtensions.Demo
|
namespace Coffee.UIExtensions.Demo
|
||||||
|
|||||||
@@ -42,12 +42,12 @@ TextureImporter:
|
|||||||
compressionQuality: 50
|
compressionQuality: 50
|
||||||
spriteMode: 1
|
spriteMode: 1
|
||||||
spriteExtrude: 1
|
spriteExtrude: 1
|
||||||
spriteMeshType: 1
|
spriteMeshType: 0
|
||||||
alignment: 0
|
alignment: 0
|
||||||
spritePivot: {x: 0.5, y: 0.5}
|
spritePivot: {x: 0.5, y: 0.5}
|
||||||
spritePixelsToUnits: 100
|
spritePixelsToUnits: 100
|
||||||
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
|
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
|
||||||
spriteGenerateFallbackPhysicsShape: 1
|
spriteGenerateFallbackPhysicsShape: 0
|
||||||
alphaUsage: 1
|
alphaUsage: 1
|
||||||
alphaIsTransparency: 1
|
alphaIsTransparency: 1
|
||||||
spriteTessellationDetail: -1
|
spriteTessellationDetail: -1
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ TextureImporter:
|
|||||||
generateCubemap: 6
|
generateCubemap: 6
|
||||||
cubemapConvolution: 0
|
cubemapConvolution: 0
|
||||||
seamlessCubemap: 0
|
seamlessCubemap: 0
|
||||||
textureFormat: 1
|
textureFormat: 4
|
||||||
maxTextureSize: 2048
|
maxTextureSize: 2048
|
||||||
textureSettings:
|
textureSettings:
|
||||||
serializedVersion: 2
|
serializedVersion: 2
|
||||||
@@ -42,12 +42,12 @@ TextureImporter:
|
|||||||
compressionQuality: 50
|
compressionQuality: 50
|
||||||
spriteMode: 1
|
spriteMode: 1
|
||||||
spriteExtrude: 1
|
spriteExtrude: 1
|
||||||
spriteMeshType: 1
|
spriteMeshType: 0
|
||||||
alignment: 0
|
alignment: 0
|
||||||
spritePivot: {x: 0.5, y: 0.5}
|
spritePivot: {x: 0.5, y: 0.5}
|
||||||
spritePixelsToUnits: 100
|
spritePixelsToUnits: 100
|
||||||
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
|
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
|
||||||
spriteGenerateFallbackPhysicsShape: 1
|
spriteGenerateFallbackPhysicsShape: 0
|
||||||
alphaUsage: 1
|
alphaUsage: 1
|
||||||
alphaIsTransparency: 1
|
alphaIsTransparency: 1
|
||||||
spriteTessellationDetail: -1
|
spriteTessellationDetail: -1
|
||||||
|
|||||||
@@ -42,12 +42,12 @@ TextureImporter:
|
|||||||
compressionQuality: 50
|
compressionQuality: 50
|
||||||
spriteMode: 1
|
spriteMode: 1
|
||||||
spriteExtrude: 1
|
spriteExtrude: 1
|
||||||
spriteMeshType: 1
|
spriteMeshType: 0
|
||||||
alignment: 0
|
alignment: 0
|
||||||
spritePivot: {x: 0.5, y: 0.5}
|
spritePivot: {x: 0.5, y: 0.5}
|
||||||
spritePixelsToUnits: 100
|
spritePixelsToUnits: 100
|
||||||
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
|
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
|
||||||
spriteGenerateFallbackPhysicsShape: 1
|
spriteGenerateFallbackPhysicsShape: 0
|
||||||
alphaUsage: 0
|
alphaUsage: 0
|
||||||
alphaIsTransparency: 1
|
alphaIsTransparency: 1
|
||||||
spriteTessellationDetail: -1
|
spriteTessellationDetail: -1
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ TextureImporter:
|
|||||||
generateCubemap: 6
|
generateCubemap: 6
|
||||||
cubemapConvolution: 0
|
cubemapConvolution: 0
|
||||||
seamlessCubemap: 0
|
seamlessCubemap: 0
|
||||||
textureFormat: -1
|
textureFormat: 4
|
||||||
maxTextureSize: 2048
|
maxTextureSize: 2048
|
||||||
textureSettings:
|
textureSettings:
|
||||||
serializedVersion: 2
|
serializedVersion: 2
|
||||||
@@ -42,12 +42,12 @@ TextureImporter:
|
|||||||
compressionQuality: 50
|
compressionQuality: 50
|
||||||
spriteMode: 1
|
spriteMode: 1
|
||||||
spriteExtrude: 1
|
spriteExtrude: 1
|
||||||
spriteMeshType: 1
|
spriteMeshType: 0
|
||||||
alignment: 0
|
alignment: 0
|
||||||
spritePivot: {x: 0.5, y: 0.5}
|
spritePivot: {x: 0.5, y: 0.5}
|
||||||
spritePixelsToUnits: 100
|
spritePixelsToUnits: 100
|
||||||
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
|
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
|
||||||
spriteGenerateFallbackPhysicsShape: 1
|
spriteGenerateFallbackPhysicsShape: 0
|
||||||
alphaUsage: 1
|
alphaUsage: 1
|
||||||
alphaIsTransparency: 1
|
alphaIsTransparency: 1
|
||||||
spriteTessellationDetail: -1
|
spriteTessellationDetail: -1
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -1,8 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: 839afb79f79094e6c942050ec5413ebf
|
|
||||||
folderAsset: yes
|
|
||||||
DefaultImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
||||||
@@ -1,88 +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_PerformanceDemo_Fire
|
|
||||||
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: 294c5667b05cc4edcac3885a5899cc65, 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
|
|
||||||
- _Glow: 1
|
|
||||||
- _InvFade: 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}
|
|
||||||
- _TintColor: {r: 1, g: 1, b: 1, a: 1}
|
|
||||||
@@ -1,8 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: 3dc66b79cada243e59bcaf09f804373d
|
|
||||||
NativeFormatImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
mainObjectFileID: 2100000
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
||||||
Binary file not shown.
|
Before Width: | Height: | Size: 585 KiB |
@@ -1,121 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: 294c5667b05cc4edcac3885a5899cc65
|
|
||||||
TextureImporter:
|
|
||||||
fileIDToRecycleName: {}
|
|
||||||
externalObjects: {}
|
|
||||||
serializedVersion: 9
|
|
||||||
mipmaps:
|
|
||||||
mipMapMode: 0
|
|
||||||
enableMipMap: 1
|
|
||||||
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: 2
|
|
||||||
aniso: 16
|
|
||||||
mipBias: -100
|
|
||||||
wrapU: -1
|
|
||||||
wrapV: -1
|
|
||||||
wrapW: -1
|
|
||||||
nPOTScale: 1
|
|
||||||
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: 0
|
|
||||||
spriteTessellationDetail: -1
|
|
||||||
textureType: 0
|
|
||||||
textureShape: 1
|
|
||||||
singleChannelComponent: 0
|
|
||||||
maxTextureSizeSet: 0
|
|
||||||
compressionQualitySet: 0
|
|
||||||
textureFormatSet: 0
|
|
||||||
platformSettings:
|
|
||||||
- serializedVersion: 2
|
|
||||||
buildTarget: DefaultTexturePlatform
|
|
||||||
maxTextureSize: 4096
|
|
||||||
resizeAlgorithm: 0
|
|
||||||
textureFormat: -1
|
|
||||||
textureCompression: 2
|
|
||||||
compressionQuality: 50
|
|
||||||
crunchedCompression: 0
|
|
||||||
allowsAlphaSplitting: 0
|
|
||||||
overridden: 0
|
|
||||||
androidETC2FallbackOverride: 0
|
|
||||||
- serializedVersion: 2
|
|
||||||
buildTarget: Standalone
|
|
||||||
maxTextureSize: 4096
|
|
||||||
resizeAlgorithm: 0
|
|
||||||
textureFormat: -1
|
|
||||||
textureCompression: 2
|
|
||||||
compressionQuality: 50
|
|
||||||
crunchedCompression: 0
|
|
||||||
allowsAlphaSplitting: 0
|
|
||||||
overridden: 0
|
|
||||||
androidETC2FallbackOverride: 0
|
|
||||||
- serializedVersion: 2
|
|
||||||
buildTarget: Android
|
|
||||||
maxTextureSize: 4096
|
|
||||||
resizeAlgorithm: 0
|
|
||||||
textureFormat: -1
|
|
||||||
textureCompression: 2
|
|
||||||
compressionQuality: 50
|
|
||||||
crunchedCompression: 0
|
|
||||||
allowsAlphaSplitting: 0
|
|
||||||
overridden: 0
|
|
||||||
androidETC2FallbackOverride: 0
|
|
||||||
- serializedVersion: 2
|
|
||||||
buildTarget: WebGL
|
|
||||||
maxTextureSize: 4096
|
|
||||||
resizeAlgorithm: 0
|
|
||||||
textureFormat: -1
|
|
||||||
textureCompression: 2
|
|
||||||
compressionQuality: 50
|
|
||||||
crunchedCompression: 0
|
|
||||||
allowsAlphaSplitting: 0
|
|
||||||
overridden: 0
|
|
||||||
androidETC2FallbackOverride: 0
|
|
||||||
spriteSheet:
|
|
||||||
serializedVersion: 2
|
|
||||||
sprites: []
|
|
||||||
outline: []
|
|
||||||
physicsShape: []
|
|
||||||
bones: []
|
|
||||||
spriteID:
|
|
||||||
vertices: []
|
|
||||||
indices:
|
|
||||||
edges: []
|
|
||||||
weights: []
|
|
||||||
spritePackingTag:
|
|
||||||
pSDRemoveMatte: 0
|
|
||||||
pSDShowRemoveMatteOption: 0
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
||||||
@@ -1,88 +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_PerformanceDemo_Spread
|
|
||||||
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: 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
|
|
||||||
- _Glow: 1
|
|
||||||
- _InvFade: 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}
|
|
||||||
- _TintColor: {r: 1, g: 1, b: 1, a: 1}
|
|
||||||
@@ -1,8 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: b7ac7640c2f1047c887aa52ff1ce9fcc
|
|
||||||
NativeFormatImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
mainObjectFileID: 2100000
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
||||||
@@ -1,8 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: c5a6b37697e71473cb1ecc90047622d0
|
|
||||||
folderAsset: yes
|
|
||||||
DefaultImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
||||||
@@ -1,8 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: b888c253a15224f1fa518bed74028211
|
|
||||||
folderAsset: yes
|
|
||||||
DefaultImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
||||||
Binary file not shown.
@@ -1,22 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: d07e6c2670f164cf7939ab011061a9bf
|
|
||||||
TrueTypeFontImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
serializedVersion: 4
|
|
||||||
fontSize: 26
|
|
||||||
forceTextureCase: 0
|
|
||||||
characterSpacing: 0
|
|
||||||
characterPadding: 1
|
|
||||||
includeFontData: 1
|
|
||||||
fontName: Share Tech Mono
|
|
||||||
fontNames:
|
|
||||||
- Share Tech Mono
|
|
||||||
fallbackFontReferences: []
|
|
||||||
customCharacters:
|
|
||||||
fontRenderingMode: 1
|
|
||||||
ascentCalculationMode: 1
|
|
||||||
useLegacyBoundsCalculation: 0
|
|
||||||
shouldRoundAdvanceValue: 1
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
||||||
@@ -1,8 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: fa6e3b593bf274861b2eab47082d9b1e
|
|
||||||
folderAsset: yes
|
|
||||||
DefaultImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -1,7 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: 784696794bc6345bc80bf49623581c2e
|
|
||||||
PrefabImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
||||||
@@ -1,8 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: f0b370726e57248da97c1c2f3bfd8bdf
|
|
||||||
folderAsset: yes
|
|
||||||
DefaultImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
||||||
@@ -1,12 +0,0 @@
|
|||||||
{
|
|
||||||
"name": "Coffee.NanoMonitor",
|
|
||||||
"references": [],
|
|
||||||
"optionalUnityReferences": [],
|
|
||||||
"includePlatforms": [],
|
|
||||||
"excludePlatforms": [],
|
|
||||||
"allowUnsafeCode": false,
|
|
||||||
"overrideReferences": false,
|
|
||||||
"precompiledReferences": [],
|
|
||||||
"autoReferenced": false,
|
|
||||||
"defineConstraints": []
|
|
||||||
}
|
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: 3d6cc132218a845708ce317bd33e5500
|
|
||||||
AssemblyDefinitionImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
||||||
@@ -1,296 +0,0 @@
|
|||||||
using System;
|
|
||||||
using UnityEngine;
|
|
||||||
using UnityEngine.Profiling;
|
|
||||||
using UnityEngine.Serialization;
|
|
||||||
using UnityEngine.UI;
|
|
||||||
#if UNITY_EDITOR
|
|
||||||
using UnityEditor;
|
|
||||||
using UnityEditorInternal;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
namespace Coffee.NanoMonitor
|
|
||||||
{
|
|
||||||
#if UNITY_EDITOR
|
|
||||||
[CustomEditor(typeof(NanoMonitor))]
|
|
||||||
internal class NanoMonitorEditor : Editor
|
|
||||||
{
|
|
||||||
private ReorderableList _monitorItemList;
|
|
||||||
|
|
||||||
private void OnEnable()
|
|
||||||
{
|
|
||||||
var items = serializedObject.FindProperty("m_CustomMonitorItems");
|
|
||||||
_monitorItemList = new ReorderableList(serializedObject, items)
|
|
||||||
{
|
|
||||||
draggable = false,
|
|
||||||
drawHeaderCallback = r =>
|
|
||||||
{
|
|
||||||
EditorGUI.LabelField(r, new GUIContent("Custom Monitor Items"));
|
|
||||||
},
|
|
||||||
drawElementCallback = (r, i, _, __) =>
|
|
||||||
{
|
|
||||||
EditorGUI.LabelField(new Rect(r.x, r.y, r.width, r.height - 2), GUIContent.none,
|
|
||||||
EditorStyles.textArea);
|
|
||||||
var labelWidth = EditorGUIUtility.labelWidth;
|
|
||||||
EditorGUIUtility.labelWidth = 80;
|
|
||||||
EditorGUI.PropertyField(new Rect(r.x + 2, r.y + 3, r.width - 4, r.height - 4),
|
|
||||||
items.GetArrayElementAtIndex(i), true);
|
|
||||||
EditorGUIUtility.labelWidth = labelWidth;
|
|
||||||
},
|
|
||||||
elementHeightCallback = i => EditorGUI.GetPropertyHeight(items.GetArrayElementAtIndex(i)) + 6
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
public override void OnInspectorGUI()
|
|
||||||
{
|
|
||||||
base.OnInspectorGUI();
|
|
||||||
|
|
||||||
_monitorItemList.DoLayoutList();
|
|
||||||
serializedObject.ApplyModifiedProperties();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
[DisallowMultipleComponent]
|
|
||||||
public sealed class NanoMonitor : MonoBehaviour
|
|
||||||
{
|
|
||||||
//################################
|
|
||||||
// Serialize Members.
|
|
||||||
//################################
|
|
||||||
// Settings
|
|
||||||
[Header("Settings")]
|
|
||||||
[SerializeField]
|
|
||||||
[Range(0.01f, 2f)]
|
|
||||||
private float m_Interval = 1f;
|
|
||||||
|
|
||||||
[SerializeField]
|
|
||||||
[Range(0, 3)]
|
|
||||||
private int m_Precision = 2;
|
|
||||||
|
|
||||||
[SerializeField]
|
|
||||||
private Font m_Font;
|
|
||||||
|
|
||||||
// Foldout
|
|
||||||
[Header("Foldout")]
|
|
||||||
[SerializeField]
|
|
||||||
private bool m_Opened;
|
|
||||||
|
|
||||||
[FormerlySerializedAs("m_Collapse")]
|
|
||||||
[SerializeField]
|
|
||||||
private GameObject m_FoldoutObject;
|
|
||||||
|
|
||||||
[SerializeField]
|
|
||||||
private Button m_OpenButton;
|
|
||||||
|
|
||||||
[SerializeField]
|
|
||||||
private Button m_CloseButton;
|
|
||||||
|
|
||||||
// View
|
|
||||||
[Header("View")]
|
|
||||||
[SerializeField]
|
|
||||||
private MonitorUI m_Fps;
|
|
||||||
|
|
||||||
[SerializeField]
|
|
||||||
private MonitorUI m_Gc;
|
|
||||||
|
|
||||||
[SerializeField]
|
|
||||||
private MonitorUI m_MonoUsage;
|
|
||||||
|
|
||||||
[SerializeField]
|
|
||||||
private MonitorUI m_UnityUsage;
|
|
||||||
|
|
||||||
[HideInInspector]
|
|
||||||
[SerializeField]
|
|
||||||
private CustomMonitorItem[] m_CustomMonitorItems = new CustomMonitorItem[0];
|
|
||||||
|
|
||||||
|
|
||||||
//################################
|
|
||||||
// Private Members.
|
|
||||||
//################################
|
|
||||||
private double _elapsed;
|
|
||||||
private double _fpsElapsed;
|
|
||||||
private int _frames;
|
|
||||||
|
|
||||||
private void Update()
|
|
||||||
{
|
|
||||||
_frames++;
|
|
||||||
_elapsed += Time.unscaledDeltaTime;
|
|
||||||
_fpsElapsed += Time.unscaledDeltaTime;
|
|
||||||
if (_elapsed < m_Interval) return;
|
|
||||||
|
|
||||||
if (m_Fps)
|
|
||||||
{
|
|
||||||
m_Fps.SetText("FPS: {0}", (int)(_frames / _fpsElapsed));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (m_Gc)
|
|
||||||
{
|
|
||||||
m_Gc.SetText("GC: {0}", GC.CollectionCount(0));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (m_MonoUsage)
|
|
||||||
{
|
|
||||||
var monoUsed = (Profiler.GetMonoUsedSizeLong() >> 10) / 1024f;
|
|
||||||
var monoTotal = (Profiler.GetMonoHeapSizeLong() >> 10) / 1024f;
|
|
||||||
if (m_Precision == 3)
|
|
||||||
{
|
|
||||||
m_MonoUsage.SetText("Mono: {0:N3}/{1:N3}MB", monoUsed, monoTotal);
|
|
||||||
}
|
|
||||||
else if (m_Precision == 2)
|
|
||||||
{
|
|
||||||
m_MonoUsage.SetText("Mono: {0:N2}/{1:N2}MB", monoUsed, monoTotal);
|
|
||||||
}
|
|
||||||
else if (m_Precision == 1)
|
|
||||||
{
|
|
||||||
m_MonoUsage.SetText("Mono: {0:N1}/{1:N1}MB", monoUsed, monoTotal);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
m_MonoUsage.SetText("Mono: {0:N0}/{1:N0}MB", monoUsed, monoTotal);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (m_UnityUsage)
|
|
||||||
{
|
|
||||||
var unityUsed = (Profiler.GetTotalAllocatedMemoryLong() >> 10) / 1024f;
|
|
||||||
var unityTotal = (Profiler.GetTotalReservedMemoryLong() >> 10) / 1024f;
|
|
||||||
if (m_Precision == 3)
|
|
||||||
{
|
|
||||||
m_UnityUsage.SetText("Unity: {0:N3}/{1:N3}MB", unityUsed, unityTotal);
|
|
||||||
}
|
|
||||||
else if (m_Precision == 2)
|
|
||||||
{
|
|
||||||
m_UnityUsage.SetText("Unity: {0:N2}/{1:N2}MB", unityUsed, unityTotal);
|
|
||||||
}
|
|
||||||
else if (m_Precision == 1)
|
|
||||||
{
|
|
||||||
m_UnityUsage.SetText("Unity: {0:N1}/{1:N1}MB", unityUsed, unityTotal);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
m_UnityUsage.SetText("Unity: {0:N0}/{1:N0}MB", unityUsed, unityTotal);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach (var item in m_CustomMonitorItems)
|
|
||||||
{
|
|
||||||
item.UpdateText();
|
|
||||||
}
|
|
||||||
|
|
||||||
_frames = 0;
|
|
||||||
_elapsed %= m_Interval;
|
|
||||||
_fpsElapsed = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//################################
|
|
||||||
// Unity Callbacks.
|
|
||||||
//################################
|
|
||||||
private void OnEnable()
|
|
||||||
{
|
|
||||||
if (m_OpenButton)
|
|
||||||
{
|
|
||||||
m_OpenButton.onClick.AddListener(Open);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (m_CloseButton)
|
|
||||||
{
|
|
||||||
m_CloseButton.onClick.AddListener(Close);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (m_Opened)
|
|
||||||
{
|
|
||||||
Open();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Close();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void OnDisable()
|
|
||||||
{
|
|
||||||
if (m_OpenButton)
|
|
||||||
{
|
|
||||||
m_OpenButton.onClick.RemoveListener(Open);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (m_CloseButton)
|
|
||||||
{
|
|
||||||
m_CloseButton.onClick.RemoveListener(Close);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#if UNITY_EDITOR
|
|
||||||
private void OnValidate()
|
|
||||||
{
|
|
||||||
if (m_Font)
|
|
||||||
{
|
|
||||||
foreach (var ui in GetComponentsInChildren<MonitorUI>(true))
|
|
||||||
{
|
|
||||||
ui.font = m_Font;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (m_Opened)
|
|
||||||
{
|
|
||||||
Open();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Close();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
//################################
|
|
||||||
// Public Members.
|
|
||||||
//################################
|
|
||||||
public void Clean()
|
|
||||||
{
|
|
||||||
Resources.UnloadUnusedAssets();
|
|
||||||
GC.Collect();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void Open()
|
|
||||||
{
|
|
||||||
_frames = 0;
|
|
||||||
_elapsed = m_Interval;
|
|
||||||
_fpsElapsed = 0;
|
|
||||||
|
|
||||||
if (m_FoldoutObject)
|
|
||||||
{
|
|
||||||
m_FoldoutObject.SetActive(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (m_CloseButton)
|
|
||||||
{
|
|
||||||
m_CloseButton.gameObject.SetActive(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (m_OpenButton)
|
|
||||||
{
|
|
||||||
m_OpenButton.gameObject.SetActive(false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void Close()
|
|
||||||
{
|
|
||||||
if (m_FoldoutObject)
|
|
||||||
{
|
|
||||||
m_FoldoutObject.SetActive(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (m_CloseButton)
|
|
||||||
{
|
|
||||||
m_CloseButton.gameObject.SetActive(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (m_OpenButton)
|
|
||||||
{
|
|
||||||
m_OpenButton.gameObject.SetActive(true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,11 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: 19e83f45e7d5648f2bd10122dc7fed14
|
|
||||||
MonoImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
serializedVersion: 2
|
|
||||||
defaultReferences: []
|
|
||||||
executionOrder: 0
|
|
||||||
icon: {instanceID: 0}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
||||||
@@ -1,8 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: affee221821a14cfb842a0b0e8514a4e
|
|
||||||
folderAsset: yes
|
|
||||||
DefaultImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
||||||
@@ -1,160 +0,0 @@
|
|||||||
using System.Collections.Generic;
|
|
||||||
using UnityEngine;
|
|
||||||
using UnityEngine.UI;
|
|
||||||
|
|
||||||
namespace Coffee.NanoMonitor
|
|
||||||
{
|
|
||||||
public class FixedFont
|
|
||||||
{
|
|
||||||
private const string k_Characters =
|
|
||||||
"_!\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~";
|
|
||||||
|
|
||||||
private static readonly Dictionary<Font, FixedFont> s_Fonts = new Dictionary<Font, FixedFont>();
|
|
||||||
private static readonly TextGenerator s_TextGenerator = new TextGenerator(100);
|
|
||||||
|
|
||||||
private static TextGenerationSettings s_Settings = new TextGenerationSettings
|
|
||||||
{
|
|
||||||
scaleFactor = 1,
|
|
||||||
horizontalOverflow = HorizontalWrapMode.Overflow,
|
|
||||||
verticalOverflow = VerticalWrapMode.Overflow,
|
|
||||||
alignByGeometry = true,
|
|
||||||
textAnchor = TextAnchor.MiddleCenter,
|
|
||||||
color = Color.white
|
|
||||||
};
|
|
||||||
|
|
||||||
private readonly Font _font;
|
|
||||||
private readonly UIVertex[] _tmpVerts = new UIVertex[4];
|
|
||||||
private UICharInfo[] _charInfos;
|
|
||||||
|
|
||||||
private int _resolution;
|
|
||||||
private UIVertex[] _verts;
|
|
||||||
|
|
||||||
private FixedFont(Font font)
|
|
||||||
{
|
|
||||||
_font = font;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int fontSize
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
return _font.dynamic ? 32 : _font.fontSize;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static FixedFont GetOrCreate(Font font)
|
|
||||||
{
|
|
||||||
if (font == null) return null;
|
|
||||||
if (s_Fonts.TryGetValue(font, out var data)) return data;
|
|
||||||
|
|
||||||
data = new FixedFont(font);
|
|
||||||
s_Fonts.Add(font, data);
|
|
||||||
return data;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Invalidate()
|
|
||||||
{
|
|
||||||
_resolution = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void UpdateFont()
|
|
||||||
{
|
|
||||||
if (!_font) return;
|
|
||||||
|
|
||||||
var mat = _font.material;
|
|
||||||
if (!mat) return;
|
|
||||||
|
|
||||||
var tex = mat.mainTexture;
|
|
||||||
if (!tex) return;
|
|
||||||
|
|
||||||
var currentResolution = tex.width * tex.height;
|
|
||||||
|
|
||||||
if (_resolution == currentResolution) return;
|
|
||||||
_resolution = currentResolution;
|
|
||||||
|
|
||||||
s_Settings.font = _font;
|
|
||||||
s_TextGenerator.Invalidate();
|
|
||||||
s_TextGenerator.Populate(k_Characters, s_Settings);
|
|
||||||
|
|
||||||
_verts = s_TextGenerator.GetVerticesArray();
|
|
||||||
_charInfos = s_TextGenerator.GetCharactersArray();
|
|
||||||
|
|
||||||
float offsetX = 0;
|
|
||||||
for (var i = 0; i < _verts.Length; i++)
|
|
||||||
{
|
|
||||||
if ((i & 3) == 0)
|
|
||||||
{
|
|
||||||
offsetX = _verts[i].position.x;
|
|
||||||
}
|
|
||||||
|
|
||||||
var v = _verts[i];
|
|
||||||
v.position -= new Vector3(offsetX, 0);
|
|
||||||
_verts[i] = v;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public float Layout(char c, float offset, float scale)
|
|
||||||
{
|
|
||||||
if (_charInfos == null) return offset;
|
|
||||||
if (c < 0x20 || 0x7e < c) return offset;
|
|
||||||
var ci = c - 0x20;
|
|
||||||
|
|
||||||
return offset + _charInfos[ci].charWidth * scale;
|
|
||||||
}
|
|
||||||
|
|
||||||
public float Append(VertexHelper toFill, char c, float offset, float scale, Color color)
|
|
||||||
{
|
|
||||||
if (_verts == null || _charInfos == null) return offset;
|
|
||||||
if (c < 0x20 || 0x7e < c) return offset;
|
|
||||||
var ci = c - 0x20;
|
|
||||||
|
|
||||||
for (var i = 0; i < 4; i++)
|
|
||||||
{
|
|
||||||
_tmpVerts[i] = _verts[ci * 4 + i];
|
|
||||||
_tmpVerts[i].position = _tmpVerts[i].position * scale + new Vector3(offset, 0);
|
|
||||||
_tmpVerts[i].color = ci == 0 ? Color.clear : color;
|
|
||||||
}
|
|
||||||
|
|
||||||
toFill.AddUIVertexQuad(_tmpVerts);
|
|
||||||
return offset + _charInfos[ci].charWidth * scale;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Fill(VertexHelper toFill, Color color, RectTransform tr)
|
|
||||||
{
|
|
||||||
if (_verts == null || _charInfos == null) return;
|
|
||||||
const int ci = '*' - 0x20;
|
|
||||||
var uv = (_verts[ci * 4].uv0 + _verts[ci * 4 + 2].uv0) / 2;
|
|
||||||
|
|
||||||
var rect = tr.rect;
|
|
||||||
var size = rect.size / 2;
|
|
||||||
var offset = (new Vector2(0.5f, 0.5f) - tr.pivot) * rect.size;
|
|
||||||
|
|
||||||
for (var i = 0; i < 4; i++)
|
|
||||||
{
|
|
||||||
_tmpVerts[i] = new UIVertex
|
|
||||||
{
|
|
||||||
uv0 = uv,
|
|
||||||
color = color
|
|
||||||
};
|
|
||||||
|
|
||||||
switch (i)
|
|
||||||
{
|
|
||||||
case 0:
|
|
||||||
_tmpVerts[i].position = new Vector2(-size.x, -size.y) + offset;
|
|
||||||
break;
|
|
||||||
case 1:
|
|
||||||
_tmpVerts[i].position = new Vector2(-size.x, size.y) + offset;
|
|
||||||
break;
|
|
||||||
case 2:
|
|
||||||
_tmpVerts[i].position = new Vector2(size.x, size.y) + offset;
|
|
||||||
break;
|
|
||||||
case 3:
|
|
||||||
_tmpVerts[i].position = new Vector2(size.x, -size.y) + offset;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
toFill.AddUIVertexQuad(_tmpVerts);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,12 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: 9a8c5c555d4bf4361ab3435c318c0699
|
|
||||||
MonoImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
serializedVersion: 2
|
|
||||||
defaultReferences:
|
|
||||||
- m_Material: {fileID: 2100000, guid: 4da4639f724144ddead57bffca64e71f, type: 3}
|
|
||||||
executionOrder: 0
|
|
||||||
icon: {instanceID: 0}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
||||||
@@ -1,239 +0,0 @@
|
|||||||
using System.Text;
|
|
||||||
using UnityEditor;
|
|
||||||
using UnityEngine;
|
|
||||||
using UnityEngine.UI;
|
|
||||||
|
|
||||||
namespace Coffee.NanoMonitor
|
|
||||||
{
|
|
||||||
#if UNITY_EDITOR
|
|
||||||
[CustomEditor(typeof(MonitorUI))]
|
|
||||||
public class MonitorTextEditor : Editor
|
|
||||||
{
|
|
||||||
private SerializedProperty _color;
|
|
||||||
private SerializedProperty _font;
|
|
||||||
private SerializedProperty _fontSize;
|
|
||||||
private SerializedProperty _mode;
|
|
||||||
private SerializedProperty _text;
|
|
||||||
private SerializedProperty _textAnchor;
|
|
||||||
|
|
||||||
private void OnEnable()
|
|
||||||
{
|
|
||||||
_mode = serializedObject.FindProperty("m_Mode");
|
|
||||||
_text = serializedObject.FindProperty("m_Text");
|
|
||||||
_color = serializedObject.FindProperty("m_Color");
|
|
||||||
var fontData = serializedObject.FindProperty("m_FontData");
|
|
||||||
_fontSize = fontData.FindPropertyRelative("m_FontSize");
|
|
||||||
_font = fontData.FindPropertyRelative("m_Font");
|
|
||||||
_textAnchor = serializedObject.FindProperty("m_TextAnchor");
|
|
||||||
}
|
|
||||||
|
|
||||||
public override void OnInspectorGUI()
|
|
||||||
{
|
|
||||||
serializedObject.Update();
|
|
||||||
|
|
||||||
EditorGUILayout.PropertyField(_mode);
|
|
||||||
if ((MonitorUI.Mode)_mode.intValue == MonitorUI.Mode.Text)
|
|
||||||
{
|
|
||||||
EditorGUILayout.PropertyField(_text);
|
|
||||||
EditorGUILayout.PropertyField(_fontSize);
|
|
||||||
EditorGUILayout.PropertyField(_textAnchor);
|
|
||||||
EditorGUILayout.PropertyField(_font);
|
|
||||||
}
|
|
||||||
|
|
||||||
EditorGUILayout.PropertyField(_color);
|
|
||||||
|
|
||||||
serializedObject.ApplyModifiedProperties();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
public class MonitorUI : Text
|
|
||||||
{
|
|
||||||
public enum Mode
|
|
||||||
{
|
|
||||||
Text,
|
|
||||||
Fill
|
|
||||||
}
|
|
||||||
|
|
||||||
public enum TextAnchor
|
|
||||||
{
|
|
||||||
Left,
|
|
||||||
Center,
|
|
||||||
Right
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//################################
|
|
||||||
// Serialize Members.
|
|
||||||
//################################
|
|
||||||
[SerializeField] private Mode m_Mode = Mode.Text;
|
|
||||||
[SerializeField] private TextAnchor m_TextAnchor;
|
|
||||||
|
|
||||||
|
|
||||||
//################################
|
|
||||||
// Private Members.
|
|
||||||
//################################
|
|
||||||
private readonly StringBuilder _sb = new StringBuilder(64);
|
|
||||||
|
|
||||||
|
|
||||||
//################################
|
|
||||||
// Public Members.
|
|
||||||
//################################
|
|
||||||
public override string text
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
return _sb.ToString();
|
|
||||||
}
|
|
||||||
set
|
|
||||||
{
|
|
||||||
m_Text = value;
|
|
||||||
if (_sb.IsEqual(m_Text)) return;
|
|
||||||
|
|
||||||
_sb.Length = 0;
|
|
||||||
_sb.Append(m_Text);
|
|
||||||
SetVerticesDirty();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public TextAnchor textAnchor
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
return m_TextAnchor;
|
|
||||||
}
|
|
||||||
set
|
|
||||||
{
|
|
||||||
if (m_TextAnchor == value) return;
|
|
||||||
|
|
||||||
m_TextAnchor = value;
|
|
||||||
SetVerticesDirty();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public override bool raycastTarget
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
return m_Mode == Mode.Fill;
|
|
||||||
}
|
|
||||||
set { }
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//################################
|
|
||||||
// Unity Callbacks.
|
|
||||||
//################################
|
|
||||||
protected override void OnEnable()
|
|
||||||
{
|
|
||||||
RegisterDirtyMaterialCallback(UpdateFont);
|
|
||||||
|
|
||||||
base.OnEnable();
|
|
||||||
raycastTarget = false;
|
|
||||||
maskable = false;
|
|
||||||
_sb.Length = 0;
|
|
||||||
_sb.Append(m_Text);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override void OnDisable()
|
|
||||||
{
|
|
||||||
UnregisterDirtyMaterialCallback(UpdateFont);
|
|
||||||
|
|
||||||
base.OnDisable();
|
|
||||||
}
|
|
||||||
|
|
||||||
#if UNITY_EDITOR
|
|
||||||
protected override void OnValidate()
|
|
||||||
{
|
|
||||||
base.OnValidate();
|
|
||||||
|
|
||||||
if (!_sb.IsEqual(m_Text))
|
|
||||||
{
|
|
||||||
_sb.Length = 0;
|
|
||||||
_sb.Append(m_Text);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
public void SetText(string format, double arg0 = 0, double arg1 = 0, double arg2 = 0, double arg3 = 0)
|
|
||||||
{
|
|
||||||
_sb.Length = 0;
|
|
||||||
_sb.AppendFormatNoAlloc(format, arg0, arg1, arg2, arg3);
|
|
||||||
SetVerticesDirty();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void SetText(StringBuilder builder)
|
|
||||||
{
|
|
||||||
_sb.Length = 0;
|
|
||||||
_sb.Append(builder);
|
|
||||||
SetVerticesDirty();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void UpdateFont()
|
|
||||||
{
|
|
||||||
var fontData = FixedFont.GetOrCreate(font);
|
|
||||||
if (fontData != null)
|
|
||||||
{
|
|
||||||
fontData.Invalidate();
|
|
||||||
fontData.UpdateFont();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override void OnPopulateMesh(VertexHelper toFill)
|
|
||||||
{
|
|
||||||
toFill.Clear();
|
|
||||||
|
|
||||||
var fontData = FixedFont.GetOrCreate(font);
|
|
||||||
if (fontData == null) return;
|
|
||||||
|
|
||||||
fontData.UpdateFont();
|
|
||||||
|
|
||||||
if (m_Mode == Mode.Fill)
|
|
||||||
{
|
|
||||||
fontData.Fill(toFill, color, rectTransform);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
var scale = (float)fontSize / fontData.fontSize;
|
|
||||||
float offset = 0;
|
|
||||||
switch (textAnchor)
|
|
||||||
{
|
|
||||||
case TextAnchor.Left:
|
|
||||||
offset = rectTransform.rect.xMin;
|
|
||||||
break;
|
|
||||||
case TextAnchor.Center:
|
|
||||||
for (var i = 0; i < _sb.Length; i++)
|
|
||||||
{
|
|
||||||
offset = fontData.Layout(_sb[i], offset, scale);
|
|
||||||
}
|
|
||||||
|
|
||||||
offset = -offset / 2;
|
|
||||||
break;
|
|
||||||
case TextAnchor.Right:
|
|
||||||
for (var i = 0; i < _sb.Length; i++)
|
|
||||||
{
|
|
||||||
offset = fontData.Layout(_sb[i], offset, scale);
|
|
||||||
}
|
|
||||||
|
|
||||||
offset = rectTransform.rect.xMax - offset;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (var i = 0; i < _sb.Length; i++)
|
|
||||||
{
|
|
||||||
offset = fontData.Append(toFill, _sb[i], offset, scale, color);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override void UpdateMaterial()
|
|
||||||
{
|
|
||||||
base.UpdateMaterial();
|
|
||||||
|
|
||||||
var fontData = FixedFont.GetOrCreate(font);
|
|
||||||
if (fontData != null)
|
|
||||||
{
|
|
||||||
fontData.UpdateFont();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,12 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: b0e08c6080a2e4d8186f97c60518830f
|
|
||||||
MonoImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
serializedVersion: 2
|
|
||||||
defaultReferences:
|
|
||||||
- m_Material: {fileID: 2100000, guid: 4da4639f724144ddead57bffca64e71f, type: 3}
|
|
||||||
executionOrder: 0
|
|
||||||
icon: {instanceID: 0}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
||||||
@@ -1,8 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: 1051ed7e3f1474ed59ca41b33b00029b
|
|
||||||
folderAsset: yes
|
|
||||||
DefaultImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
||||||
@@ -1,55 +0,0 @@
|
|||||||
using System;
|
|
||||||
using UnityEngine;
|
|
||||||
#if UNITY_EDITOR
|
|
||||||
using UnityEditor;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
namespace Coffee.NanoMonitor
|
|
||||||
{
|
|
||||||
#if UNITY_EDITOR
|
|
||||||
[CustomPropertyDrawer(typeof(CustomMonitorItem))]
|
|
||||||
internal sealed class CustomMonitorItemDrawer : PropertyDrawer
|
|
||||||
{
|
|
||||||
public override void OnGUI(Rect p, SerializedProperty property, GUIContent label)
|
|
||||||
{
|
|
||||||
var pos = new Rect(p.x, p.y + 18 * 0, p.width, 16);
|
|
||||||
EditorGUI.PropertyField(pos, property.FindPropertyRelative("m_Text"));
|
|
||||||
pos.y += 18;
|
|
||||||
EditorGUI.PropertyField(pos, property.FindPropertyRelative("m_Format"));
|
|
||||||
pos.y += 18;
|
|
||||||
EditorGUI.indentLevel++;
|
|
||||||
EditorGUI.PropertyField(pos, property.FindPropertyRelative("m_Arg0"));
|
|
||||||
pos.y += 18;
|
|
||||||
EditorGUI.PropertyField(pos, property.FindPropertyRelative("m_Arg1"));
|
|
||||||
pos.y += 18;
|
|
||||||
EditorGUI.PropertyField(pos, property.FindPropertyRelative("m_Arg2"));
|
|
||||||
EditorGUI.indentLevel--;
|
|
||||||
|
|
||||||
property.serializedObject.ApplyModifiedProperties();
|
|
||||||
}
|
|
||||||
|
|
||||||
public override float GetPropertyHeight(SerializedProperty property, GUIContent label)
|
|
||||||
{
|
|
||||||
return (EditorGUIUtility.singleLineHeight + 2) * 5;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
[Serializable]
|
|
||||||
public class CustomMonitorItem
|
|
||||||
{
|
|
||||||
[SerializeField] private MonitorUI m_Text;
|
|
||||||
[SerializeField] private string m_Format = "";
|
|
||||||
[SerializeField] private NumericProperty m_Arg0;
|
|
||||||
[SerializeField] private NumericProperty m_Arg1;
|
|
||||||
[SerializeField] private NumericProperty m_Arg2;
|
|
||||||
|
|
||||||
public void UpdateText()
|
|
||||||
{
|
|
||||||
if (m_Text)
|
|
||||||
{
|
|
||||||
m_Text.SetText(m_Format, m_Arg0.Get(), m_Arg1.Get(), m_Arg2.Get());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,11 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: 5c50c6434f4ad4488bfc5b0928dbb4c4
|
|
||||||
MonoImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
serializedVersion: 2
|
|
||||||
defaultReferences: []
|
|
||||||
executionOrder: 0
|
|
||||||
icon: {instanceID: 0}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
||||||
@@ -1,236 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Reflection;
|
|
||||||
using UnityEditor;
|
|
||||||
using UnityEngine;
|
|
||||||
|
|
||||||
namespace Coffee.NanoMonitor
|
|
||||||
{
|
|
||||||
#if UNITY_EDITOR
|
|
||||||
[CustomPropertyDrawer(typeof(NumericProperty))]
|
|
||||||
internal sealed class NumericPropertyDrawer : PropertyDrawer
|
|
||||||
{
|
|
||||||
private static Action<PropertyInfo> s_OnMenuSelected;
|
|
||||||
private static GenericMenu s_PropertyMenu;
|
|
||||||
|
|
||||||
private static readonly Dictionary<Type, string> s_SupportedTypes = new Dictionary<Type, string>
|
|
||||||
{
|
|
||||||
{ typeof(bool), "bool" },
|
|
||||||
{ typeof(sbyte), "sbyte" },
|
|
||||||
{ typeof(short), "short" },
|
|
||||||
{ typeof(int), "int" },
|
|
||||||
{ typeof(long), "long" },
|
|
||||||
{ typeof(byte), "byte" },
|
|
||||||
{ typeof(ushort), "ushort" },
|
|
||||||
{ typeof(uint), "uint" },
|
|
||||||
{ typeof(ulong), "ulong" },
|
|
||||||
{ typeof(float), "float" },
|
|
||||||
{ typeof(double), "double" },
|
|
||||||
{ typeof(decimal), "decimal" }
|
|
||||||
};
|
|
||||||
|
|
||||||
private static void Init()
|
|
||||||
{
|
|
||||||
if (s_PropertyMenu != null) return;
|
|
||||||
|
|
||||||
const BindingFlags bindingFlags = BindingFlags.Public
|
|
||||||
| BindingFlags.NonPublic
|
|
||||||
| BindingFlags.Static
|
|
||||||
| BindingFlags.GetProperty;
|
|
||||||
var properties = AppDomain.CurrentDomain.GetAssemblies()
|
|
||||||
.SelectMany(assembly => assembly.GetTypes())
|
|
||||||
.SelectMany(type => type.GetProperties(bindingFlags))
|
|
||||||
.Where(pi => pi.GetMethod != null && s_SupportedTypes.ContainsKey(pi.PropertyType))
|
|
||||||
.OrderBy(pi => ConvertToMenuItem(pi, false))
|
|
||||||
.ToArray();
|
|
||||||
|
|
||||||
s_PropertyMenu = new GenericMenu();
|
|
||||||
s_PropertyMenu.AddItem(new GUIContent("No Property"), false,
|
|
||||||
arg => s_OnMenuSelected?.Invoke(arg as PropertyInfo), null);
|
|
||||||
s_PropertyMenu.AddItem(new GUIContent("(Non Public Properties)/"), false, () => { });
|
|
||||||
s_PropertyMenu.AddSeparator("");
|
|
||||||
|
|
||||||
foreach (var pi in properties)
|
|
||||||
{
|
|
||||||
s_PropertyMenu.AddItem(new GUIContent(ConvertToMenuItem(pi, true)), false,
|
|
||||||
arg => s_OnMenuSelected?.Invoke(arg as PropertyInfo), pi);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static string ConvertToMenuItem(PropertyInfo p, bool propertyType)
|
|
||||||
{
|
|
||||||
var type = p.DeclaringType;
|
|
||||||
if (type == null) return "";
|
|
||||||
|
|
||||||
var category = p.GetMethod.IsPublic && type.IsPublic
|
|
||||||
? ""
|
|
||||||
: "(Non Public Properties)/";
|
|
||||||
var typeName = type.FullName;
|
|
||||||
var asmName = type.Assembly.GetName().Name;
|
|
||||||
if (asmName == "UnityEngine.CoreModule")
|
|
||||||
{
|
|
||||||
asmName = "UnityEngine";
|
|
||||||
}
|
|
||||||
|
|
||||||
return propertyType
|
|
||||||
? $"{category}{asmName}/{typeName}/{s_SupportedTypes[p.PropertyType]} {p.Name}"
|
|
||||||
: $"{category}{asmName}/{typeName}/{p.Name}";
|
|
||||||
}
|
|
||||||
|
|
||||||
public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
|
|
||||||
{
|
|
||||||
Init();
|
|
||||||
label = EditorGUI.BeginProperty(position, label, property);
|
|
||||||
|
|
||||||
var path = property.FindPropertyRelative("m_Path");
|
|
||||||
var split = path.stringValue.Split(';', ' ', ',');
|
|
||||||
var name = split.Length == 4 ? $"{split[0]}.{split[3]}" : "No Property";
|
|
||||||
|
|
||||||
position = EditorGUI.PrefixLabel(position, label);
|
|
||||||
if (GUI.Button(position, name, EditorStyles.popup))
|
|
||||||
{
|
|
||||||
s_OnMenuSelected = p =>
|
|
||||||
{
|
|
||||||
path.stringValue = p == null
|
|
||||||
? ""
|
|
||||||
: $"{p.DeclaringType?.FullName}, {p.DeclaringType?.Assembly.GetName().Name};{p.Name}";
|
|
||||||
property.serializedObject.ApplyModifiedProperties();
|
|
||||||
};
|
|
||||||
s_PropertyMenu.DropDown(position);
|
|
||||||
}
|
|
||||||
|
|
||||||
EditorGUI.EndProperty();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
[Serializable]
|
|
||||||
public class NumericProperty : ISerializationCallbackReceiver
|
|
||||||
{
|
|
||||||
//################################
|
|
||||||
// Serialized Members.
|
|
||||||
//################################
|
|
||||||
[SerializeField] private string m_Path = "";
|
|
||||||
|
|
||||||
|
|
||||||
//################################
|
|
||||||
// Private Members.
|
|
||||||
//################################
|
|
||||||
private Func<double> _get;
|
|
||||||
|
|
||||||
void ISerializationCallbackReceiver.OnBeforeSerialize()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void ISerializationCallbackReceiver.OnAfterDeserialize()
|
|
||||||
{
|
|
||||||
var pInfo = GetPropertyInfo(m_Path);
|
|
||||||
_get = CreateFunc(pInfo?.GetMethod);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//################################
|
|
||||||
// Public Members.
|
|
||||||
//################################
|
|
||||||
public double Get()
|
|
||||||
{
|
|
||||||
return _get?.Invoke() ?? -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static PropertyInfo GetPropertyInfo(string path)
|
|
||||||
{
|
|
||||||
var p = path.Split(';');
|
|
||||||
if (p.Length != 2) return null;
|
|
||||||
|
|
||||||
var type = Type.GetType(p[0]);
|
|
||||||
if (type == null)
|
|
||||||
{
|
|
||||||
Debug.LogException(new Exception($"Type '{p[0]}' is not found"));
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
var pInfo = type.GetProperty(p[1], BindingFlags.GetProperty | BindingFlags.Public | BindingFlags.Static);
|
|
||||||
if (pInfo == null)
|
|
||||||
{
|
|
||||||
Debug.LogException(new Exception($"Member '{p[1]}' is not found in type '{type}'"));
|
|
||||||
}
|
|
||||||
|
|
||||||
return pInfo;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static Func<double> CreateFunc(MethodInfo mInfo)
|
|
||||||
{
|
|
||||||
if (mInfo == null) return null;
|
|
||||||
switch (Type.GetTypeCode(mInfo.ReturnType))
|
|
||||||
{
|
|
||||||
case TypeCode.Boolean:
|
|
||||||
{
|
|
||||||
var func = (Func<bool>)mInfo.CreateDelegate(typeof(Func<bool>));
|
|
||||||
return () => func() ? 1 : 0;
|
|
||||||
}
|
|
||||||
case TypeCode.Byte:
|
|
||||||
{
|
|
||||||
var func = (Func<byte>)mInfo.CreateDelegate(typeof(Func<byte>));
|
|
||||||
return () => func();
|
|
||||||
}
|
|
||||||
case TypeCode.SByte:
|
|
||||||
{
|
|
||||||
var func = (Func<sbyte>)mInfo.CreateDelegate(typeof(Func<sbyte>));
|
|
||||||
return () => func();
|
|
||||||
}
|
|
||||||
case TypeCode.UInt16:
|
|
||||||
{
|
|
||||||
var func = (Func<ushort>)mInfo.CreateDelegate(typeof(Func<ushort>));
|
|
||||||
return () => func();
|
|
||||||
}
|
|
||||||
case TypeCode.UInt32:
|
|
||||||
{
|
|
||||||
var func = (Func<uint>)mInfo.CreateDelegate(typeof(Func<uint>));
|
|
||||||
return () => func();
|
|
||||||
}
|
|
||||||
case TypeCode.UInt64:
|
|
||||||
{
|
|
||||||
var func = (Func<ulong>)mInfo.CreateDelegate(typeof(Func<ulong>));
|
|
||||||
return () => func();
|
|
||||||
}
|
|
||||||
case TypeCode.Int16:
|
|
||||||
{
|
|
||||||
var func = (Func<short>)mInfo.CreateDelegate(typeof(Func<short>));
|
|
||||||
return () => func();
|
|
||||||
}
|
|
||||||
case TypeCode.Int32:
|
|
||||||
{
|
|
||||||
var f = (Func<int>)mInfo.CreateDelegate(typeof(Func<int>));
|
|
||||||
return () => f();
|
|
||||||
}
|
|
||||||
case TypeCode.Int64:
|
|
||||||
{
|
|
||||||
var f = (Func<long>)mInfo.CreateDelegate(typeof(Func<long>));
|
|
||||||
return () => f();
|
|
||||||
}
|
|
||||||
case TypeCode.Decimal:
|
|
||||||
{
|
|
||||||
var f = (Func<decimal>)mInfo.CreateDelegate(typeof(Func<decimal>));
|
|
||||||
return () => (double)f();
|
|
||||||
}
|
|
||||||
case TypeCode.Double:
|
|
||||||
{
|
|
||||||
var f = (Func<double>)mInfo.CreateDelegate(typeof(Func<double>));
|
|
||||||
return f;
|
|
||||||
}
|
|
||||||
case TypeCode.Single:
|
|
||||||
{
|
|
||||||
var f = (Func<float>)mInfo.CreateDelegate(typeof(Func<float>));
|
|
||||||
return () => f();
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
{
|
|
||||||
var message = $"Method '{mInfo.DeclaringType}.{mInfo.Name} ({mInfo.ReturnType})' is not supported.";
|
|
||||||
Debug.LogException(new Exception(message));
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,11 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: 87fefa9f373e8411596b00238a65f3c3
|
|
||||||
MonoImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
serializedVersion: 2
|
|
||||||
defaultReferences: []
|
|
||||||
executionOrder: 0
|
|
||||||
icon: {instanceID: 0}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
||||||
@@ -1,236 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Runtime.CompilerServices;
|
|
||||||
using System.Text;
|
|
||||||
|
|
||||||
[assembly: InternalsVisibleTo("Coffee.NanoMonitor.Tests")]
|
|
||||||
|
|
||||||
namespace Coffee.NanoMonitor
|
|
||||||
{
|
|
||||||
internal static class StringBuilderExtensions
|
|
||||||
{
|
|
||||||
public static bool IsEqual(this StringBuilder sb, string other)
|
|
||||||
{
|
|
||||||
if (sb == null || other == null) return false;
|
|
||||||
if (sb.Length != other.Length) return false;
|
|
||||||
|
|
||||||
for (var i = 0; i < sb.Length; i++)
|
|
||||||
{
|
|
||||||
if (sb[i] != other[i]) return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void AppendFormatNoAlloc(this StringBuilder sb, string format, double arg0 = 0, double arg1 = 0,
|
|
||||||
double arg2 = 0, double arg3 = 0)
|
|
||||||
{
|
|
||||||
for (var i = 0; i < format.Length; i++)
|
|
||||||
{
|
|
||||||
var c = format[i];
|
|
||||||
|
|
||||||
// Append formatted value
|
|
||||||
if (c == '{')
|
|
||||||
{
|
|
||||||
i = GetFormat(format, i, out var argIndex, out var padding, out var precision, out var alignment);
|
|
||||||
|
|
||||||
switch (argIndex)
|
|
||||||
{
|
|
||||||
case 0:
|
|
||||||
sb.AppendDouble(arg0, padding, precision, alignment);
|
|
||||||
break;
|
|
||||||
case 1:
|
|
||||||
sb.AppendDouble(arg1, padding, precision, alignment);
|
|
||||||
break;
|
|
||||||
case 2:
|
|
||||||
sb.AppendDouble(arg2, padding, precision, alignment);
|
|
||||||
break;
|
|
||||||
case 3:
|
|
||||||
sb.AppendDouble(arg3, padding, precision, alignment);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Append character
|
|
||||||
sb.Append(c);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void AppendInteger(this StringBuilder sb, double number, int padding, int alignment)
|
|
||||||
{
|
|
||||||
number = Math.Truncate(number);
|
|
||||||
var sign = number < 0;
|
|
||||||
number = sign ? -number : number;
|
|
||||||
|
|
||||||
var startIndex = sb.Length;
|
|
||||||
do
|
|
||||||
{
|
|
||||||
var n = Math.Truncate(number % 10);
|
|
||||||
number /= 10;
|
|
||||||
|
|
||||||
sb.Append((char)(n + 48));
|
|
||||||
} while (1 <= number || sb.Length - startIndex < padding);
|
|
||||||
|
|
||||||
if (sign)
|
|
||||||
{
|
|
||||||
sb.Append('-');
|
|
||||||
}
|
|
||||||
|
|
||||||
var endIndex = sb.Length - 1;
|
|
||||||
|
|
||||||
sb.Reverse(startIndex, endIndex);
|
|
||||||
sb.Alignment(alignment, startIndex, endIndex);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void AppendDouble(this StringBuilder sb, double number, int padding, int precision,
|
|
||||||
int alignment)
|
|
||||||
{
|
|
||||||
var integer = Math.Truncate(number);
|
|
||||||
var startIndex = sb.Length;
|
|
||||||
sb.AppendInteger(integer, padding, 0);
|
|
||||||
|
|
||||||
if (0 < precision)
|
|
||||||
{
|
|
||||||
sb.Append('.');
|
|
||||||
number -= integer;
|
|
||||||
number = Math.Round(number, precision);
|
|
||||||
for (var p = 0; p < precision; p++)
|
|
||||||
{
|
|
||||||
number *= 10;
|
|
||||||
integer = (long)number;
|
|
||||||
sb.Append((char)(integer + 48));
|
|
||||||
number -= integer;
|
|
||||||
number = Math.Round(number, precision);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
sb.Alignment(alignment, startIndex, sb.Length - 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void Reverse(this StringBuilder sb, int start, int end)
|
|
||||||
{
|
|
||||||
while (start < end)
|
|
||||||
{
|
|
||||||
// swap
|
|
||||||
(sb[start], sb[end]) = (sb[end], sb[start]);
|
|
||||||
start++;
|
|
||||||
end--;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void Alignment(this StringBuilder sb, int alignment, int start, int end)
|
|
||||||
{
|
|
||||||
if (alignment == 0) return;
|
|
||||||
|
|
||||||
var len = end - start + 1;
|
|
||||||
if (0 < alignment && len < alignment)
|
|
||||||
{
|
|
||||||
sb.Append(' ', alignment - len);
|
|
||||||
for (var i = 0; i < len; i++)
|
|
||||||
{
|
|
||||||
// swap
|
|
||||||
(sb[end - i], sb[start + alignment - i - 1]) = (sb[start + alignment - i - 1], sb[end - i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (alignment < 0 && len < -alignment)
|
|
||||||
{
|
|
||||||
sb.Append(' ', -alignment - len);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static int GetFormat(string format, int i, out int argIndex, out int padding, out int precision,
|
|
||||||
out int alignment)
|
|
||||||
{
|
|
||||||
argIndex = -1;
|
|
||||||
padding = 0;
|
|
||||||
precision = 0;
|
|
||||||
alignment = 0;
|
|
||||||
|
|
||||||
var alignmentSign = false;
|
|
||||||
var readFlag = 0;
|
|
||||||
|
|
||||||
for (; i < format.Length; i++)
|
|
||||||
{
|
|
||||||
var c = format[i];
|
|
||||||
|
|
||||||
// End format
|
|
||||||
if (c == '}')
|
|
||||||
{
|
|
||||||
return i;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Start format
|
|
||||||
if (c == '{')
|
|
||||||
{
|
|
||||||
readFlag = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
// After '{': Read argument index and format
|
|
||||||
else if (readFlag == 1)
|
|
||||||
{
|
|
||||||
if ('0' <= c && c <= '3')
|
|
||||||
{
|
|
||||||
argIndex = c - 48;
|
|
||||||
}
|
|
||||||
else if (c == ',')
|
|
||||||
{
|
|
||||||
readFlag = 2;
|
|
||||||
}
|
|
||||||
else if (c == ':')
|
|
||||||
{
|
|
||||||
readFlag = 3;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//After ',': Read alignment value
|
|
||||||
else if (readFlag == 2)
|
|
||||||
{
|
|
||||||
if ('0' <= c && c <= '9')
|
|
||||||
{
|
|
||||||
alignment = alignment * 10 + (alignmentSign ? 48 - c : c - 48);
|
|
||||||
}
|
|
||||||
else if (c == '-')
|
|
||||||
{
|
|
||||||
alignmentSign = true;
|
|
||||||
}
|
|
||||||
else if (c == ':')
|
|
||||||
{
|
|
||||||
readFlag = 3;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// After ':': Read format for integral
|
|
||||||
else if (readFlag == 3)
|
|
||||||
{
|
|
||||||
if (c == '.')
|
|
||||||
{
|
|
||||||
precision = 0;
|
|
||||||
readFlag = 4;
|
|
||||||
}
|
|
||||||
else if (c == '0')
|
|
||||||
{
|
|
||||||
padding++;
|
|
||||||
}
|
|
||||||
// Legacy mode
|
|
||||||
else if ('1' <= c && c <= '9')
|
|
||||||
{
|
|
||||||
precision = c - 48;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// After '.': Read decimal precision value
|
|
||||||
else if (readFlag == 4)
|
|
||||||
{
|
|
||||||
if (c == '0')
|
|
||||||
{
|
|
||||||
precision++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
argIndex = -1;
|
|
||||||
return i;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,12 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: 23b4d6d0f5b8644b0981a065d7e47478
|
|
||||||
MonoImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
serializedVersion: 2
|
|
||||||
defaultReferences:
|
|
||||||
- m_Material: {fileID: 2100000, guid: 4da4639f724144ddead57bffca64e71f, type: 3}
|
|
||||||
executionOrder: 0
|
|
||||||
icon: {instanceID: 0}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
||||||
@@ -1,18 +0,0 @@
|
|||||||
{
|
|
||||||
"name": "com.coffee.nano-monitor",
|
|
||||||
"displayName": "Nano Monitor",
|
|
||||||
"description": "This package displays FPS, memory status and any static properties.\n- extremely fast\n- no allocations (on build)\n-1 set pass call only\n- open/close/refresh (GC) buttons",
|
|
||||||
"version": "1.0.0",
|
|
||||||
"unity": "2018.3",
|
|
||||||
"license": "MIT",
|
|
||||||
"repository": {
|
|
||||||
"type": "git",
|
|
||||||
"url": "git+https://github.com/mob-sakai/MaskTweaksForUGUI.git"
|
|
||||||
},
|
|
||||||
"author": "mob-sakai <sakai861104@gmail.com> (https://github.com/mob-sakai)",
|
|
||||||
"dependencies": {},
|
|
||||||
"keywords": [
|
|
||||||
"monitor",
|
|
||||||
"utility"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: be075f23fcc314d319e4f4ebfa6eefdd
|
|
||||||
TextScriptImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
||||||
@@ -1,8 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: db256ad6e34f94a4a95dedcbce09ddf1
|
|
||||||
folderAsset: yes
|
|
||||||
DefaultImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
||||||
@@ -1,14 +0,0 @@
|
|||||||
{
|
|
||||||
"name": "Coffee.UIParticle.PerformanceDemo",
|
|
||||||
"references": [
|
|
||||||
"Coffee.UIParticle"
|
|
||||||
],
|
|
||||||
"optionalUnityReferences": [],
|
|
||||||
"includePlatforms": [],
|
|
||||||
"excludePlatforms": [],
|
|
||||||
"allowUnsafeCode": false,
|
|
||||||
"overrideReferences": false,
|
|
||||||
"precompiledReferences": [],
|
|
||||||
"autoReferenced": false,
|
|
||||||
"defineConstraints": []
|
|
||||||
}
|
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: 9c1a1a5e813ba46d2b837936f34e33a7
|
|
||||||
AssemblyDefinitionImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
||||||
@@ -1,84 +0,0 @@
|
|||||||
using UnityEngine;
|
|
||||||
using UnityEngine.Serialization;
|
|
||||||
|
|
||||||
namespace Coffee.UIExtensions.Demo
|
|
||||||
{
|
|
||||||
public class UIParticle_PerformanceDemo : MonoBehaviour
|
|
||||||
{
|
|
||||||
[FormerlySerializedAs("copyOrigin")]
|
|
||||||
[SerializeField]
|
|
||||||
private GameObject m_CopyOrigin;
|
|
||||||
|
|
||||||
[FormerlySerializedAs("copyCount")]
|
|
||||||
[SerializeField]
|
|
||||||
public int m_CopyCount;
|
|
||||||
|
|
||||||
[FormerlySerializedAs("root")]
|
|
||||||
[SerializeField]
|
|
||||||
public Canvas m_RootCanvas;
|
|
||||||
|
|
||||||
private void Start()
|
|
||||||
{
|
|
||||||
Application.targetFrameRate = 60;
|
|
||||||
|
|
||||||
if (m_CopyOrigin)
|
|
||||||
{
|
|
||||||
m_CopyOrigin.SetActive(false);
|
|
||||||
|
|
||||||
var parent = m_CopyOrigin.transform.parent;
|
|
||||||
for (var i = 0; i < m_CopyCount; i++)
|
|
||||||
{
|
|
||||||
var go = Instantiate(m_CopyOrigin, parent, false);
|
|
||||||
go.name = string.Format("{0} {1}", m_CopyOrigin.name, i + 1);
|
|
||||||
go.hideFlags = HideFlags.DontSave;
|
|
||||||
|
|
||||||
go.SetActive(true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void UIParticle_Enable(bool flag)
|
|
||||||
{
|
|
||||||
foreach (var uip in m_RootCanvas.GetComponentsInChildren<UIParticle>(true))
|
|
||||||
{
|
|
||||||
uip.enabled = flag;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!flag)
|
|
||||||
{
|
|
||||||
foreach (var ps in FindObjectsOfType<ParticleSystem>())
|
|
||||||
{
|
|
||||||
ps.Play(false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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 ParticleSystem_SetScale(float scale)
|
|
||||||
{
|
|
||||||
foreach (var ps in FindObjectsOfType<ParticleSystem>())
|
|
||||||
{
|
|
||||||
ps.transform.localScale = new Vector3(scale, scale, scale);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,11 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: 3a595cf9cf93f4e0686f247a5e7e19ce
|
|
||||||
MonoImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
serializedVersion: 2
|
|
||||||
defaultReferences: []
|
|
||||||
executionOrder: 0
|
|
||||||
icon: {instanceID: 0}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
||||||
@@ -1,8 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: aacefbb114f024ec0bd6d3153b28bb36
|
|
||||||
folderAsset: yes
|
|
||||||
DefaultImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user