Compare commits
No commits in common. "3c11209f17d38f154e020cee8b0518be9ee0fb86" and "a499f0c04670e6e52893799f02a30aa7b5b4db05" have entirely different histories.
3c11209f17
...
a499f0c046
|
@ -10,39 +10,26 @@ assignees: mob-sakai
|
|||
NOTE: Your issue may already be reported! Please search on the [issue tracker](../) before creating one.
|
||||
|
||||
**Describe the bug**
|
||||
|
||||
A clear and concise description of what the bug is.
|
||||
|
||||
**To Reproduce**
|
||||
|
||||
Steps to reproduce the behavior:
|
||||
|
||||
1. Go to '...'
|
||||
2. Click on '....'
|
||||
3. Scroll down to '....'
|
||||
4. See error
|
||||
|
||||
**Expected behavior**
|
||||
|
||||
A clear and concise description of what you expected to happen.
|
||||
|
||||
**Screenshots**
|
||||
|
||||
If applicable, add screenshots to help explain your problem.
|
||||
|
||||
**Environment (please complete the following)**
|
||||
|
||||
- Package version [e.g. 4.2.0, 3.3.14]
|
||||
- Platform: [e.g. Editor(Windows/Mac), Standalone(Windows/Mac), iOS, Android, WebGL]
|
||||
- Unity version: [e.g. 2021.3.7f1]
|
||||
- Project options: [e.g. Mono/IL2CPP, .Net Standard 2.1/.Net 4.x, URP/HDRP, GraphicAPIs]
|
||||
**Environment (please complete the following information):**
|
||||
- Version [e.g. 1.0.0]
|
||||
- Platform: [e.g. Editor(Windows/Mac), Standalone(Windows/Mac), iOS, Android, WebGL]
|
||||
- Unity version: [e.g. 2018.2.8f1]
|
||||
- Build options: [e.g. IL2CPP, .Net 4.x, LWRP]
|
||||
|
||||
**Additional context**
|
||||
|
||||
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`
|
||||
Add any other context about the problem here.
|
||||
|
|
|
@ -10,17 +10,13 @@ assignees: mob-sakai
|
|||
NOTE: Your issue may already be reported! Please search on the [issue tracker](../) before creating one.
|
||||
|
||||
**Is your feature request related to a problem? Please describe.**
|
||||
|
||||
A clear and concise description of what the issue is. (e.g. I'm always frustrated when [...])
|
||||
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
|
||||
|
||||
**Describe the solution you'd like**
|
||||
|
||||
A clear and concise description of what you want to happen.
|
||||
|
||||
**Describe alternatives you've considered**
|
||||
|
||||
A clear and concise description of any alternative solutions or features you've considered.
|
||||
|
||||
**Additional context**
|
||||
|
||||
Add any other context or screenshots about the feature request here.
|
||||
|
|
|
@ -13,9 +13,9 @@ jobs:
|
|||
release:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v2
|
||||
|
||||
- uses: cycjimmy/semantic-release-action@v3
|
||||
- uses: cycjimmy/semantic-release-action@v2
|
||||
with:
|
||||
extra_plugins: |
|
||||
@semantic-release/changelog
|
||||
|
|
|
@ -36,7 +36,7 @@ jobs:
|
|||
|
||||
steps:
|
||||
# Checkout sandbox project
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v2
|
||||
with:
|
||||
ref: sandbox
|
||||
submodules: true
|
||||
|
@ -48,7 +48,7 @@ jobs:
|
|||
run: git checkout ${{ github.sha }}
|
||||
|
||||
# Cache
|
||||
- uses: actions/cache@v3
|
||||
- uses: actions/cache@v2
|
||||
with:
|
||||
path: Library
|
||||
key: Library-${{ matrix.version }}-${{ github.sha }}
|
||||
|
|
40
CHANGELOG.md
40
CHANGELOG.md
|
@ -1,43 +1,3 @@
|
|||
## [4.2.1](https://github.com/mob-sakai/ParticleEffectForUGUI/compare/4.2.0...4.2.1) (2023-08-18)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* autoScaling and PositionMode may be locked ([3f2f12d](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/3f2f12d2cf7541118c02830ec9fdea8183357487))
|
||||
|
||||
# [4.2.0](https://github.com/mob-sakai/ParticleEffectForUGUI/compare/4.1.7...4.2.0) (2023-08-18)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* assertion 'ps->array_size()' in UpdateMesh() when using trails of type ribbon ([f75fcce](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/f75fcce0dae0bc166bd01d36a150aded1fd721f3)), closes [#241](https://github.com/mob-sakai/ParticleEffectForUGUI/issues/241)
|
||||
* built-in shaders are no longer supported ([c2119c1](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/c2119c171a1262431eac7fea6bf3125db2bcaaca)), closes [#233](https://github.com/mob-sakai/ParticleEffectForUGUI/issues/233) [#257](https://github.com/mob-sakai/ParticleEffectForUGUI/issues/257)
|
||||
* crash occurs when too many vertices are rendered ([723a04d](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/723a04d0cfd156715a3c92b6d6bd75fdc1862c28))
|
||||
* error: SerializedObject target has been destroyed ([e930516](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/e93051603e121732c92bcd89ded48087c2b0d7fb)), closes [#267](https://github.com/mob-sakai/ParticleEffectForUGUI/issues/267)
|
||||
* excessive particle emitted on move ParticleSystem for local space simulation and emission over distance ([2fe0bde](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/2fe0bde422f9769dfedaf6b053ea07f773646679)), closes [#265](https://github.com/mob-sakai/ParticleEffectForUGUI/issues/265)
|
||||
* fix typos ([52f2ef1](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/52f2ef1f2471a2e1c29fca96255c04b222d9c848))
|
||||
* generated GameObject will be named '[generated] *' ([9b2e5c1](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/9b2e5c1d1024e091de6d18a4578cd18b43563e48))
|
||||
* inactive ParticleSystems are removed from the list on refresh ([4851a18](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/4851a1880eef9f385dd9db644ea7e544f95da4fc))
|
||||
* mesh sharing not working ([8b4ca1a](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/8b4ca1add5c409601e840253e1c0dbcdbf536da8)), closes [#236](https://github.com/mob-sakai/ParticleEffectForUGUI/issues/236)
|
||||
* nullptr exceptions when using nested UIParticle components in hierarchy ([e67e948](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/e67e9482e2cb840b16e2cfe76e04f7423fcbd3a3)), closes [#246](https://github.com/mob-sakai/ParticleEffectForUGUI/issues/246)
|
||||
* nullReferenceException after copy-n-paste ([425aad0](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/425aad0cbab475635c72bee84ecbf3f2acedccc2)), closes [#258](https://github.com/mob-sakai/ParticleEffectForUGUI/issues/258)
|
||||
* remove unnecessary per-frame allocation. ([e92b514](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/e92b514624cc362e53ddeae5ade20fa732f94c7c))
|
||||
* scaling ParticleSystem puts prewarmed particles in wrong location ([fb31db4](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/fb31db47f2debb3aadbdc4d1b88d0efd9c4ad7bd)), closes [#235](https://github.com/mob-sakai/ParticleEffectForUGUI/issues/235)
|
||||
* sub-emitters option is not work in editor playing ([b308b26](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/b308b2683372662bb834b6f6d23ea3435a68d1b3)), closes [#231](https://github.com/mob-sakai/ParticleEffectForUGUI/issues/231)
|
||||
* the camera under UIParticle will be assigned as _orthoCamera ([c42f8c8](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/c42f8c8ab0ff033689349a81e02a4808e071a8a2))
|
||||
* UIParticleAttractor attracts the particles at wrong position when in RelativeMode ([68d9925](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/68d9925a16237df3c7b07b4781172cbd03425421)), closes [#262](https://github.com/mob-sakai/ParticleEffectForUGUI/issues/262)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* 'AbsoluteMode' option is renamed to 'PositionMode' ([67eff61](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/67eff610736344ba0122163ff5ee63b25c43f555))
|
||||
* 'AutoScaling' option will be imported from 'IgnoreCanvasScale' (for v3.x) ([4103041](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/410304125f3f25f3f543c7bc01dcc661eab00609))
|
||||
* add 'AutoScaling' option for UIParticle ([35325c8](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/35325c88996fa6aea19a6dd1395c05884e1f84ae))
|
||||
* add 'UpdateMode' option for UIParticleAttractor ([903f702](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/903f702d7be38228841a5a693e3afdceb4a59d9f)), closes [#250](https://github.com/mob-sakai/ParticleEffectForUGUI/issues/250)
|
||||
* add particle system getter and setter for attractor ([a4bcf93](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/a4bcf93022d2729f3d2a74a2cac4f52e68641b18)), closes [#253](https://github.com/mob-sakai/ParticleEffectForUGUI/issues/253)
|
||||
* add public properties for UIParticleAttractor ([392ab6d](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/392ab6dd76c36e815320d3a50744d19faa631260)), closes [#253](https://github.com/mob-sakai/ParticleEffectForUGUI/issues/253)
|
||||
* add Start/StopEmission API for UIParticle ([e499836](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/e4998365c9825fa385e0a317768ce073a1f15b48)), closes [#240](https://github.com/mob-sakai/ParticleEffectForUGUI/issues/240)
|
||||
|
||||
## [4.1.7](https://github.com/mob-sakai/ParticleEffectForUGUI/compare/4.1.6...4.1.7) (2022-08-30)
|
||||
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
Copyright 2018-2023 mob-sakai
|
||||
Copyright 2018-2022 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:
|
||||
|
||||
|
|
110
README.md
110
README.md
|
@ -4,12 +4,14 @@ Particle Effect For UGUI (UI Particle)
|
|||
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://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/releases) [](https://github.com/mob-sakai/ParticleEffectForUGUI/blob/master/LICENSE.txt)
|
||||
[](http://makeapullrequest.com)
|
||||

|
||||

|
||||

|
||||

|
||||
|
||||
|
||||
<< [Description](#Description) | [Demo](#demo) | [Installation](#installation) | [Usage](#usage) | [Development Note](#development-note) | [Change log](https://github.com/mob-sakai/ParticleEffectForUGUI/blob/upm/CHANGELOG.md) >>
|
||||
|
@ -56,8 +58,6 @@ Compares this "Baking mesh" approach with the conventional approach:
|
|||
* Support CanvasGroup alpha
|
||||
* No allocations
|
||||
* Support overlay, camera space and world space
|
||||
* Support Universal Render Pipeline (URP) and High Definition Render Pipeline (HDRP)
|
||||
* Support disabling `Enter Play Mode Options > Reload Domain`
|
||||
* Support changing material property with AnimationClip (AnimatableProperty)
|
||||

|
||||
* [4.0.0+] Support 8+ materials
|
||||
|
@ -92,41 +92,39 @@ Compares this "Baking mesh" approach with the conventional approach:
|
|||
|
||||
### Requirement
|
||||
|
||||
Unity 2018.2 or later
|
||||

|
||||

|
||||

|
||||

|
||||
|
||||
### Install via OpenUPM
|
||||
### Using OpenUPM
|
||||
|
||||
This package is available on [OpenUPM](https://openupm.com).
|
||||
It's recommended to install it via [openupm-cli](https://github.com/openupm/openupm-cli).
|
||||
You can install it via [openupm-cli](https://github.com/openupm/openupm-cli).
|
||||
```
|
||||
openupm add com.coffee.ui-particle
|
||||
```
|
||||
|
||||
### Install via Package Manager Window (using Git URL)
|
||||
### Using Git
|
||||
|
||||
1. Select `Window/Package Manager` menu to open `Package Manager` window.
|
||||
2. Click `+` and `Install package from git URL...`
|
||||

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

|
||||
Find the manifest.json file in the Packages folder of your project and add a line to `dependencies` field.
|
||||
|
||||
* `"com.coffee.ui-particle": "https://github.com/mob-sakai/ParticleEffectForUGUI.git"`
|
||||
|
||||
To update the package, change suffix `#{version}` to the target version.
|
||||
|
||||
* `"com.coffee.ui-particle": "https://github.com/mob-sakai/ParticleEffectForUGUI.git#4.0.0",`
|
||||
|
||||
Or, use [UpmGitExtension](https://github.com/mob-sakai/UpmGitExtension) to install and update the package.
|
||||
|
||||
### Install via manifest.json (using Git URL)
|
||||
### For Unity 2018.2
|
||||
|
||||
1. Open `Packages/manifest.json` in your project.
|
||||
2. Add this line below `"dependencies": {`
|
||||
* `"com.coffee.ui-particle": "https://github.com/mob-sakai/ParticleEffectForUGUI.git",`
|
||||

|
||||
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
|
||||
Unity 2018.2 supports embedded packages.
|
||||
|
||||
1. Download a source code zip file from [Releases](https://github.com/mob-sakai/ParticleEffectForUGUI/releases) page
|
||||
2. Extract it and place it under `Packages` directory in your project.
|
||||

|
||||
2. Extract it
|
||||
3. Import it under `Packages` directory in your Unity project
|
||||
|
||||
|
||||
|
||||
<br><br><br><br>
|
||||
|
@ -163,17 +161,17 @@ Or, use [UpmGitExtension](https://github.com/mob-sakai/UpmGitExtension) to insta
|
|||
|
||||
`UIParticle` controls the ParticleSystems that is attached to its own game objects and child game objects.
|
||||
|
||||

|
||||

|
||||
|
||||
| Properties | Description |
|
||||
| -- | -- |
|
||||
| Maskable | Does this graphic allow masking. |
|
||||
| Ignore Canvas Scale | Ignore the scale of the root canvas.<br>This prevents it from displaying small even in hierarchy scaling mode of `ParticleSystem`. |
|
||||
| Scale | Scale the rendering.<br>When the `3D` toggle is enabled, 3D scale (x,y,z) is supported. |
|
||||
| Animatable Properties | If you want update material properties (e.g. `_MainTex_ST`, `_Color`) in AnimationClip, use this to mark the changes. |
|
||||
| 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. |
|
||||
| Absolute Mode | The particles will be emitted at the ParticleSystem position.<br>Move the UIParticle/ParticleSystem to move the particle. |
|
||||
| Rendering Order | The ParticleSystems to be rendered.<br>You can change the rendering order and the materials. |
|
||||
|
||||
NOTE: Press `Refresh` button to reconstruct rendering order based on children ParticleSystem's sorting order and z position.
|
||||
|
||||
|
@ -229,7 +227,7 @@ uiParticle.Stop();
|
|||
|
||||
`UIParticleAttractor` attracts particles generated by the specified ParticleSystem.
|
||||
|
||||

|
||||

|
||||

|
||||
|
||||
| Properties | Description |
|
||||
|
@ -239,66 +237,22 @@ uiParticle.Stop();
|
|||
| Delay Rate | Delay to start attracting.<br>It is a percentage of the particle's start lifetime. |
|
||||
| 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. |
|
||||
| Movement | Attracting movement type. (Linear, Smooth, Sphere) |
|
||||
| Update Mode | **Normal:** Update with scaled delta time.<br>**Unscaled Time:** Update with unscaled delta time. |
|
||||
| OnAttracted | An event called when attracting is complete (per particle). |
|
||||
|
||||
<br><br><br><br>
|
||||
|
||||
## Development Note
|
||||
|
||||
### FAQ: Why are my particle effects not displayed correctly?
|
||||
|
||||
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)
|
||||
* Most cases can be solved by using `UI/Additive` or `UI/Default`.
|
||||
* Particles are masked
|
||||
* `UIParticle` is maskable.
|
||||
* Set `Mask` or `RectMask2D` component properly.
|
||||
* Particles are too small
|
||||
* If particles are small enough, they will not appear on the screen.
|
||||
* Increase the `Scale` value.
|
||||
* If you don't want to change the apparent size depending on the resolution, try `Auto Scaling` option.
|
||||
* Particles are too many
|
||||
* No more than 65535 vertices can be displayed (for mesh combination limitations).
|
||||
* Please set `Emission` module and `Max Particles` of ParticleSystem properly.
|
||||
* Particles are emitted off-screen.
|
||||
* When `Position Mode = Relative`, particles are emitted from scaled position of the ParticleSystem, not from the screen point of the ParticleSystem.
|
||||
* Place the ParticleSystem in the proper position or try `Position Mode = Absolute`.
|
||||
* Attaching `UIParticle` to the same object as `ParticleSystem`
|
||||
* `Transform.localScale` will be overridden by `Auto Scaling` option.
|
||||
* It is recommended to place `ParticleSystem` under `UIParticle`.
|
||||
|
||||
|
||||
<br>
|
||||
|
||||
### Shader Limitation
|
||||
|
||||
The use of UI shaders is recommended.
|
||||
|
||||
- If you need a simple Additive shader, use the `UI/Additive` shader instead.
|
||||
- If you need a simple alpha-blend shader, use the `UI/Default` shader instead.
|
||||
- If your custom shader does not work properly with UIParticle, consider creating a custom UI shader.
|
||||
|
||||
#### Built-in shaders are not supported
|
||||
|
||||
UIParticle does not support all built-in shaders except for `UI/Default`.
|
||||
If their use is detected, an error is displayed in the inspector.
|
||||
Use UI shaders instead.
|
||||
|
||||
#### UV.zw components will be discarded
|
||||
|
||||
UIParticleRenderer renders the particles based on UIVertex.
|
||||
Therefore, only xy components is available for each UV in the shader. (zw components will be discarded).
|
||||
UIParticles are based on UIVertex.
|
||||
Therefore, only xy components is available for each UV in the shader. (zw components will be ignored).
|
||||
So unfortunately UIParticles will not work well with some shaders.
|
||||
|
||||
#### Custom vertex streams
|
||||
|
||||
When using custom vertex streams, you can fill zw components with "unnecessary" data.
|
||||
https://github.com/mob-sakai/ParticleEffectForUGUI/issues/191
|
||||
|
||||
|
||||
<br>
|
||||
- If you need a simple Additive shader, use the `UI/Additive` shader instead.
|
||||
- If you need a simple alpha-blend shader, use the `UI/Default` shader instead.
|
||||
|
||||
### Overheads
|
||||
|
||||
|
|
|
@ -1,51 +1,33 @@
|
|||
using System;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using Coffee.UIExtensions;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
using UnityEngine.SceneManagement;
|
||||
using UnityEngine.UI;
|
||||
using Object = UnityEngine.Object;
|
||||
|
||||
namespace Coffee.UIExtensions.Demo
|
||||
public class CFX_Demo_With_UIParticle : MonoBehaviour
|
||||
{
|
||||
public class CFX_Demo_With_UIParticle : MonoBehaviour
|
||||
{
|
||||
private MonoBehaviour _demo;
|
||||
private Toggle _spawnOnUI;
|
||||
private UIParticle _uiParticle;
|
||||
private UIParticle UiParticle;
|
||||
private Toggle spawnOnUI;
|
||||
private MonoBehaviour demo;
|
||||
|
||||
// Start is called before the first frame update
|
||||
private void Start()
|
||||
{
|
||||
_uiParticle = GetComponentInChildren<UIParticle>();
|
||||
_spawnOnUI = GetComponentInChildren<Toggle>();
|
||||
_demo = FindObjectOfType("CFX_Demo_New") as MonoBehaviour
|
||||
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)
|
||||
private Object FindObjectOfType(string typeName)
|
||||
{
|
||||
var type = AppDomain.CurrentDomain.GetAssemblies()
|
||||
.SelectMany(x => x.GetTypes())
|
||||
|
@ -54,6 +36,23 @@ namespace Coffee.UIExtensions.Demo
|
|||
return type == null ? null : FindObjectOfType(type);
|
||||
}
|
||||
|
||||
// Update is called once per frame
|
||||
private void Update()
|
||||
{
|
||||
if (!spawnOnUI.isOn || !demo || !Input.GetMouseButtonDown(0)) return;
|
||||
|
||||
foreach (Transform child in UiParticle.transform)
|
||||
{
|
||||
Destroy(child.gameObject);
|
||||
}
|
||||
|
||||
var particle = demo.GetType()
|
||||
.GetMethod("spawnParticle", BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public)
|
||||
.Invoke(demo, new object[0]) as GameObject;
|
||||
particle.transform.localScale = Vector3.one;
|
||||
UiParticle.SetParticleSystemInstance(particle);
|
||||
}
|
||||
|
||||
public void SetCanvasWidth(int width)
|
||||
{
|
||||
var scaler = GetComponentInParent<CanvasScaler>();
|
||||
|
@ -83,5 +82,4 @@ namespace Coffee.UIExtensions.Demo
|
|||
{
|
||||
SceneManager.LoadScene(scene);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,28 +1,22 @@
|
|||
using UnityEngine;
|
||||
using UnityEngine.Serialization;
|
||||
|
||||
namespace Coffee.UIExtensions.Demo
|
||||
{
|
||||
public class CopyItemOnStart : MonoBehaviour
|
||||
{
|
||||
[FormerlySerializedAs("origin")]
|
||||
[SerializeField]
|
||||
private GameObject m_Origin;
|
||||
|
||||
[FormerlySerializedAs("count")]
|
||||
[SerializeField]
|
||||
private int m_Count;
|
||||
public GameObject origin;
|
||||
public int count;
|
||||
|
||||
private void Start()
|
||||
{
|
||||
if (!m_Origin) return;
|
||||
m_Origin.SetActive(false);
|
||||
if (!origin) return;
|
||||
origin.SetActive(false);
|
||||
|
||||
var parent = m_Origin.transform.parent;
|
||||
for (var i = 0; i < m_Count; i++)
|
||||
var parent = origin.transform.parent;
|
||||
for (var i = 0; i < count; i++)
|
||||
{
|
||||
var go = Instantiate(m_Origin, parent, false);
|
||||
go.name = $"{m_Origin.name} {i + 1}";
|
||||
var go = Instantiate(origin, parent, false);
|
||||
go.name = string.Format("{0} {1}", origin.name, i + 1);
|
||||
go.hideFlags = HideFlags.DontSave;
|
||||
go.SetActive(true);
|
||||
}
|
||||
|
|
|
@ -1,31 +1,25 @@
|
|||
using System;
|
||||
using UnityEngine;
|
||||
using UnityEngine;
|
||||
using UnityEngine.EventSystems;
|
||||
using UnityEngine.Serialization;
|
||||
|
||||
public class UIElementDragger : MonoBehaviour, IBeginDragHandler, IDragHandler, IEndDragHandler
|
||||
{
|
||||
[SerializeField]
|
||||
private Target m_Target;
|
||||
public enum Target
|
||||
{
|
||||
Self,
|
||||
Parent,
|
||||
Custom,
|
||||
}
|
||||
|
||||
[SerializeField]
|
||||
private Transform m_CustomTarget;
|
||||
|
||||
[FormerlySerializedAs("ex2")]
|
||||
[SerializeField]
|
||||
private bool m_UseCanvasScale;
|
||||
|
||||
private Canvas _canvas;
|
||||
private RectTransform _rectTransform;
|
||||
private RectTransform rectTransform;
|
||||
private Canvas canvas;
|
||||
public Target m_Target;
|
||||
public Transform m_CustomTarget;
|
||||
public bool ex2;
|
||||
|
||||
private void OnEnable()
|
||||
{
|
||||
_rectTransform = GetComponent<RectTransform>();
|
||||
_canvas = GetComponentInParent<Canvas>();
|
||||
}
|
||||
|
||||
public void OnBeginDrag(PointerEventData eventData)
|
||||
{
|
||||
rectTransform = GetComponent<RectTransform>();
|
||||
canvas = GetComponentInParent<Canvas>();
|
||||
}
|
||||
|
||||
public void OnDrag(PointerEventData eventData)
|
||||
|
@ -35,34 +29,34 @@ public class UIElementDragger : MonoBehaviour, IBeginDragHandler, IDragHandler,
|
|||
switch (m_Target)
|
||||
{
|
||||
case Target.Self:
|
||||
_rectTransform.localPosition += delta;
|
||||
rectTransform.localPosition += delta;
|
||||
break;
|
||||
case Target.Parent:
|
||||
_rectTransform.parent.localPosition += delta;
|
||||
rectTransform.parent.localPosition += delta;
|
||||
break;
|
||||
case Target.Custom:
|
||||
_rectTransform.localPosition += delta;
|
||||
rectTransform.localPosition += delta;
|
||||
if (m_CustomTarget)
|
||||
{
|
||||
if (m_UseCanvasScale)
|
||||
{
|
||||
delta.Scale(_canvas.rootCanvas.transform.localScale);
|
||||
}
|
||||
|
||||
if (ex2)
|
||||
delta.Scale(canvas.rootCanvas.transform.localScale);
|
||||
m_CustomTarget.localPosition += delta;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public void OnBeginDrag(PointerEventData eventData)
|
||||
{
|
||||
}
|
||||
|
||||
public void OnEndDrag(PointerEventData eventData)
|
||||
{
|
||||
}
|
||||
|
||||
private Vector2 GetLocalDelta(Vector2 evDelta)
|
||||
{
|
||||
switch (_canvas.renderMode)
|
||||
switch (canvas.renderMode)
|
||||
{
|
||||
case RenderMode.ScreenSpaceOverlay:
|
||||
{
|
||||
|
@ -71,23 +65,21 @@ public class UIElementDragger : MonoBehaviour, IBeginDragHandler, IDragHandler,
|
|||
return delta - zero;
|
||||
}
|
||||
case RenderMode.ScreenSpaceCamera:
|
||||
{
|
||||
Vector2 zero, delta;
|
||||
RectTransformUtility.ScreenPointToLocalPointInRectangle(rectTransform, Vector2.zero, canvas.worldCamera, out zero);
|
||||
RectTransformUtility.ScreenPointToLocalPointInRectangle(rectTransform, evDelta, canvas.worldCamera, out delta);
|
||||
return delta - zero;
|
||||
}
|
||||
case RenderMode.WorldSpace:
|
||||
{
|
||||
RectTransformUtility.ScreenPointToLocalPointInRectangle(_rectTransform, Vector2.zero,
|
||||
_canvas.worldCamera, out var zero);
|
||||
RectTransformUtility.ScreenPointToLocalPointInRectangle(_rectTransform, evDelta,
|
||||
_canvas.worldCamera, out var delta);
|
||||
Vector3 zero, delta;
|
||||
RectTransformUtility.ScreenPointToWorldPointInRectangle(rectTransform, Vector2.zero, canvas.worldCamera, out zero);
|
||||
RectTransformUtility.ScreenPointToWorldPointInRectangle(rectTransform, evDelta, canvas.worldCamera, out delta);
|
||||
return delta - zero;
|
||||
}
|
||||
default:
|
||||
throw new NotSupportedException();
|
||||
throw new System.NotSupportedException();
|
||||
}
|
||||
}
|
||||
|
||||
private enum Target
|
||||
{
|
||||
Self,
|
||||
Parent,
|
||||
Custom
|
||||
}
|
||||
}
|
|
@ -1,18 +1,14 @@
|
|||
using UnityEngine;
|
||||
using UnityEngine.Serialization;
|
||||
using UnityEngine.UI;
|
||||
|
||||
namespace Coffee.UIExtensions.Demo
|
||||
{
|
||||
public class UIParticle_Demo : MonoBehaviour
|
||||
{
|
||||
[FormerlySerializedAs("root")]
|
||||
[SerializeField]
|
||||
private Canvas m_RootCanvas;
|
||||
public Canvas root;
|
||||
|
||||
private int _height;
|
||||
private int _score;
|
||||
private int _width;
|
||||
private int _height;
|
||||
|
||||
private void Start()
|
||||
{
|
||||
|
@ -28,18 +24,11 @@ namespace Coffee.UIExtensions.Demo
|
|||
case RuntimePlatform.WindowsPlayer:
|
||||
case RuntimePlatform.LinuxPlayer:
|
||||
if (Screen.width == _width && Screen.height == _height)
|
||||
{
|
||||
Screen.SetResolution(_height, _width, Screen.fullScreen);
|
||||
}
|
||||
else if (Screen.width == _height && Screen.height == _width)
|
||||
{
|
||||
Screen.SetResolution(Mathf.Min(_width, _height), Mathf.Min(_width, _height), Screen.fullScreen);
|
||||
}
|
||||
else
|
||||
{
|
||||
Screen.SetResolution(_width, _height, Screen.fullScreen);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -49,31 +38,27 @@ namespace Coffee.UIExtensions.Demo
|
|||
Screen.fullScreen = !Screen.fullScreen;
|
||||
}
|
||||
|
||||
public void EnableAnimations(bool flag)
|
||||
public void EnableAnimations(bool enabled)
|
||||
{
|
||||
foreach (var animator in FindObjectsOfType<Animator>())
|
||||
{
|
||||
animator.enabled = flag;
|
||||
animator.enabled = enabled;
|
||||
}
|
||||
}
|
||||
|
||||
public void UIParticle_MeshSharing(bool flag)
|
||||
public void UIParticle_MeshSharing(bool enabled)
|
||||
{
|
||||
foreach (var uip in m_RootCanvas.GetComponentsInChildren<UIParticle>(true))
|
||||
foreach (var uip in root.GetComponentsInChildren<UIParticle>(true))
|
||||
{
|
||||
uip.meshSharing = flag
|
||||
? UIParticle.MeshSharing.Auto
|
||||
: UIParticle.MeshSharing.None;
|
||||
uip.meshSharing = enabled ? UIParticle.MeshSharing.Auto : UIParticle.MeshSharing.None;
|
||||
}
|
||||
}
|
||||
|
||||
public void UIParticle_RandomGroup(bool flag)
|
||||
public void UIParticle_RandomGroup(bool enabled)
|
||||
{
|
||||
foreach (var uip in m_RootCanvas.GetComponentsInChildren<UIParticle>(true))
|
||||
foreach (var uip in root.GetComponentsInChildren<UIParticle>(true))
|
||||
{
|
||||
uip.groupMaxId = flag
|
||||
? 4
|
||||
: 0;
|
||||
uip.groupMaxId = enabled ? 4 : 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -85,40 +70,38 @@ namespace Coffee.UIExtensions.Demo
|
|||
}
|
||||
}
|
||||
|
||||
public void ParticleSystem_WorldSpaseSimulation(bool flag)
|
||||
public void ParticleSystem_WorldSpaseSimulation(bool enabled)
|
||||
{
|
||||
foreach (var p in FindObjectsOfType<ParticleSystem>())
|
||||
foreach (var ps in FindObjectsOfType<ParticleSystem>())
|
||||
{
|
||||
var main = p.main;
|
||||
main.simulationSpace = flag
|
||||
? ParticleSystemSimulationSpace.World
|
||||
: ParticleSystemSimulationSpace.Local;
|
||||
var main = ps.main;
|
||||
main.simulationSpace = enabled ? ParticleSystemSimulationSpace.World : ParticleSystemSimulationSpace.Local;
|
||||
}
|
||||
}
|
||||
|
||||
public void ParticleSystem_WorldSpaseSimulation(ParticleSystem ps)
|
||||
public void ParticleSystem_WorldSpaseSimulation(ParticleSystem particleSystem)
|
||||
{
|
||||
foreach (var p in ps.GetComponentsInChildren<ParticleSystem>())
|
||||
foreach (var ps in particleSystem.GetComponentsInChildren<ParticleSystem>())
|
||||
{
|
||||
var main = p.main;
|
||||
var main = ps.main;
|
||||
main.simulationSpace = ParticleSystemSimulationSpace.World;
|
||||
p.Clear();
|
||||
ps.Clear();
|
||||
}
|
||||
}
|
||||
|
||||
public void ParticleSystem_LocalSpaseSimulation(ParticleSystem ps)
|
||||
public void ParticleSystem_LocalSpaseSimulation(ParticleSystem particleSystem)
|
||||
{
|
||||
foreach (var p in ps.GetComponentsInChildren<ParticleSystem>())
|
||||
foreach (var ps in particleSystem.GetComponentsInChildren<ParticleSystem>())
|
||||
{
|
||||
var main = p.main;
|
||||
var main = ps.main;
|
||||
main.simulationSpace = ParticleSystemSimulationSpace.Local;
|
||||
p.Clear();
|
||||
ps.Clear();
|
||||
}
|
||||
}
|
||||
|
||||
public void ParticleSystem_Emit(ParticleSystem ps)
|
||||
public void ParticleSystem_Emit(ParticleSystem particleSystem)
|
||||
{
|
||||
ps.Emit(5);
|
||||
particleSystem.Emit(5);
|
||||
}
|
||||
|
||||
public void ParticleSystem_SetScale(float scale)
|
||||
|
@ -144,37 +127,41 @@ namespace Coffee.UIExtensions.Demo
|
|||
attractor.movement = UIParticleAttractor.Movement.Sphere;
|
||||
}
|
||||
|
||||
int score = 0;
|
||||
public void UIParticleAttractor_OnAttract(Text scoreText)
|
||||
{
|
||||
_score++;
|
||||
scoreText.text = _score.ToString();
|
||||
score++;
|
||||
scoreText.text = score.ToString();
|
||||
scoreText.GetComponent<Animator>().Play(0);
|
||||
}
|
||||
|
||||
public void Canvas_WorldSpace(bool flag)
|
||||
{
|
||||
if (!flag) return;
|
||||
|
||||
if (flag)
|
||||
{
|
||||
var canvas = FindObjectOfType<Canvas>();
|
||||
canvas.renderMode = RenderMode.ScreenSpaceCamera;
|
||||
canvas.renderMode = RenderMode.WorldSpace;
|
||||
canvas.transform.rotation = Quaternion.Euler(new Vector3(0, 10, 0));
|
||||
}
|
||||
}
|
||||
|
||||
public void Canvas_CameraSpace(bool flag)
|
||||
{
|
||||
if (!flag) return;
|
||||
|
||||
if (flag)
|
||||
{
|
||||
var canvas = FindObjectOfType<Canvas>();
|
||||
canvas.renderMode = RenderMode.ScreenSpaceCamera;
|
||||
}
|
||||
}
|
||||
|
||||
public void Canvas_Overlay(bool flag)
|
||||
{
|
||||
if (!flag) return;
|
||||
|
||||
if (flag)
|
||||
{
|
||||
var canvas = FindObjectOfType<Canvas>();
|
||||
canvas.renderMode = RenderMode.ScreenSpaceOverlay;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,37 +1,30 @@
|
|||
using UnityEngine;
|
||||
using UnityEngine.Serialization;
|
||||
|
||||
namespace Coffee.UIExtensions.Demo
|
||||
{
|
||||
public class UIParticle_Demo_UIParticleController : MonoBehaviour
|
||||
{
|
||||
[FormerlySerializedAs("root")]
|
||||
[SerializeField]
|
||||
private Transform m_RootTransform;
|
||||
public Transform root;
|
||||
|
||||
public void UIParticle_MeshSharing(bool flag)
|
||||
public void UIParticle_MeshSharing(bool enabled)
|
||||
{
|
||||
foreach (var uip in m_RootTransform.GetComponentsInChildren<UIParticle>(true))
|
||||
foreach (var uip in root.GetComponentsInChildren<UIParticle>(true))
|
||||
{
|
||||
uip.meshSharing = flag
|
||||
? UIParticle.MeshSharing.Auto
|
||||
: UIParticle.MeshSharing.None;
|
||||
uip.meshSharing = enabled ? UIParticle.MeshSharing.Auto : UIParticle.MeshSharing.None;
|
||||
}
|
||||
}
|
||||
|
||||
public void UIParticle_RandomGroup(bool flag)
|
||||
public void UIParticle_RandomGroup(bool enabled)
|
||||
{
|
||||
foreach (var uip in m_RootTransform.GetComponentsInChildren<UIParticle>(true))
|
||||
foreach (var uip in root.GetComponentsInChildren<UIParticle>(true))
|
||||
{
|
||||
uip.groupMaxId = flag
|
||||
? 4
|
||||
: 0;
|
||||
uip.groupMaxId = enabled ? 4 : 0;
|
||||
}
|
||||
}
|
||||
|
||||
public void UIParticle_Scale(float scale)
|
||||
{
|
||||
foreach (var uip in m_RootTransform.GetComponentsInChildren<UIParticle>(true))
|
||||
foreach (var uip in root.GetComponentsInChildren<UIParticle>(true))
|
||||
{
|
||||
uip.scale = scale;
|
||||
}
|
||||
|
|
Binary file not shown.
|
@ -1,5 +1,5 @@
|
|||
fileFormatVersion: 2
|
||||
guid: d07e6c2670f164cf7939ab011061a9bf
|
||||
guid: 70069a8db1df148ae8b4c8108c079acf
|
||||
TrueTypeFontImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 4
|
||||
|
@ -8,9 +8,9 @@ TrueTypeFontImporter:
|
|||
characterSpacing: 0
|
||||
characterPadding: 1
|
||||
includeFontData: 1
|
||||
fontName: Share Tech Mono
|
||||
fontName: Falstin
|
||||
fontNames:
|
||||
- Share Tech Mono
|
||||
- Falstin
|
||||
fallbackFontReferences: []
|
||||
customCharacters:
|
||||
fontRenderingMode: 1
|
Binary file not shown.
|
@ -127,7 +127,7 @@ MonoBehaviour:
|
|||
m_PersistentCalls:
|
||||
m_Calls: []
|
||||
m_FontData:
|
||||
m_Font: {fileID: 12800000, guid: d07e6c2670f164cf7939ab011061a9bf, type: 3}
|
||||
m_Font: {fileID: 12800000, guid: 70069a8db1df148ae8b4c8108c079acf, type: 3}
|
||||
m_FontSize: 14
|
||||
m_FontStyle: 0
|
||||
m_BestFit: 0
|
||||
|
@ -206,7 +206,7 @@ MonoBehaviour:
|
|||
m_PersistentCalls:
|
||||
m_Calls: []
|
||||
m_FontData:
|
||||
m_Font: {fileID: 12800000, guid: d07e6c2670f164cf7939ab011061a9bf, type: 3}
|
||||
m_Font: {fileID: 12800000, guid: 70069a8db1df148ae8b4c8108c079acf, type: 3}
|
||||
m_FontSize: 14
|
||||
m_FontStyle: 0
|
||||
m_BestFit: 0
|
||||
|
@ -285,7 +285,7 @@ MonoBehaviour:
|
|||
m_PersistentCalls:
|
||||
m_Calls: []
|
||||
m_FontData:
|
||||
m_Font: {fileID: 12800000, guid: d07e6c2670f164cf7939ab011061a9bf, type: 3}
|
||||
m_Font: {fileID: 12800000, guid: 70069a8db1df148ae8b4c8108c079acf, type: 3}
|
||||
m_FontSize: 14
|
||||
m_FontStyle: 0
|
||||
m_BestFit: 0
|
||||
|
@ -366,7 +366,7 @@ MonoBehaviour:
|
|||
m_PersistentCalls:
|
||||
m_Calls: []
|
||||
m_FontData:
|
||||
m_Font: {fileID: 12800000, guid: d07e6c2670f164cf7939ab011061a9bf, type: 3}
|
||||
m_Font: {fileID: 12800000, guid: 70069a8db1df148ae8b4c8108c079acf, type: 3}
|
||||
m_FontSize: 14
|
||||
m_FontStyle: 0
|
||||
m_BestFit: 0
|
||||
|
@ -516,7 +516,7 @@ MonoBehaviour:
|
|||
m_PersistentCalls:
|
||||
m_Calls: []
|
||||
m_FontData:
|
||||
m_Font: {fileID: 12800000, guid: d07e6c2670f164cf7939ab011061a9bf, type: 3}
|
||||
m_Font: {fileID: 12800000, guid: 70069a8db1df148ae8b4c8108c079acf, type: 3}
|
||||
m_FontSize: 14
|
||||
m_FontStyle: 0
|
||||
m_BestFit: 0
|
||||
|
@ -595,7 +595,7 @@ MonoBehaviour:
|
|||
m_PersistentCalls:
|
||||
m_Calls: []
|
||||
m_FontData:
|
||||
m_Font: {fileID: 12800000, guid: d07e6c2670f164cf7939ab011061a9bf, type: 3}
|
||||
m_Font: {fileID: 12800000, guid: 70069a8db1df148ae8b4c8108c079acf, type: 3}
|
||||
m_FontSize: 14
|
||||
m_FontStyle: 0
|
||||
m_BestFit: 0
|
||||
|
@ -736,7 +736,7 @@ MonoBehaviour:
|
|||
m_PersistentCalls:
|
||||
m_Calls: []
|
||||
m_FontData:
|
||||
m_Font: {fileID: 12800000, guid: d07e6c2670f164cf7939ab011061a9bf, type: 3}
|
||||
m_Font: {fileID: 12800000, guid: 70069a8db1df148ae8b4c8108c079acf, type: 3}
|
||||
m_FontSize: 16
|
||||
m_FontStyle: 0
|
||||
m_BestFit: 0
|
||||
|
@ -889,7 +889,7 @@ MonoBehaviour:
|
|||
m_PersistentCalls:
|
||||
m_Calls: []
|
||||
m_FontData:
|
||||
m_Font: {fileID: 12800000, guid: d07e6c2670f164cf7939ab011061a9bf, type: 3}
|
||||
m_Font: {fileID: 12800000, guid: 70069a8db1df148ae8b4c8108c079acf, type: 3}
|
||||
m_FontSize: 16
|
||||
m_FontStyle: 0
|
||||
m_BestFit: 0
|
||||
|
@ -1042,7 +1042,7 @@ MonoBehaviour:
|
|||
m_PersistentCalls:
|
||||
m_Calls: []
|
||||
m_FontData:
|
||||
m_Font: {fileID: 12800000, guid: d07e6c2670f164cf7939ab011061a9bf, type: 3}
|
||||
m_Font: {fileID: 12800000, guid: 70069a8db1df148ae8b4c8108c079acf, type: 3}
|
||||
m_FontSize: 14
|
||||
m_FontStyle: 0
|
||||
m_BestFit: 0
|
||||
|
@ -1206,7 +1206,7 @@ MonoBehaviour:
|
|||
m_PersistentCalls:
|
||||
m_Calls: []
|
||||
m_FontData:
|
||||
m_Font: {fileID: 12800000, guid: d07e6c2670f164cf7939ab011061a9bf, type: 3}
|
||||
m_Font: {fileID: 12800000, guid: 70069a8db1df148ae8b4c8108c079acf, type: 3}
|
||||
m_FontSize: 16
|
||||
m_FontStyle: 0
|
||||
m_BestFit: 0
|
||||
|
@ -1418,7 +1418,7 @@ MonoBehaviour:
|
|||
m_EditorClassIdentifier:
|
||||
m_Interval: 0.5
|
||||
m_Precision: 2
|
||||
m_Font: {fileID: 12800000, guid: d07e6c2670f164cf7939ab011061a9bf, type: 3}
|
||||
m_Font: {fileID: 12800000, guid: 70069a8db1df148ae8b4c8108c079acf, type: 3}
|
||||
m_Opened: 1
|
||||
m_FoldoutObject: {fileID: 8720459857733317289}
|
||||
m_OpenButton: {fileID: 2149219299373497733}
|
||||
|
@ -1502,7 +1502,7 @@ MonoBehaviour:
|
|||
m_PersistentCalls:
|
||||
m_Calls: []
|
||||
m_FontData:
|
||||
m_Font: {fileID: 12800000, guid: d07e6c2670f164cf7939ab011061a9bf, type: 3}
|
||||
m_Font: {fileID: 12800000, guid: 70069a8db1df148ae8b4c8108c079acf, type: 3}
|
||||
m_FontSize: 16
|
||||
m_FontStyle: 0
|
||||
m_BestFit: 0
|
||||
|
@ -1695,7 +1695,7 @@ MonoBehaviour:
|
|||
m_PersistentCalls:
|
||||
m_Calls: []
|
||||
m_FontData:
|
||||
m_Font: {fileID: 12800000, guid: d07e6c2670f164cf7939ab011061a9bf, type: 3}
|
||||
m_Font: {fileID: 12800000, guid: 70069a8db1df148ae8b4c8108c079acf, type: 3}
|
||||
m_FontSize: 14
|
||||
m_FontStyle: 0
|
||||
m_BestFit: 0
|
||||
|
|
|
@ -1,11 +1,10 @@
|
|||
using System;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Profiling;
|
||||
using UnityEngine.Serialization;
|
||||
using UnityEngine.UI;
|
||||
#if UNITY_EDITOR
|
||||
using UnityEditor;
|
||||
using UnityEditorInternal;
|
||||
|
||||
#endif
|
||||
|
||||
namespace Coffee.NanoMonitor
|
||||
|
@ -14,29 +13,24 @@ namespace Coffee.NanoMonitor
|
|||
[CustomEditor(typeof(NanoMonitor))]
|
||||
internal class NanoMonitorEditor : Editor
|
||||
{
|
||||
private ReorderableList _monitorItemList;
|
||||
private UnityEditorInternal.ReorderableList m_MonitorItemList;
|
||||
|
||||
private void OnEnable()
|
||||
{
|
||||
var items = serializedObject.FindProperty("m_CustomMonitorItems");
|
||||
_monitorItemList = new ReorderableList(serializedObject, items)
|
||||
m_MonitorItemList = new UnityEditorInternal.ReorderableList(serializedObject, items)
|
||||
{
|
||||
draggable = false,
|
||||
drawHeaderCallback = r =>
|
||||
{
|
||||
EditorGUI.LabelField(r, new GUIContent("Custom Monitor Items"));
|
||||
},
|
||||
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);
|
||||
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);
|
||||
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
|
||||
elementHeightCallback = i => EditorGUI.GetPropertyHeight(items.GetArrayElementAtIndex(i)) + 6,
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -44,7 +38,7 @@ namespace Coffee.NanoMonitor
|
|||
{
|
||||
base.OnInspectorGUI();
|
||||
|
||||
_monitorItemList.DoLayoutList();
|
||||
m_MonitorItemList.DoLayoutList();
|
||||
serializedObject.ApplyModifiedProperties();
|
||||
}
|
||||
}
|
||||
|
@ -58,50 +52,38 @@ namespace Coffee.NanoMonitor
|
|||
// Serialize Members.
|
||||
//################################
|
||||
// Settings
|
||||
[Header("Settings")]
|
||||
[SerializeField]
|
||||
[Range(0.01f, 2f)]
|
||||
[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;
|
||||
[SerializeField] [Range(0, 3)] private int m_Precision = 2;
|
||||
[SerializeField] private Font m_Font;
|
||||
|
||||
// Foldout
|
||||
[Header("Foldout")]
|
||||
[SerializeField]
|
||||
private bool m_Opened;
|
||||
[Header("Foldout")] [SerializeField] private bool m_Opened = false;
|
||||
|
||||
[FormerlySerializedAs("m_Collapse")]
|
||||
[SerializeField]
|
||||
private GameObject m_FoldoutObject;
|
||||
[FormerlySerializedAs("m_Collapse")] [SerializeField]
|
||||
private GameObject m_FoldoutObject = null;
|
||||
|
||||
[SerializeField]
|
||||
private Button m_OpenButton;
|
||||
|
||||
[SerializeField]
|
||||
private Button m_CloseButton;
|
||||
[SerializeField] private Button m_OpenButton = null;
|
||||
[SerializeField] private Button m_CloseButton = null;
|
||||
|
||||
// View
|
||||
[Header("View")]
|
||||
[SerializeField]
|
||||
private MonitorUI m_Fps;
|
||||
[Header("View")] [SerializeField] private MonitorUI m_Fps = null;
|
||||
[SerializeField] private MonitorUI m_Gc = null;
|
||||
[SerializeField] private MonitorUI m_MonoUsage = null;
|
||||
[SerializeField] private MonitorUI m_UnityUsage = null;
|
||||
|
||||
[SerializeField]
|
||||
private MonitorUI m_Gc;
|
||||
[HideInInspector] [SerializeField] private CustomMonitorItem[] m_CustomMonitorItems = new CustomMonitorItem[0];
|
||||
|
||||
[SerializeField]
|
||||
private MonitorUI m_MonoUsage;
|
||||
|
||||
[SerializeField]
|
||||
private MonitorUI m_UnityUsage;
|
||||
|
||||
[HideInInspector]
|
||||
[SerializeField]
|
||||
private CustomMonitorItem[] m_CustomMonitorItems = new CustomMonitorItem[0];
|
||||
//################################
|
||||
// Public Members.
|
||||
//################################
|
||||
public void Clean()
|
||||
{
|
||||
Resources.UnloadUnusedAssets();
|
||||
GC.Collect();
|
||||
}
|
||||
|
||||
|
||||
//################################
|
||||
|
@ -111,75 +93,44 @@ namespace Coffee.NanoMonitor
|
|||
private double _fpsElapsed;
|
||||
private int _frames;
|
||||
|
||||
private void Update()
|
||||
private void Open()
|
||||
{
|
||||
_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;
|
||||
_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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -221,6 +172,77 @@ namespace Coffee.NanoMonitor
|
|||
}
|
||||
}
|
||||
|
||||
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 = (UnityEngine.Profiling.Profiler.GetMonoUsedSizeLong() >> 10) / 1024f;
|
||||
var monoTotal = (UnityEngine.Profiling.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 = (UnityEngine.Profiling.Profiler.GetTotalAllocatedMemoryLong() >> 10) / 1024f;
|
||||
var unityTotal = (UnityEngine.Profiling.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;
|
||||
}
|
||||
|
||||
#if UNITY_EDITOR
|
||||
private void OnValidate()
|
||||
{
|
||||
|
@ -242,55 +264,5 @@ namespace Coffee.NanoMonitor
|
|||
}
|
||||
}
|
||||
#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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,17 +2,14 @@
|
|||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
|
||||
namespace Coffee.NanoMonitor
|
||||
{
|
||||
namespace Coffee.NanoMonitor{
|
||||
public class FixedFont
|
||||
{
|
||||
private const string k_Characters =
|
||||
"_!\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~";
|
||||
private readonly UIVertex[] _tmpVerts = new UIVertex[4];
|
||||
private static readonly Dictionary<Font, FixedFont> _fonts = new Dictionary<Font, FixedFont>();
|
||||
private static readonly TextGenerator _textGenerator = new TextGenerator(100);
|
||||
|
||||
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
|
||||
private static TextGenerationSettings _settings = new TextGenerationSettings
|
||||
{
|
||||
scaleFactor = 1,
|
||||
horizontalOverflow = HorizontalWrapMode.Overflow,
|
||||
|
@ -22,33 +19,25 @@ namespace Coffee.NanoMonitor
|
|||
color = Color.white
|
||||
};
|
||||
|
||||
private int _resolution = 0;
|
||||
private readonly Font _font;
|
||||
private readonly UIVertex[] _tmpVerts = new UIVertex[4];
|
||||
private UICharInfo[] _charInfos;
|
||||
|
||||
private int _resolution;
|
||||
private UIVertex[] _verts;
|
||||
private UICharInfo[] _charInfos;
|
||||
|
||||
private FixedFont(Font font)
|
||||
{
|
||||
_font = font;
|
||||
}
|
||||
|
||||
public int fontSize
|
||||
{
|
||||
get
|
||||
{
|
||||
return _font.dynamic ? 32 : _font.fontSize;
|
||||
}
|
||||
}
|
||||
public int fontSize => _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;
|
||||
if (_fonts.TryGetValue(font, out var data)) return data;
|
||||
|
||||
data = new FixedFont(font);
|
||||
s_Fonts.Add(font, data);
|
||||
_fonts.Add(font, data);
|
||||
return data;
|
||||
}
|
||||
|
||||
|
@ -72,20 +61,18 @@ namespace Coffee.NanoMonitor
|
|||
if (_resolution == currentResolution) return;
|
||||
_resolution = currentResolution;
|
||||
|
||||
s_Settings.font = _font;
|
||||
s_TextGenerator.Invalidate();
|
||||
s_TextGenerator.Populate(k_Characters, s_Settings);
|
||||
_settings.font = _font;
|
||||
_textGenerator.Invalidate();
|
||||
_textGenerator.Populate("_!\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~", _settings);
|
||||
|
||||
_verts = s_TextGenerator.GetVerticesArray();
|
||||
_charInfos = s_TextGenerator.GetCharactersArray();
|
||||
_verts = _textGenerator.GetVerticesArray();
|
||||
_charInfos = _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);
|
||||
|
@ -131,27 +118,18 @@ namespace Coffee.NanoMonitor
|
|||
|
||||
for (var i = 0; i < 4; i++)
|
||||
{
|
||||
_tmpVerts[i] = new UIVertex
|
||||
{
|
||||
uv0 = uv,
|
||||
color = color
|
||||
};
|
||||
_tmpVerts[i] = new UIVertex();
|
||||
_tmpVerts[i].uv0 = uv;
|
||||
_tmpVerts[i].color = color;
|
||||
|
||||
switch (i)
|
||||
{
|
||||
case 0:
|
||||
if (i == 0)
|
||||
_tmpVerts[i].position = new Vector2(-size.x, -size.y) + offset;
|
||||
break;
|
||||
case 1:
|
||||
else if (i == 1)
|
||||
_tmpVerts[i].position = new Vector2(-size.x, size.y) + offset;
|
||||
break;
|
||||
case 2:
|
||||
else if (i == 2)
|
||||
_tmpVerts[i].position = new Vector2(size.x, size.y) + offset;
|
||||
break;
|
||||
case 3:
|
||||
else
|
||||
_tmpVerts[i].position = new Vector2(size.x, -size.y) + offset;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
toFill.AddUIVertexQuad(_tmpVerts);
|
||||
|
|
|
@ -1,46 +1,50 @@
|
|||
using System.Text;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
|
||||
namespace Coffee.NanoMonitor
|
||||
{
|
||||
namespace Coffee.NanoMonitor{
|
||||
#if UNITY_EDITOR
|
||||
using UnityEditor;
|
||||
|
||||
[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 SerializedProperty m_Mode;
|
||||
private SerializedProperty m_TextAnchor;
|
||||
private SerializedProperty m_FontSize;
|
||||
private SerializedProperty m_Font;
|
||||
private SerializedProperty m_Text;
|
||||
private SerializedProperty m_Color;
|
||||
|
||||
private void OnEnable()
|
||||
{
|
||||
_mode = serializedObject.FindProperty("m_Mode");
|
||||
_text = serializedObject.FindProperty("m_Text");
|
||||
_color = serializedObject.FindProperty("m_Color");
|
||||
m_Mode = serializedObject.FindProperty("m_Mode");
|
||||
|
||||
m_Text = serializedObject.FindProperty("m_Text");
|
||||
m_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");
|
||||
m_FontSize = fontData.FindPropertyRelative("m_FontSize");
|
||||
m_Font = fontData.FindPropertyRelative("m_Font");
|
||||
m_TextAnchor = serializedObject.FindProperty("m_TextAnchor");
|
||||
}
|
||||
|
||||
public override void OnInspectorGUI()
|
||||
{
|
||||
serializedObject.Update();
|
||||
|
||||
EditorGUILayout.PropertyField(_mode);
|
||||
if ((MonitorUI.Mode)_mode.intValue == MonitorUI.Mode.Text)
|
||||
EditorGUILayout.PropertyField(m_Mode);
|
||||
if ((MonitorUI.Mode) m_Mode.intValue == MonitorUI.Mode.Text)
|
||||
{
|
||||
EditorGUILayout.PropertyField(_text);
|
||||
EditorGUILayout.PropertyField(_fontSize);
|
||||
EditorGUILayout.PropertyField(_textAnchor);
|
||||
EditorGUILayout.PropertyField(_font);
|
||||
EditorGUILayout.PropertyField(m_Text);
|
||||
EditorGUILayout.PropertyField(m_FontSize);
|
||||
EditorGUILayout.PropertyField(m_TextAnchor);
|
||||
|
||||
//EditorGUI.BeginDisabledGroup(true);
|
||||
EditorGUILayout.PropertyField(m_Font);
|
||||
//EditorGUI.EndDisabledGroup();
|
||||
}
|
||||
|
||||
EditorGUILayout.PropertyField(_color);
|
||||
EditorGUILayout.PropertyField(m_Color);
|
||||
|
||||
serializedObject.ApplyModifiedProperties();
|
||||
}
|
||||
|
@ -52,7 +56,7 @@ namespace Coffee.NanoMonitor
|
|||
public enum Mode
|
||||
{
|
||||
Text,
|
||||
Fill
|
||||
Fill,
|
||||
}
|
||||
|
||||
public enum TextAnchor
|
||||
|
@ -70,38 +74,26 @@ namespace Coffee.NanoMonitor
|
|||
[SerializeField] private TextAnchor m_TextAnchor;
|
||||
|
||||
|
||||
//################################
|
||||
// Private Members.
|
||||
//################################
|
||||
private readonly StringBuilder _sb = new StringBuilder(64);
|
||||
|
||||
|
||||
//################################
|
||||
// Public Members.
|
||||
//################################
|
||||
public override string text
|
||||
{
|
||||
get
|
||||
{
|
||||
return _sb.ToString();
|
||||
}
|
||||
get => m_StringBuilder.ToString();
|
||||
set
|
||||
{
|
||||
m_Text = value;
|
||||
if (_sb.IsEqual(m_Text)) return;
|
||||
if (m_StringBuilder.IsEqual(m_Text)) return;
|
||||
|
||||
_sb.Length = 0;
|
||||
_sb.Append(m_Text);
|
||||
m_StringBuilder.Length = 0;
|
||||
m_StringBuilder.Append(m_Text);
|
||||
SetVerticesDirty();
|
||||
}
|
||||
}
|
||||
|
||||
public TextAnchor textAnchor
|
||||
{
|
||||
get
|
||||
{
|
||||
return m_TextAnchor;
|
||||
}
|
||||
get => m_TextAnchor;
|
||||
set
|
||||
{
|
||||
if (m_TextAnchor == value) return;
|
||||
|
@ -113,30 +105,65 @@ namespace Coffee.NanoMonitor
|
|||
|
||||
public override bool raycastTarget
|
||||
{
|
||||
get
|
||||
{
|
||||
return m_Mode == Mode.Fill;
|
||||
}
|
||||
get => m_Mode == Mode.Fill;
|
||||
set { }
|
||||
}
|
||||
|
||||
public void SetText(string format, double arg0 = 0, double arg1 = 0, double arg2 = 0, double arg3 = 0)
|
||||
{
|
||||
m_StringBuilder.Length = 0;
|
||||
m_StringBuilder.AppendFormatNoAlloc(format, arg0, arg1, arg2, arg3);
|
||||
SetVerticesDirty();
|
||||
}
|
||||
|
||||
public void SetText(StringBuilder builder)
|
||||
{
|
||||
m_StringBuilder.Length = 0;
|
||||
m_StringBuilder.Append(builder);
|
||||
SetVerticesDirty();
|
||||
}
|
||||
|
||||
|
||||
//################################
|
||||
// Private Members.
|
||||
//################################
|
||||
private readonly StringBuilder m_StringBuilder = new StringBuilder(64);
|
||||
|
||||
private void UpdateFont()
|
||||
{
|
||||
//var globalFont = NNanoMonitorttings.Instance.font;
|
||||
//if (globalFont)
|
||||
//{
|
||||
// font = globalFont;
|
||||
//}
|
||||
|
||||
var fontData = FixedFont.GetOrCreate(font);
|
||||
if (fontData != null)
|
||||
{
|
||||
fontData.Invalidate();
|
||||
fontData.UpdateFont();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//################################
|
||||
// Unity Callbacks.
|
||||
//################################
|
||||
protected override void OnEnable()
|
||||
{
|
||||
//NaNanoMonitortings.Instance.onFontChanged += UpdateFont;
|
||||
RegisterDirtyMaterialCallback(UpdateFont);
|
||||
|
||||
base.OnEnable();
|
||||
raycastTarget = false;
|
||||
maskable = false;
|
||||
_sb.Length = 0;
|
||||
_sb.Append(m_Text);
|
||||
m_StringBuilder.Length = 0;
|
||||
m_StringBuilder.Append(m_Text);
|
||||
}
|
||||
|
||||
protected override void OnDisable()
|
||||
{
|
||||
//NanNanoMonitorings.Instance.onFontChanged -= UpdateFont;
|
||||
UnregisterDirtyMaterialCallback(UpdateFont);
|
||||
|
||||
base.OnDisable();
|
||||
|
@ -147,38 +174,14 @@ namespace Coffee.NanoMonitor
|
|||
{
|
||||
base.OnValidate();
|
||||
|
||||
if (!_sb.IsEqual(m_Text))
|
||||
if (!m_StringBuilder.IsEqual(m_Text))
|
||||
{
|
||||
_sb.Length = 0;
|
||||
_sb.Append(m_Text);
|
||||
m_StringBuilder.Length = 0;
|
||||
m_StringBuilder.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();
|
||||
|
@ -194,7 +197,7 @@ namespace Coffee.NanoMonitor
|
|||
return;
|
||||
}
|
||||
|
||||
var scale = (float)fontSize / fontData.fontSize;
|
||||
var scale = (float) fontSize / fontData.fontSize;
|
||||
float offset = 0;
|
||||
switch (textAnchor)
|
||||
{
|
||||
|
@ -202,26 +205,20 @@ namespace Coffee.NanoMonitor
|
|||
offset = rectTransform.rect.xMin;
|
||||
break;
|
||||
case TextAnchor.Center:
|
||||
for (var i = 0; i < _sb.Length; i++)
|
||||
{
|
||||
offset = fontData.Layout(_sb[i], offset, scale);
|
||||
}
|
||||
|
||||
for (var i = 0; i < m_StringBuilder.Length; i++)
|
||||
offset = fontData.Layout(m_StringBuilder[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);
|
||||
}
|
||||
|
||||
for (var i = 0; i < m_StringBuilder.Length; i++)
|
||||
offset = fontData.Layout(m_StringBuilder[i], offset, scale);
|
||||
offset = rectTransform.rect.xMax - offset;
|
||||
break;
|
||||
}
|
||||
|
||||
for (var i = 0; i < _sb.Length; i++)
|
||||
for (var i = 0; i < m_StringBuilder.Length; i++)
|
||||
{
|
||||
offset = fontData.Append(toFill, _sb[i], offset, scale, color);
|
||||
offset = fontData.Append(toFill, m_StringBuilder[i], offset, scale, color);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,55 @@
|
|||
using System;
|
||||
using System.Linq;
|
||||
using UnityEngine;
|
||||
using UnityEngine.SceneManagement;
|
||||
|
||||
namespace Coffee.MiniProfiler
|
||||
{
|
||||
internal class MiniProfilerSettings : ScriptableSettings<MiniProfilerSettings>
|
||||
{
|
||||
[Header("UI")]
|
||||
[SerializeField] private Font m_Font = null;
|
||||
|
||||
[Header("Instantiate On Boot")]
|
||||
[SerializeField] private GameObject miniProfilerPrefab = null;
|
||||
[SerializeField] private string[] m_SceneNames = new string[0];
|
||||
|
||||
public Font font => m_Font;
|
||||
public event Action onFontChanged;
|
||||
|
||||
protected override void OnBoot()
|
||||
{
|
||||
SceneManager.sceneLoaded -= OnSceneLoaded;
|
||||
SceneManager.sceneLoaded += OnSceneLoaded;
|
||||
}
|
||||
|
||||
public void OnSceneLoaded(Scene scene, LoadSceneMode __)
|
||||
{
|
||||
SceneManager.sceneLoaded -= OnSceneLoaded;
|
||||
if (!miniProfilerPrefab || !m_SceneNames.Contains(scene.name)) return;
|
||||
|
||||
var go = Instantiate(miniProfilerPrefab);
|
||||
if (Application.isPlaying)
|
||||
DontDestroyOnLoad(go);
|
||||
}
|
||||
|
||||
protected override bool bootOnPlayMode => true;
|
||||
protected override bool bootOnEditorMode => false;
|
||||
|
||||
#if UNITY_EDITOR
|
||||
protected override void OnValidate()
|
||||
{
|
||||
onFontChanged?.Invoke();
|
||||
base.OnValidate();
|
||||
}
|
||||
|
||||
private void Reset()
|
||||
{
|
||||
m_Font = UnityEngine.Resources.GetBuiltinResource<Font>("Arial.ttf");
|
||||
}
|
||||
|
||||
[UnityEditor.SettingsProvider]
|
||||
private static UnityEditor.SettingsProvider CreateSettingsProvider() => new ScriptableSettingsProvider<MiniProfilerSettings>();
|
||||
#endif
|
||||
}
|
||||
}
|
|
@ -0,0 +1,13 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 647dad4f8226a49b9874b68b79413d64
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences:
|
||||
- miniProfilerPrefab: {fileID: 7211429669315726685, guid: 784696794bc6345bc80bf49623581c2e,
|
||||
type: 3}
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,280 @@
|
|||
using UnityEngine;
|
||||
using System;
|
||||
using System.Linq;
|
||||
#if UNITY_EDITOR
|
||||
using UnityEditor;
|
||||
|
||||
#endif
|
||||
|
||||
namespace Coffee.MiniProfiler
|
||||
{
|
||||
internal abstract class ScriptableSettings : ScriptableObject
|
||||
{
|
||||
#if UNITY_EDITOR
|
||||
public virtual string GetSettingPath()
|
||||
{
|
||||
return GetSettingPath(GetType());
|
||||
}
|
||||
|
||||
internal static string GetSettingPath(Type type)
|
||||
{
|
||||
return $"Project/{ObjectNames.NicifyVariableName(type.Name.Replace("ProjectSettings", ""))}";
|
||||
}
|
||||
#endif
|
||||
|
||||
public virtual string GetDefaultAssetPath()
|
||||
{
|
||||
return $"Assets/ProjectSettings/{GetType().Name}.asset";
|
||||
}
|
||||
}
|
||||
|
||||
internal abstract class ScriptableSettings<T> : ScriptableSettings
|
||||
where T : ScriptableSettings<T>
|
||||
{
|
||||
//################################
|
||||
// Public Members.
|
||||
//################################
|
||||
public static T Instance => _instance ? _instance : _instance = GetOrCreate();
|
||||
|
||||
private static T _instance;
|
||||
|
||||
protected virtual bool bootOnEditorMode => true;
|
||||
protected virtual bool bootOnPlayMode => true;
|
||||
|
||||
protected abstract void OnBoot();
|
||||
|
||||
#if UNITY_EDITOR
|
||||
//################################
|
||||
// Private Members.
|
||||
//################################
|
||||
private bool enabled;
|
||||
|
||||
private static T GetOrCreate()
|
||||
{
|
||||
return PlayerSettings.GetPreloadedAssets()
|
||||
.OfType<T>()
|
||||
.FirstOrDefault() ?? CreateInstance<T>();
|
||||
}
|
||||
|
||||
private void OnPlayModeStateChanged(PlayModeStateChange state)
|
||||
{
|
||||
switch (state)
|
||||
{
|
||||
case PlayModeStateChange.EnteredEditMode:
|
||||
enabled = true;
|
||||
Boot();
|
||||
break;
|
||||
case PlayModeStateChange.ExitingEditMode:
|
||||
case PlayModeStateChange.ExitingPlayMode:
|
||||
enabled = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private void Boot()
|
||||
{
|
||||
var preloadedAssets = PlayerSettings.GetPreloadedAssets();
|
||||
var assets = preloadedAssets.OfType<T>().ToArray();
|
||||
var first = assets.FirstOrDefault() ?? this as T;
|
||||
|
||||
// If there are no preloaded assets, registry the first asset.
|
||||
// If there are multiple preloaded assets, unregisters all but the first one.
|
||||
if (assets.Length != 1)
|
||||
{
|
||||
// The first asset is not saved.
|
||||
if (string.IsNullOrEmpty(AssetDatabase.GetAssetPath(first)))
|
||||
{
|
||||
if (!AssetDatabase.IsValidFolder("Assets/ProjectSettings"))
|
||||
AssetDatabase.CreateFolder("Assets", "ProjectSettings");
|
||||
|
||||
var assetName = ObjectNames.NicifyVariableName(first.GetType().Name.Replace("ProjectSettings", ""));
|
||||
var assetPath = AssetDatabase.GenerateUniqueAssetPath($"Assets/ProjectSettings/{assetName}.asset");
|
||||
AssetDatabase.CreateAsset(first, assetPath);
|
||||
}
|
||||
|
||||
PlayerSettings.SetPreloadedAssets(preloadedAssets
|
||||
.Where(x => x)
|
||||
.Except(assets)
|
||||
.Concat(new[] {first})
|
||||
.ToArray());
|
||||
}
|
||||
|
||||
// Another asset is registered as a preload asset.
|
||||
if (first != this)
|
||||
{
|
||||
UnityEngine.Debug.LogError($"Another asset '{first}' is registered as a preload '{typeof(T).Name}' asset." +
|
||||
$"\nThis instance ('{this}') will be ignored. Check 'Project Settings > Player > Preload Assets'", this);
|
||||
return;
|
||||
}
|
||||
|
||||
_instance = first;
|
||||
|
||||
// Do nothing on editor mode.
|
||||
if (!bootOnEditorMode && !EditorApplication.isPlayingOrWillChangePlaymode)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Do nothing on play mode.
|
||||
if (!bootOnPlayMode && EditorApplication.isPlayingOrWillChangePlaymode)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
OnBoot();
|
||||
}
|
||||
|
||||
|
||||
//################################
|
||||
// Unity Callbacks.
|
||||
//################################
|
||||
private void OnEnable()
|
||||
{
|
||||
enabled = true;
|
||||
Boot();
|
||||
EditorApplication.playModeStateChanged += OnPlayModeStateChanged;
|
||||
}
|
||||
|
||||
private void OnDisable()
|
||||
{
|
||||
EditorApplication.playModeStateChanged -= OnPlayModeStateChanged;
|
||||
}
|
||||
|
||||
protected virtual void OnValidate()
|
||||
{
|
||||
if (enabled)
|
||||
Boot();
|
||||
}
|
||||
#else
|
||||
private static T GetOrCreate()
|
||||
{
|
||||
return CreateInstance<T>();
|
||||
}
|
||||
|
||||
private void OnEnable()
|
||||
{
|
||||
if (!bootOnPlayMode) return;
|
||||
|
||||
_instance = this as T;
|
||||
OnBoot();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
[CustomEditor(typeof(ScriptablePreferenceSettings<>), true)]
|
||||
internal class ScriptablePreferenceSettingsEditor : Editor
|
||||
{
|
||||
private static readonly GUIContent _button = new GUIContent("Open Project Settings");
|
||||
|
||||
public override void OnInspectorGUI()
|
||||
{
|
||||
if (GUILayout.Button(_button))
|
||||
{
|
||||
SettingsService.OpenProjectSettings(((ScriptableSettings) target).GetSettingPath());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal abstract class ScriptablePreferenceSettings<T> : ScriptableSingleton<T>
|
||||
where T : ScriptablePreferenceSettings<T>
|
||||
{
|
||||
}
|
||||
|
||||
#if UNITY_EDITOR
|
||||
[CustomEditor(typeof(ScriptableSettings), true)]
|
||||
internal class ScriptableSettingsEditor : Editor
|
||||
{
|
||||
private static readonly GUIContent _button = new GUIContent("Open Project Settings");
|
||||
|
||||
public override void OnInspectorGUI()
|
||||
{
|
||||
if (GUILayout.Button(_button))
|
||||
{
|
||||
SettingsService.OpenProjectSettings(((ScriptableSettings) target).GetSettingPath());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal class ScriptableSettingsProvider<T> : SettingsProvider where T : ScriptableSettings<T>
|
||||
{
|
||||
public ScriptableSettingsProvider(string path) : base(path)
|
||||
{
|
||||
}
|
||||
|
||||
public ScriptableSettingsProvider() : base(ScriptableSettings.GetSettingPath(typeof(T)))
|
||||
{
|
||||
}
|
||||
|
||||
protected SerializedObject serializedObject { get; private set; }
|
||||
protected ScriptableSettings<T> target { get; private set; }
|
||||
|
||||
public sealed override void OnGUI(string searchContext)
|
||||
{
|
||||
if (!target)
|
||||
{
|
||||
target = ScriptableSettings<T>.Instance;
|
||||
serializedObject = new SerializedObject(target);
|
||||
}
|
||||
|
||||
OnGUI();
|
||||
}
|
||||
|
||||
protected virtual void OnGUI()
|
||||
{
|
||||
serializedObject.UpdateIfRequiredOrScript();
|
||||
var iterator = serializedObject.GetIterator();
|
||||
var enterChildren = true;
|
||||
while (iterator.NextVisible(enterChildren))
|
||||
{
|
||||
if (iterator.propertyPath != "m_Script")
|
||||
EditorGUILayout.PropertyField(iterator, true);
|
||||
|
||||
enterChildren = false;
|
||||
}
|
||||
|
||||
serializedObject.ApplyModifiedProperties();
|
||||
}
|
||||
}
|
||||
|
||||
internal class ScriptablePreferenceSettingsProvider<T> : SettingsProvider where T : ScriptableSettings<T>
|
||||
{
|
||||
public ScriptablePreferenceSettingsProvider(string path) : base(path, SettingsScope.User)
|
||||
{
|
||||
}
|
||||
|
||||
public ScriptablePreferenceSettingsProvider() : base(ScriptableSettings.GetSettingPath(typeof(T)), SettingsScope.User)
|
||||
{
|
||||
}
|
||||
|
||||
protected SerializedObject serializedObject { get; private set; }
|
||||
protected ScriptableSettings<T> target { get; private set; }
|
||||
|
||||
public sealed override void OnGUI(string searchContext)
|
||||
{
|
||||
if (!target)
|
||||
{
|
||||
target = ScriptableSettings<T>.Instance;
|
||||
serializedObject = new SerializedObject(target);
|
||||
}
|
||||
|
||||
OnGUI();
|
||||
}
|
||||
|
||||
protected virtual void OnGUI()
|
||||
{
|
||||
serializedObject.UpdateIfRequiredOrScript();
|
||||
var iterator = serializedObject.GetIterator();
|
||||
var enterChildren = true;
|
||||
while (iterator.NextVisible(enterChildren))
|
||||
{
|
||||
if (iterator.propertyPath != "m_Script")
|
||||
EditorGUILayout.PropertyField(iterator, true);
|
||||
|
||||
enterChildren = false;
|
||||
}
|
||||
|
||||
serializedObject.ApplyModifiedProperties();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 6ea9606f69cee413e9f96f52de99fa5e
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -1,5 +1,4 @@
|
|||
using System;
|
||||
using UnityEngine;
|
||||
using UnityEngine;
|
||||
#if UNITY_EDITOR
|
||||
using UnityEditor;
|
||||
#endif
|
||||
|
@ -12,17 +11,12 @@ namespace Coffee.NanoMonitor
|
|||
{
|
||||
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.PropertyField(new Rect(p.x, p.y + 18 * 0, p.width, 16), property.FindPropertyRelative("m_Text"));
|
||||
EditorGUI.PropertyField(new Rect(p.x, p.y + 18 * 1, p.width, 16), property.FindPropertyRelative("m_Format"));
|
||||
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.PropertyField(new Rect(p.x, p.y + 18 * 2, p.width, 16), property.FindPropertyRelative("m_Arg0"));
|
||||
EditorGUI.PropertyField(new Rect(p.x, p.y + 18 * 3, p.width, 16), property.FindPropertyRelative("m_Arg1"));
|
||||
EditorGUI.PropertyField(new Rect(p.x, p.y + 18 * 4, p.width, 16), property.FindPropertyRelative("m_Arg2"));
|
||||
EditorGUI.indentLevel--;
|
||||
|
||||
property.serializedObject.ApplyModifiedProperties();
|
||||
|
@ -35,21 +29,19 @@ namespace Coffee.NanoMonitor
|
|||
}
|
||||
#endif
|
||||
|
||||
[Serializable]
|
||||
[System.Serializable]
|
||||
public class CustomMonitorItem
|
||||
{
|
||||
[SerializeField] private MonitorUI m_Text;
|
||||
[SerializeField] private MonitorUI m_Text = null;
|
||||
[SerializeField] private string m_Format = "";
|
||||
[SerializeField] private NumericProperty m_Arg0;
|
||||
[SerializeField] private NumericProperty m_Arg1;
|
||||
[SerializeField] private NumericProperty m_Arg2;
|
||||
[SerializeField] private NumericProperty m_Arg0 = null;
|
||||
[SerializeField] private NumericProperty m_Arg1 = null;
|
||||
[SerializeField] private NumericProperty m_Arg2 = null;
|
||||
|
||||
public void UpdateText()
|
||||
{
|
||||
if (m_Text)
|
||||
{
|
||||
m_Text.SetText(m_Format, m_Arg0.Get(), m_Arg1.Get(), m_Arg2.Get());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,8 +2,12 @@
|
|||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Serialization;
|
||||
#if UNITY_EDITOR
|
||||
using UnityEditor;
|
||||
|
||||
#endif
|
||||
|
||||
namespace Coffee.NanoMonitor
|
||||
{
|
||||
|
@ -16,45 +20,39 @@ namespace Coffee.NanoMonitor
|
|||
|
||||
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" }
|
||||
{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))
|
||||
.SelectMany(type => type.GetProperties(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.GetProperty))
|
||||
.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.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);
|
||||
s_PropertyMenu.AddItem(new GUIContent(ConvertToMenuItem(pi, true)), false, arg => s_OnMenuSelected?.Invoke(arg as PropertyInfo), pi);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -62,17 +60,11 @@ namespace Coffee.NanoMonitor
|
|||
{
|
||||
var type = p.DeclaringType;
|
||||
if (type == null) return "";
|
||||
|
||||
var category = p.GetMethod.IsPublic && type.IsPublic
|
||||
? ""
|
||||
: "(Non Public Properties)/";
|
||||
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}";
|
||||
|
@ -92,9 +84,7 @@ namespace Coffee.NanoMonitor
|
|||
{
|
||||
s_OnMenuSelected = p =>
|
||||
{
|
||||
path.stringValue = p == null
|
||||
? ""
|
||||
: $"{p.DeclaringType?.FullName}, {p.DeclaringType?.Assembly.GetName().Name};{p.Name}";
|
||||
path.stringValue = p == null ? "" : $"{p.DeclaringType?.FullName}, {p.DeclaringType?.Assembly.GetName().Name};{p.Name}";
|
||||
property.serializedObject.ApplyModifiedProperties();
|
||||
};
|
||||
s_PropertyMenu.DropDown(position);
|
||||
|
@ -114,22 +104,6 @@ namespace Coffee.NanoMonitor
|
|||
[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.
|
||||
//################################
|
||||
|
@ -138,6 +112,12 @@ namespace Coffee.NanoMonitor
|
|||
return _get?.Invoke() ?? -1;
|
||||
}
|
||||
|
||||
|
||||
//################################
|
||||
// Private Members.
|
||||
//################################
|
||||
private Func<double> _get = null;
|
||||
|
||||
private static PropertyInfo GetPropertyInfo(string path)
|
||||
{
|
||||
var p = path.Split(';');
|
||||
|
@ -146,14 +126,14 @@ namespace Coffee.NanoMonitor
|
|||
var type = Type.GetType(p[0]);
|
||||
if (type == null)
|
||||
{
|
||||
Debug.LogException(new Exception($"Type '{p[0]}' is not found"));
|
||||
UnityEngine.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}'"));
|
||||
UnityEngine.Debug.LogException(new Exception($"Member '{p[1]}' is not found in type '{type}'"));
|
||||
}
|
||||
|
||||
return pInfo;
|
||||
|
@ -165,72 +145,55 @@ namespace Coffee.NanoMonitor
|
|||
switch (Type.GetTypeCode(mInfo.ReturnType))
|
||||
{
|
||||
case TypeCode.Boolean:
|
||||
{
|
||||
var func = (Func<bool>)mInfo.CreateDelegate(typeof(Func<bool>));
|
||||
return () => func() ? 1 : 0;
|
||||
}
|
||||
var f_bool = (Func<bool>) mInfo.CreateDelegate(typeof(Func<bool>));
|
||||
return () => f_bool() ? 1 : 0;
|
||||
case TypeCode.Byte:
|
||||
{
|
||||
var func = (Func<byte>)mInfo.CreateDelegate(typeof(Func<byte>));
|
||||
return () => func();
|
||||
}
|
||||
var f_byte = (Func<byte>) mInfo.CreateDelegate(typeof(Func<byte>));
|
||||
return () => f_byte();
|
||||
case TypeCode.SByte:
|
||||
{
|
||||
var func = (Func<sbyte>)mInfo.CreateDelegate(typeof(Func<sbyte>));
|
||||
return () => func();
|
||||
}
|
||||
var f_sbyte = (Func<sbyte>) mInfo.CreateDelegate(typeof(Func<sbyte>));
|
||||
return () => f_sbyte();
|
||||
case TypeCode.UInt16:
|
||||
{
|
||||
var func = (Func<ushort>)mInfo.CreateDelegate(typeof(Func<ushort>));
|
||||
return () => func();
|
||||
}
|
||||
var f_ushort = (Func<ushort>) mInfo.CreateDelegate(typeof(Func<ushort>));
|
||||
return () => f_ushort();
|
||||
case TypeCode.UInt32:
|
||||
{
|
||||
var func = (Func<uint>)mInfo.CreateDelegate(typeof(Func<uint>));
|
||||
return () => func();
|
||||
}
|
||||
var f_uint = (Func<uint>) mInfo.CreateDelegate(typeof(Func<uint>));
|
||||
return () => f_uint();
|
||||
case TypeCode.UInt64:
|
||||
{
|
||||
var func = (Func<ulong>)mInfo.CreateDelegate(typeof(Func<ulong>));
|
||||
return () => func();
|
||||
}
|
||||
var f_ulong = (Func<ulong>) mInfo.CreateDelegate(typeof(Func<ulong>));
|
||||
return () => f_ulong();
|
||||
case TypeCode.Int16:
|
||||
{
|
||||
var func = (Func<short>)mInfo.CreateDelegate(typeof(Func<short>));
|
||||
return () => func();
|
||||
}
|
||||
var f_short = (Func<short>) mInfo.CreateDelegate(typeof(Func<short>));
|
||||
return () => f_short();
|
||||
case TypeCode.Int32:
|
||||
{
|
||||
var f = (Func<int>)mInfo.CreateDelegate(typeof(Func<int>));
|
||||
return () => f();
|
||||
}
|
||||
var f_int = (Func<int>) mInfo.CreateDelegate(typeof(Func<int>));
|
||||
return () => f_int();
|
||||
case TypeCode.Int64:
|
||||
{
|
||||
var f = (Func<long>)mInfo.CreateDelegate(typeof(Func<long>));
|
||||
return () => f();
|
||||
}
|
||||
var f_long = (Func<long>) mInfo.CreateDelegate(typeof(Func<long>));
|
||||
return () => f_long();
|
||||
case TypeCode.Decimal:
|
||||
{
|
||||
var f = (Func<decimal>)mInfo.CreateDelegate(typeof(Func<decimal>));
|
||||
return () => (double)f();
|
||||
}
|
||||
var f_decimal = (Func<decimal>) mInfo.CreateDelegate(typeof(Func<decimal>));
|
||||
return () => (double) f_decimal();
|
||||
case TypeCode.Double:
|
||||
{
|
||||
var f = (Func<double>)mInfo.CreateDelegate(typeof(Func<double>));
|
||||
return f;
|
||||
}
|
||||
var f_double = (Func<double>) mInfo.CreateDelegate(typeof(Func<double>));
|
||||
return f_double;
|
||||
case TypeCode.Single:
|
||||
{
|
||||
var f = (Func<float>)mInfo.CreateDelegate(typeof(Func<float>));
|
||||
return () => f();
|
||||
}
|
||||
var f_float = (Func<float>) mInfo.CreateDelegate(typeof(Func<float>));
|
||||
return () => f_float();
|
||||
default:
|
||||
{
|
||||
var message = $"Method '{mInfo.DeclaringType}.{mInfo.Name} ({mInfo.ReturnType})' is not supported.";
|
||||
Debug.LogException(new Exception(message));
|
||||
UnityEngine.Debug.LogException(new Exception(string.Format("Method '{1}.{0}' is not supported.", mInfo.Name, mInfo.DeclaringType)));
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
void ISerializationCallbackReceiver.OnBeforeSerialize()
|
||||
{
|
||||
}
|
||||
|
||||
void ISerializationCallbackReceiver.OnAfterDeserialize()
|
||||
{
|
||||
var pInfo = GetPropertyInfo(m_Path);
|
||||
_get = CreateFunc(pInfo?.GetMethod);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -21,8 +21,7 @@ namespace Coffee.NanoMonitor
|
|||
return true;
|
||||
}
|
||||
|
||||
public static void AppendFormatNoAlloc(this StringBuilder sb, string format, double arg0 = 0, double arg1 = 0,
|
||||
double arg2 = 0, double arg3 = 0)
|
||||
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++)
|
||||
{
|
||||
|
@ -57,7 +56,7 @@ namespace Coffee.NanoMonitor
|
|||
}
|
||||
}
|
||||
|
||||
private static void AppendInteger(this StringBuilder sb, double number, int padding, int alignment)
|
||||
internal static void AppendInteger(this StringBuilder sb, double number, int padding, int precision, int alignment)
|
||||
{
|
||||
number = Math.Truncate(number);
|
||||
var sign = number < 0;
|
||||
|
@ -69,8 +68,8 @@ namespace Coffee.NanoMonitor
|
|||
var n = Math.Truncate(number % 10);
|
||||
number /= 10;
|
||||
|
||||
sb.Append((char)(n + 48));
|
||||
} while (1 <= number || sb.Length - startIndex < padding);
|
||||
sb.Append((char) (n + 48));
|
||||
} while (1 <= number || (sb.Length - startIndex) < padding);
|
||||
|
||||
if (sign)
|
||||
{
|
||||
|
@ -83,12 +82,11 @@ namespace Coffee.NanoMonitor
|
|||
sb.Alignment(alignment, startIndex, endIndex);
|
||||
}
|
||||
|
||||
private static void AppendDouble(this StringBuilder sb, double number, int padding, int precision,
|
||||
int alignment)
|
||||
internal 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);
|
||||
sb.AppendInteger(integer, padding, precision, 0);
|
||||
|
||||
if (0 < precision)
|
||||
{
|
||||
|
@ -98,8 +96,8 @@ namespace Coffee.NanoMonitor
|
|||
for (var p = 0; p < precision; p++)
|
||||
{
|
||||
number *= 10;
|
||||
integer = (long)number;
|
||||
sb.Append((char)(integer + 48));
|
||||
integer = (long) number;
|
||||
sb.Append((char) (integer + 48));
|
||||
number -= integer;
|
||||
number = Math.Round(number, precision);
|
||||
}
|
||||
|
@ -108,18 +106,20 @@ namespace Coffee.NanoMonitor
|
|||
sb.Alignment(alignment, startIndex, sb.Length - 1);
|
||||
}
|
||||
|
||||
private static void Reverse(this StringBuilder sb, int start, int end)
|
||||
internal static void Reverse(this StringBuilder sb, int start, int end)
|
||||
{
|
||||
while (start < end)
|
||||
{
|
||||
// swap
|
||||
(sb[start], sb[end]) = (sb[end], sb[start]);
|
||||
var c = sb[start];
|
||||
sb[start] = sb[end];
|
||||
sb[end] = c;
|
||||
|
||||
start++;
|
||||
end--;
|
||||
}
|
||||
}
|
||||
|
||||
private static void Alignment(this StringBuilder sb, int alignment, int start, int end)
|
||||
internal static void Alignment(this StringBuilder sb, int alignment, int start, int end)
|
||||
{
|
||||
if (alignment == 0) return;
|
||||
|
||||
|
@ -129,8 +129,9 @@ namespace Coffee.NanoMonitor
|
|||
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]);
|
||||
var c = sb[end - i];
|
||||
sb[end - i] = sb[start + alignment - i - 1];
|
||||
sb[start + alignment - i - 1] = c;
|
||||
}
|
||||
}
|
||||
else if (alignment < 0 && len < -alignment)
|
||||
|
@ -139,8 +140,7 @@ namespace Coffee.NanoMonitor
|
|||
}
|
||||
}
|
||||
|
||||
private static int GetFormat(string format, int i, out int argIndex, out int padding, out int precision,
|
||||
out int alignment)
|
||||
internal static int GetFormat(string format, int i, out int argIndex, out int padding, out int precision, out int alignment)
|
||||
{
|
||||
argIndex = -1;
|
||||
padding = 0;
|
||||
|
|
|
@ -1,35 +1,26 @@
|
|||
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;
|
||||
public GameObject copyOrigin;
|
||||
public int copyCount;
|
||||
public Canvas root;
|
||||
|
||||
private void Start()
|
||||
{
|
||||
Application.targetFrameRate = 60;
|
||||
|
||||
if (m_CopyOrigin)
|
||||
if (copyOrigin)
|
||||
{
|
||||
m_CopyOrigin.SetActive(false);
|
||||
copyOrigin.SetActive(false);
|
||||
|
||||
var parent = m_CopyOrigin.transform.parent;
|
||||
for (var i = 0; i < m_CopyCount; i++)
|
||||
var parent = copyOrigin.transform.parent;
|
||||
for (var i = 0; i < copyCount; i++)
|
||||
{
|
||||
var go = Instantiate(m_CopyOrigin, parent, false);
|
||||
go.name = string.Format("{0} {1}", m_CopyOrigin.name, i + 1);
|
||||
var go = GameObject.Instantiate(copyOrigin, parent, false);
|
||||
go.name = string.Format("{0} {1}", copyOrigin.name, i + 1);
|
||||
go.hideFlags = HideFlags.DontSave;
|
||||
|
||||
go.SetActive(true);
|
||||
|
@ -37,14 +28,32 @@ namespace Coffee.UIExtensions.Demo
|
|||
}
|
||||
}
|
||||
|
||||
public void UIParticle_Enable(bool flag)
|
||||
public void ChangeScreenSize()
|
||||
{
|
||||
foreach (var uip in m_RootCanvas.GetComponentsInChildren<UIParticle>(true))
|
||||
{
|
||||
uip.enabled = flag;
|
||||
if (Screen.width == 400 && Screen.height == 720)
|
||||
Screen.SetResolution(720, 720, false);
|
||||
else if (Screen.width == 720 && Screen.height == 720)
|
||||
Screen.SetResolution(720, 400, false);
|
||||
else
|
||||
Screen.SetResolution(400, 720, false);
|
||||
}
|
||||
|
||||
if (!flag)
|
||||
public void EnableAnimations(bool enabled)
|
||||
{
|
||||
foreach (var animator in FindObjectsOfType<Animator>())
|
||||
{
|
||||
animator.enabled = enabled;
|
||||
}
|
||||
}
|
||||
|
||||
public void UIParticle_Enable(bool enabled)
|
||||
{
|
||||
|
||||
foreach (var uip in root.GetComponentsInChildren<UIParticle>(true))
|
||||
{
|
||||
uip.enabled = enabled;
|
||||
}
|
||||
if (!enabled)
|
||||
{
|
||||
foreach (var ps in FindObjectsOfType<ParticleSystem>())
|
||||
{
|
||||
|
@ -53,23 +62,36 @@ namespace Coffee.UIExtensions.Demo
|
|||
}
|
||||
}
|
||||
|
||||
public void UIParticle_MeshSharing(bool flag)
|
||||
public void UIParticle_MeshSharing(bool enabled)
|
||||
{
|
||||
foreach (var uip in m_RootCanvas.GetComponentsInChildren<UIParticle>(true))
|
||||
foreach (var uip in root.GetComponentsInChildren<UIParticle>(true))
|
||||
{
|
||||
uip.meshSharing = flag
|
||||
? UIParticle.MeshSharing.Auto
|
||||
: UIParticle.MeshSharing.None;
|
||||
uip.meshSharing = enabled ? UIParticle.MeshSharing.Auto : UIParticle.MeshSharing.None;
|
||||
}
|
||||
}
|
||||
|
||||
public void UIParticle_RandomGroup(bool flag)
|
||||
public void UIParticle_RandomGroup(bool enabled)
|
||||
{
|
||||
foreach (var uip in m_RootCanvas.GetComponentsInChildren<UIParticle>(true))
|
||||
foreach (var uip in root.GetComponentsInChildren<UIParticle>(true))
|
||||
{
|
||||
uip.groupMaxId = flag
|
||||
? 4
|
||||
: 0;
|
||||
uip.groupMaxId = enabled ? 4 : 0;
|
||||
}
|
||||
}
|
||||
|
||||
public void UIParticle_Scale(float scale)
|
||||
{
|
||||
foreach (var uip in FindObjectsOfType<UIParticle>())
|
||||
{
|
||||
uip.scale = scale;
|
||||
}
|
||||
}
|
||||
|
||||
public void ParticleSystem_WorldSpaseSimulation(bool enabled)
|
||||
{
|
||||
foreach (var ps in FindObjectsOfType<ParticleSystem>())
|
||||
{
|
||||
var main = ps.main;
|
||||
main.simulationSpace = enabled ? ParticleSystemSimulationSpace.World : ParticleSystemSimulationSpace.Local;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -80,5 +102,34 @@ namespace Coffee.UIExtensions.Demo
|
|||
ps.transform.localScale = new Vector3(scale, scale, scale);
|
||||
}
|
||||
}
|
||||
|
||||
public void Canvas_WorldSpace(bool flag)
|
||||
{
|
||||
if (flag)
|
||||
{
|
||||
var canvas = FindObjectOfType<Canvas>();
|
||||
canvas.renderMode = RenderMode.ScreenSpaceCamera;
|
||||
canvas.renderMode = RenderMode.WorldSpace;
|
||||
canvas.transform.rotation = Quaternion.Euler(new Vector3(0, 10, 0));
|
||||
}
|
||||
}
|
||||
|
||||
public void Canvas_CameraSpace(bool flag)
|
||||
{
|
||||
if (flag)
|
||||
{
|
||||
var canvas = FindObjectOfType<Canvas>();
|
||||
canvas.renderMode = RenderMode.ScreenSpaceCamera;
|
||||
}
|
||||
}
|
||||
|
||||
public void Canvas_Overlay(bool flag)
|
||||
{
|
||||
if (flag)
|
||||
{
|
||||
var canvas = FindObjectOfType<Canvas>();
|
||||
canvas.renderMode = RenderMode.ScreenSpaceOverlay;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -38,7 +38,7 @@ RenderSettings:
|
|||
m_ReflectionIntensity: 1
|
||||
m_CustomReflection: {fileID: 0}
|
||||
m_Sun: {fileID: 0}
|
||||
m_IndirectSpecularColor: {r: 0.12731689, g: 0.13414702, b: 0.1210784, a: 1}
|
||||
m_IndirectSpecularColor: {r: 0.12731704, g: 0.13414726, b: 0.1210787, a: 1}
|
||||
m_UseRadianceAmbientProbe: 0
|
||||
--- !u!157 &3
|
||||
LightmapSettings:
|
||||
|
@ -757,6 +757,85 @@ Transform:
|
|||
m_Father: {fileID: 0}
|
||||
m_RootOrder: 2
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||
--- !u!1 &455490117
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
serializedVersion: 6
|
||||
m_Component:
|
||||
- component: {fileID: 455490120}
|
||||
- component: {fileID: 455490119}
|
||||
- component: {fileID: 455490118}
|
||||
m_Layer: 5
|
||||
m_Name: Custom 1
|
||||
m_TagString: Untagged
|
||||
m_Icon: {fileID: 0}
|
||||
m_NavMeshLayer: 0
|
||||
m_StaticEditorFlags: 0
|
||||
m_IsActive: 1
|
||||
--- !u!114 &455490118
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 455490117}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: b0e08c6080a2e4d8186f97c60518830f, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
m_Material: {fileID: 0}
|
||||
m_Color: {r: 1, g: 1, b: 1, a: 1}
|
||||
m_RaycastTarget: 0
|
||||
m_OnCullStateChanged:
|
||||
m_PersistentCalls:
|
||||
m_Calls: []
|
||||
m_FontData:
|
||||
m_Font: {fileID: 12800000, guid: 70069a8db1df148ae8b4c8108c079acf, type: 3}
|
||||
m_FontSize: 14
|
||||
m_FontStyle: 0
|
||||
m_BestFit: 0
|
||||
m_MinSize: 1
|
||||
m_MaxSize: 40
|
||||
m_Alignment: 0
|
||||
m_AlignByGeometry: 0
|
||||
m_RichText: 1
|
||||
m_HorizontalOverflow: 0
|
||||
m_VerticalOverflow: 0
|
||||
m_LineSpacing: 1
|
||||
m_Text: 'UIParticle: 888'
|
||||
m_Mode: 0
|
||||
m_TextAnchor: 0
|
||||
--- !u!222 &455490119
|
||||
CanvasRenderer:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 455490117}
|
||||
m_CullTransparentMesh: 0
|
||||
--- !u!224 &455490120
|
||||
RectTransform:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 455490117}
|
||||
m_LocalRotation: {x: -0, y: -0, z: -0, w: 1}
|
||||
m_LocalPosition: {x: 0, y: 0, z: 0}
|
||||
m_LocalScale: {x: 1, y: 1, z: 1}
|
||||
m_Children: []
|
||||
m_Father: {fileID: 1002673088}
|
||||
m_RootOrder: 1
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||
m_AnchorMin: {x: 0, y: 1}
|
||||
m_AnchorMax: {x: 0, y: 1}
|
||||
m_AnchoredPosition: {x: 251.8711, y: -10}
|
||||
m_SizeDelta: {x: 247.8711, y: 20}
|
||||
m_Pivot: {x: 0, y: 0.5}
|
||||
--- !u!1 &496349153
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
|
@ -893,12 +972,12 @@ PrefabInstance:
|
|||
- target: {fileID: 864895766138689324, guid: a4669dfbba654429bbcddf0c9b79fb8b,
|
||||
type: 3}
|
||||
propertyPath: m_AnchoredPosition.x
|
||||
value: 240
|
||||
value: 240.00002
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 864895766138689324, guid: a4669dfbba654429bbcddf0c9b79fb8b,
|
||||
type: 3}
|
||||
propertyPath: m_AnchoredPosition.y
|
||||
value: -180
|
||||
value: -179.99998
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 864895766138689324, guid: a4669dfbba654429bbcddf0c9b79fb8b,
|
||||
type: 3}
|
||||
|
@ -1081,85 +1160,6 @@ CanvasRenderer:
|
|||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 608849065}
|
||||
m_CullTransparentMesh: 0
|
||||
--- !u!1 &733597319
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
serializedVersion: 6
|
||||
m_Component:
|
||||
- component: {fileID: 733597322}
|
||||
- component: {fileID: 733597321}
|
||||
- component: {fileID: 733597320}
|
||||
m_Layer: 5
|
||||
m_Name: Custom 1
|
||||
m_TagString: Untagged
|
||||
m_Icon: {fileID: 0}
|
||||
m_NavMeshLayer: 0
|
||||
m_StaticEditorFlags: 0
|
||||
m_IsActive: 1
|
||||
--- !u!114 &733597320
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 733597319}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: b0e08c6080a2e4d8186f97c60518830f, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
m_Material: {fileID: 0}
|
||||
m_Color: {r: 1, g: 1, b: 1, a: 1}
|
||||
m_RaycastTarget: 0
|
||||
m_OnCullStateChanged:
|
||||
m_PersistentCalls:
|
||||
m_Calls: []
|
||||
m_FontData:
|
||||
m_Font: {fileID: 12800000, guid: d07e6c2670f164cf7939ab011061a9bf, type: 3}
|
||||
m_FontSize: 14
|
||||
m_FontStyle: 0
|
||||
m_BestFit: 0
|
||||
m_MinSize: 1
|
||||
m_MaxSize: 40
|
||||
m_Alignment: 0
|
||||
m_AlignByGeometry: 0
|
||||
m_RichText: 1
|
||||
m_HorizontalOverflow: 0
|
||||
m_VerticalOverflow: 0
|
||||
m_LineSpacing: 1
|
||||
m_Text: 'Screen: 8888x8888 Time: 8888.88'
|
||||
m_Mode: 0
|
||||
m_TextAnchor: 0
|
||||
--- !u!222 &733597321
|
||||
CanvasRenderer:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 733597319}
|
||||
m_CullTransparentMesh: 0
|
||||
--- !u!224 &733597322
|
||||
RectTransform:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 733597319}
|
||||
m_LocalRotation: {x: -0, y: -0, z: -0, w: 1}
|
||||
m_LocalPosition: {x: 0, y: 0, z: 0}
|
||||
m_LocalScale: {x: 1, y: 1, z: 1}
|
||||
m_Children: []
|
||||
m_Father: {fileID: 1002673088}
|
||||
m_RootOrder: 1
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||
m_AnchorMin: {x: 0, y: 1}
|
||||
m_AnchorMax: {x: 0, y: 1}
|
||||
m_AnchoredPosition: {x: 251.8711, y: -10}
|
||||
m_SizeDelta: {x: 247.8711, y: 20}
|
||||
m_Pivot: {x: 0, y: 0.5}
|
||||
--- !u!1 &879285143
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
|
@ -1287,9 +1287,9 @@ MonoBehaviour:
|
|||
m_Script: {fileID: 11500000, guid: 3a595cf9cf93f4e0686f247a5e7e19ce, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
m_CopyOrigin: {fileID: 1581241706}
|
||||
m_CopyCount: 266
|
||||
m_RootCanvas: {fileID: 919637305}
|
||||
copyOrigin: {fileID: 1581241706}
|
||||
copyCount: 266
|
||||
root: {fileID: 919637305}
|
||||
--- !u!4 &903906985
|
||||
Transform:
|
||||
m_ObjectHideFlags: 0
|
||||
|
@ -1505,6 +1505,11 @@ PrefabInstance:
|
|||
propertyPath: m_SizeDelta.x
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 151878254403844079, guid: 784696794bc6345bc80bf49623581c2e,
|
||||
type: 3}
|
||||
propertyPath: m_TargetGraphic
|
||||
value:
|
||||
objectReference: {fileID: 1002673091}
|
||||
- target: {fileID: 323826319202443003, guid: 784696794bc6345bc80bf49623581c2e,
|
||||
type: 3}
|
||||
propertyPath: m_AnchorMin.y
|
||||
|
@ -1525,6 +1530,11 @@ PrefabInstance:
|
|||
propertyPath: m_AnchoredPosition.y
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 1087632561348207336, guid: 784696794bc6345bc80bf49623581c2e,
|
||||
type: 3}
|
||||
propertyPath: m_TargetGraphic
|
||||
value:
|
||||
objectReference: {fileID: 1002673092}
|
||||
- target: {fileID: 1458366075964155596, guid: 784696794bc6345bc80bf49623581c2e,
|
||||
type: 3}
|
||||
propertyPath: m_AnchorMin.y
|
||||
|
@ -1554,7 +1564,7 @@ PrefabInstance:
|
|||
type: 3}
|
||||
propertyPath: m_CustomMonitorItems.Array.data[1].m_Text
|
||||
value:
|
||||
objectReference: {fileID: 733597320}
|
||||
objectReference: {fileID: 455490118}
|
||||
- target: {fileID: 4567906826058368312, guid: 784696794bc6345bc80bf49623581c2e,
|
||||
type: 3}
|
||||
propertyPath: m_CustomMonitorItems.Array.data[1].m_Format
|
||||
|
@ -1620,6 +1630,16 @@ PrefabInstance:
|
|||
propertyPath: m_SizeDelta.x
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 5526675317024915317, guid: 784696794bc6345bc80bf49623581c2e,
|
||||
type: 3}
|
||||
propertyPath: m_TargetGraphic
|
||||
value:
|
||||
objectReference: {fileID: 1002673089}
|
||||
- target: {fileID: 5526675317129615258, guid: 784696794bc6345bc80bf49623581c2e,
|
||||
type: 3}
|
||||
propertyPath: m_TargetGraphic
|
||||
value:
|
||||
objectReference: {fileID: 1002673090}
|
||||
- target: {fileID: 5758968653464739090, guid: 784696794bc6345bc80bf49623581c2e,
|
||||
type: 3}
|
||||
propertyPath: m_SizeDelta.y
|
||||
|
@ -1783,6 +1803,54 @@ RectTransform:
|
|||
type: 3}
|
||||
m_PrefabInstance: {fileID: 1002673087}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
--- !u!114 &1002673089 stripped
|
||||
MonoBehaviour:
|
||||
m_CorrespondingSourceObject: {fileID: 5526675317024915314, guid: 784696794bc6345bc80bf49623581c2e,
|
||||
type: 3}
|
||||
m_PrefabInstance: {fileID: 1002673087}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 0}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: b0e08c6080a2e4d8186f97c60518830f, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
--- !u!114 &1002673090 stripped
|
||||
MonoBehaviour:
|
||||
m_CorrespondingSourceObject: {fileID: 5526675317129615259, guid: 784696794bc6345bc80bf49623581c2e,
|
||||
type: 3}
|
||||
m_PrefabInstance: {fileID: 1002673087}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 0}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: b0e08c6080a2e4d8186f97c60518830f, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
--- !u!114 &1002673091 stripped
|
||||
MonoBehaviour:
|
||||
m_CorrespondingSourceObject: {fileID: 6638879077379268485, guid: 784696794bc6345bc80bf49623581c2e,
|
||||
type: 3}
|
||||
m_PrefabInstance: {fileID: 1002673087}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 0}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: b0e08c6080a2e4d8186f97c60518830f, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
--- !u!114 &1002673092 stripped
|
||||
MonoBehaviour:
|
||||
m_CorrespondingSourceObject: {fileID: 6720252555115459274, guid: 784696794bc6345bc80bf49623581c2e,
|
||||
type: 3}
|
||||
m_PrefabInstance: {fileID: 1002673087}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 0}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: b0e08c6080a2e4d8186f97c60518830f, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
--- !u!1 &1023851109
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
|
@ -3564,11 +3632,6 @@ PrefabInstance:
|
|||
m_Modification:
|
||||
m_TransformParent: {fileID: 1924051224}
|
||||
m_Modifications:
|
||||
- target: {fileID: 864895764861262036, guid: a4669dfbba654429bbcddf0c9b79fb8b,
|
||||
type: 3}
|
||||
propertyPath: m_IgnoreCanvasScaler
|
||||
value: 1
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 864895765507486433, guid: a4669dfbba654429bbcddf0c9b79fb8b,
|
||||
type: 3}
|
||||
propertyPath: m_AnchorMax.x
|
||||
|
@ -3727,17 +3790,17 @@ PrefabInstance:
|
|||
- target: {fileID: 1088568576793901561, guid: a4669dfbba654429bbcddf0c9b79fb8b,
|
||||
type: 3}
|
||||
propertyPath: m_LocalScale.x
|
||||
value: 1
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 1088568576793901561, guid: a4669dfbba654429bbcddf0c9b79fb8b,
|
||||
type: 3}
|
||||
propertyPath: m_LocalScale.y
|
||||
value: 1
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 1088568576793901561, guid: a4669dfbba654429bbcddf0c9b79fb8b,
|
||||
type: 3}
|
||||
propertyPath: m_LocalScale.z
|
||||
value: 1
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
m_RemovedComponents: []
|
||||
m_SourcePrefab: {fileID: 100100000, guid: a4669dfbba654429bbcddf0c9b79fb8b, type: 3}
|
||||
|
|
|
@ -1,9 +1,8 @@
|
|||
using System;
|
||||
using UnityEngine;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Coffee.UIExtensions
|
||||
{
|
||||
[Serializable]
|
||||
[System.Serializable]
|
||||
public class AnimatableProperty : ISerializationCallbackReceiver
|
||||
{
|
||||
public enum ShaderPropertyType
|
||||
|
@ -12,11 +11,11 @@ namespace Coffee.UIExtensions
|
|||
Vector,
|
||||
Float,
|
||||
Range,
|
||||
Texture
|
||||
Texture,
|
||||
}
|
||||
|
||||
[SerializeField] private string m_Name = "";
|
||||
[SerializeField] private ShaderPropertyType m_Type = ShaderPropertyType.Vector;
|
||||
[SerializeField] string m_Name = "";
|
||||
[SerializeField] ShaderPropertyType m_Type = ShaderPropertyType.Vector;
|
||||
public int id { get; private set; }
|
||||
|
||||
public ShaderPropertyType type
|
||||
|
@ -24,15 +23,6 @@ namespace Coffee.UIExtensions
|
|||
get { return m_Type; }
|
||||
}
|
||||
|
||||
void ISerializationCallbackReceiver.OnBeforeSerialize()
|
||||
{
|
||||
}
|
||||
|
||||
void ISerializationCallbackReceiver.OnAfterDeserialize()
|
||||
{
|
||||
id = Shader.PropertyToID(m_Name);
|
||||
}
|
||||
|
||||
public void UpdateMaterialProperties(Material material, MaterialPropertyBlock mpb)
|
||||
{
|
||||
if (!material.HasProperty(id)) return;
|
||||
|
@ -41,38 +31,35 @@ namespace Coffee.UIExtensions
|
|||
{
|
||||
case ShaderPropertyType.Color:
|
||||
var color = mpb.GetColor(id);
|
||||
if (color != default)
|
||||
{
|
||||
if (color != default(Color))
|
||||
material.SetColor(id, color);
|
||||
}
|
||||
|
||||
break;
|
||||
case ShaderPropertyType.Vector:
|
||||
var vector = mpb.GetVector(id);
|
||||
if (vector != default)
|
||||
{
|
||||
if (vector != default(Vector4))
|
||||
material.SetVector(id, vector);
|
||||
}
|
||||
|
||||
break;
|
||||
case ShaderPropertyType.Float:
|
||||
case ShaderPropertyType.Range:
|
||||
var value = mpb.GetFloat(id);
|
||||
if (!Mathf.Approximately(value, 0))
|
||||
{
|
||||
if (value != default(float))
|
||||
material.SetFloat(id, value);
|
||||
}
|
||||
|
||||
break;
|
||||
case ShaderPropertyType.Texture:
|
||||
var tex = mpb.GetTexture(id);
|
||||
if (tex != default(Texture))
|
||||
{
|
||||
material.SetTexture(id, tex);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public void OnBeforeSerialize()
|
||||
{
|
||||
}
|
||||
|
||||
public void OnAfterDeserialize()
|
||||
{
|
||||
id = Shader.PropertyToID(m_Name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,143 +0,0 @@
|
|||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Coffee.UIExtensions
|
||||
{
|
||||
internal static class AnimatablePropertyEditor
|
||||
{
|
||||
private static readonly GUIContent s_ContentNothing = new GUIContent("Nothing");
|
||||
private static readonly List<string> s_ActiveNames = new List<string>();
|
||||
private static readonly StringBuilder s_Sb = new StringBuilder();
|
||||
private static readonly HashSet<string> s_Names = new HashSet<string>();
|
||||
|
||||
private static string CollectActiveNames(SerializedProperty sp, List<string> result)
|
||||
{
|
||||
result.Clear();
|
||||
for (var i = 0; i < sp.arraySize; i++)
|
||||
{
|
||||
var spName = sp.GetArrayElementAtIndex(i).FindPropertyRelative("m_Name");
|
||||
if (spName == null) continue;
|
||||
|
||||
result.Add(spName.stringValue);
|
||||
}
|
||||
|
||||
s_Sb.Length = 0;
|
||||
if (result.Count == 0)
|
||||
{
|
||||
s_Sb.Append("Nothing");
|
||||
}
|
||||
else
|
||||
{
|
||||
result.Aggregate(s_Sb, (a, b) => s_Sb.AppendFormat("{0}, ", b));
|
||||
s_Sb.Length -= 2;
|
||||
}
|
||||
|
||||
return s_Sb.ToString();
|
||||
}
|
||||
|
||||
public static void Draw(SerializedProperty sp, Material[] mats)
|
||||
{
|
||||
bool isClicked;
|
||||
using (new EditorGUILayout.HorizontalScope(GUILayout.ExpandWidth(false)))
|
||||
{
|
||||
var pos = EditorGUILayout.GetControlRect(true);
|
||||
var label = new GUIContent(sp.displayName, sp.tooltip);
|
||||
var rect = EditorGUI.PrefixLabel(pos, label);
|
||||
var text = sp.hasMultipleDifferentValues
|
||||
? "-"
|
||||
: CollectActiveNames(sp, s_ActiveNames);
|
||||
isClicked = GUI.Button(rect, text, EditorStyles.popup);
|
||||
}
|
||||
|
||||
if (!isClicked) return;
|
||||
|
||||
var gm = new GenericMenu();
|
||||
gm.AddItem(s_ContentNothing, s_ActiveNames.Count == 0, () =>
|
||||
{
|
||||
sp.ClearArray();
|
||||
sp.serializedObject.ApplyModifiedProperties();
|
||||
});
|
||||
|
||||
if (!sp.hasMultipleDifferentValues)
|
||||
{
|
||||
for (var i = 0; i < sp.arraySize; i++)
|
||||
{
|
||||
var p = sp.GetArrayElementAtIndex(i);
|
||||
var name = p.FindPropertyRelative("m_Name").stringValue;
|
||||
var type = (AnimatableProperty.ShaderPropertyType)p.FindPropertyRelative("m_Type").intValue;
|
||||
AddMenu(gm, sp, new ShaderProperty(name, type), false);
|
||||
}
|
||||
}
|
||||
|
||||
s_Names.Clear();
|
||||
for (var j = 0; j < mats.Length; j++)
|
||||
{
|
||||
var mat = mats[j];
|
||||
if (!mat || !mat.shader) continue;
|
||||
|
||||
for (var i = 0; i < ShaderUtil.GetPropertyCount(mat.shader); i++)
|
||||
{
|
||||
var name = ShaderUtil.GetPropertyName(mat.shader, i);
|
||||
var type = (AnimatableProperty.ShaderPropertyType)ShaderUtil.GetPropertyType(mat.shader, i);
|
||||
if (s_Names.Contains(name)) continue;
|
||||
s_Names.Add(name);
|
||||
|
||||
AddMenu(gm, sp, new ShaderProperty(name, type), true);
|
||||
|
||||
if (type != AnimatableProperty.ShaderPropertyType.Texture) continue;
|
||||
|
||||
AddMenu(gm, sp, new ShaderProperty($"{name}_ST"), true);
|
||||
AddMenu(gm, sp, new ShaderProperty($"{name}_HDR"), true);
|
||||
AddMenu(gm, sp, new ShaderProperty($"{name}_TexelSize"), true);
|
||||
}
|
||||
}
|
||||
|
||||
gm.ShowAsContext();
|
||||
}
|
||||
|
||||
private static void AddMenu(GenericMenu menu, SerializedProperty sp, ShaderProperty prop, bool add)
|
||||
{
|
||||
if (add && s_ActiveNames.Contains(prop.name)) return;
|
||||
|
||||
var label = new GUIContent($"{prop.name} ({prop.type})");
|
||||
menu.AddItem(label, s_ActiveNames.Contains(prop.name), () =>
|
||||
{
|
||||
var index = s_ActiveNames.IndexOf(prop.name);
|
||||
if (0 <= index)
|
||||
{
|
||||
sp.DeleteArrayElementAtIndex(index);
|
||||
}
|
||||
else
|
||||
{
|
||||
sp.InsertArrayElementAtIndex(sp.arraySize);
|
||||
var p = sp.GetArrayElementAtIndex(sp.arraySize - 1);
|
||||
p.FindPropertyRelative("m_Name").stringValue = prop.name;
|
||||
p.FindPropertyRelative("m_Type").intValue = (int)prop.type;
|
||||
}
|
||||
|
||||
sp.serializedObject.ApplyModifiedProperties();
|
||||
});
|
||||
}
|
||||
|
||||
private struct ShaderProperty
|
||||
{
|
||||
public readonly string name;
|
||||
public readonly AnimatableProperty.ShaderPropertyType type;
|
||||
|
||||
public ShaderProperty(string name)
|
||||
{
|
||||
this.name = name;
|
||||
type = AnimatableProperty.ShaderPropertyType.Vector;
|
||||
}
|
||||
|
||||
public ShaderProperty(string name, AnimatableProperty.ShaderPropertyType type)
|
||||
{
|
||||
this.name = name;
|
||||
this.type = type;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,123 @@
|
|||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using ShaderPropertyType = Coffee.UIExtensions.AnimatableProperty.ShaderPropertyType;
|
||||
|
||||
namespace Coffee.UIExtensions
|
||||
{
|
||||
internal class AnimatedPropertiesEditor
|
||||
{
|
||||
private static readonly List<string> s_ActiveNames = new List<string>();
|
||||
private static readonly System.Text.StringBuilder s_Sb = new System.Text.StringBuilder();
|
||||
private static readonly HashSet<string> s_Names = new HashSet<string>();
|
||||
|
||||
private string _name;
|
||||
private ShaderPropertyType _type;
|
||||
|
||||
static string CollectActiveNames(SerializedProperty sp, List<string> result)
|
||||
{
|
||||
result.Clear();
|
||||
for (var i = 0; i < sp.arraySize; i++)
|
||||
{
|
||||
var spName = sp.GetArrayElementAtIndex(i).FindPropertyRelative("m_Name");
|
||||
if (spName == null) continue;
|
||||
|
||||
result.Add(spName.stringValue);
|
||||
}
|
||||
|
||||
s_Sb.Length = 0;
|
||||
if (result.Count == 0)
|
||||
{
|
||||
s_Sb.Append("Nothing");
|
||||
}
|
||||
else
|
||||
{
|
||||
result.Aggregate(s_Sb, (a, b) => s_Sb.AppendFormat("{0}, ", b));
|
||||
s_Sb.Length -= 2;
|
||||
}
|
||||
|
||||
return s_Sb.ToString();
|
||||
}
|
||||
|
||||
public static void DrawAnimatableProperties(SerializedProperty sp, Material[] mats)
|
||||
{
|
||||
bool isClicked;
|
||||
using (new EditorGUILayout.HorizontalScope(GUILayout.ExpandWidth(false)))
|
||||
{
|
||||
var r = EditorGUI.PrefixLabel(EditorGUILayout.GetControlRect(true), new GUIContent(sp.displayName, sp.tooltip));
|
||||
var text = sp.hasMultipleDifferentValues ? "-" : CollectActiveNames(sp, s_ActiveNames);
|
||||
isClicked = GUI.Button(r, text, EditorStyles.popup);
|
||||
}
|
||||
|
||||
if (!isClicked) return;
|
||||
|
||||
var gm = new GenericMenu();
|
||||
gm.AddItem(new GUIContent("Nothing"), s_ActiveNames.Count == 0, () =>
|
||||
{
|
||||
sp.ClearArray();
|
||||
sp.serializedObject.ApplyModifiedProperties();
|
||||
});
|
||||
|
||||
|
||||
if (!sp.hasMultipleDifferentValues)
|
||||
{
|
||||
for (var i = 0; i < sp.arraySize; i++)
|
||||
{
|
||||
var p = sp.GetArrayElementAtIndex(i);
|
||||
var name = p.FindPropertyRelative("m_Name").stringValue;
|
||||
var type = (ShaderPropertyType) p.FindPropertyRelative("m_Type").intValue;
|
||||
AddMenu(gm, sp, new AnimatedPropertiesEditor {_name = name, _type = type}, false);
|
||||
}
|
||||
}
|
||||
|
||||
s_Names.Clear();
|
||||
foreach (var mat in mats)
|
||||
{
|
||||
if (!mat || !mat.shader) continue;
|
||||
|
||||
for (var i = 0; i < ShaderUtil.GetPropertyCount(mat.shader); i++)
|
||||
{
|
||||
var pName = ShaderUtil.GetPropertyName(mat.shader, i);
|
||||
var type = (ShaderPropertyType) ShaderUtil.GetPropertyType(mat.shader, i);
|
||||
var name = string.Format("{0} ({1})", pName, type);
|
||||
if (s_Names.Contains(name)) continue;
|
||||
s_Names.Add(name);
|
||||
|
||||
AddMenu(gm, sp, new AnimatedPropertiesEditor {_name = pName, _type = type}, true);
|
||||
|
||||
if (type != ShaderPropertyType.Texture) continue;
|
||||
|
||||
AddMenu(gm, sp, new AnimatedPropertiesEditor {_name = pName + "_ST", _type = ShaderPropertyType.Vector}, true);
|
||||
AddMenu(gm, sp, new AnimatedPropertiesEditor {_name = pName + "_HDR", _type = ShaderPropertyType.Vector}, true);
|
||||
AddMenu(gm, sp, new AnimatedPropertiesEditor {_name = pName + "_TexelSize", _type = ShaderPropertyType.Vector}, true);
|
||||
}
|
||||
}
|
||||
|
||||
gm.ShowAsContext();
|
||||
}
|
||||
|
||||
private static void AddMenu(GenericMenu menu, SerializedProperty sp, AnimatedPropertiesEditor property, bool add)
|
||||
{
|
||||
if (add && s_ActiveNames.Contains(property._name)) return;
|
||||
|
||||
menu.AddItem(new GUIContent(string.Format("{0} ({1})", property._name, property._type)), s_ActiveNames.Contains(property._name), () =>
|
||||
{
|
||||
var index = s_ActiveNames.IndexOf(property._name);
|
||||
if (0 <= index)
|
||||
{
|
||||
sp.DeleteArrayElementAtIndex(index);
|
||||
}
|
||||
else
|
||||
{
|
||||
sp.InsertArrayElementAtIndex(sp.arraySize);
|
||||
var p = sp.GetArrayElementAtIndex(sp.arraySize - 1);
|
||||
p.FindPropertyRelative("m_Name").stringValue = property._name;
|
||||
p.FindPropertyRelative("m_Type").intValue = (int) property._type;
|
||||
}
|
||||
|
||||
sp.serializedObject.ApplyModifiedProperties();
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
|
@ -32,16 +32,11 @@ namespace Coffee.UIExtensions
|
|||
private static void ImportSample(string jsonGuid, string sampleName)
|
||||
{
|
||||
var jsonPath = AssetDatabase.GUIDToAssetPath(jsonGuid);
|
||||
if (string.IsNullOrEmpty(jsonPath)) return;
|
||||
|
||||
var jsonDir = Path.GetDirectoryName(jsonPath);
|
||||
if (string.IsNullOrEmpty(jsonDir)) return;
|
||||
|
||||
var packageRoot = jsonDir.Replace('\\', '/');
|
||||
var packageRoot = Path.GetDirectoryName(jsonPath).Replace('\\', '/');
|
||||
var json = File.ReadAllText(jsonPath);
|
||||
var version = Regex.Match(json, "\"version\"\\s*:\\s*\"([^\"]+)\"").Groups[1].Value;
|
||||
var src = $"{packageRoot}/Samples~/{sampleName}";
|
||||
var dst = $"Assets/Samples/{k_DisplayName}/{version}/{sampleName}";
|
||||
var src = string.Format("{0}/Samples~/{1}", packageRoot, sampleName);
|
||||
var dst = string.Format("Assets/Samples/{0}/{1}/{2}", k_DisplayName, version, sampleName);
|
||||
var previousPath = GetPreviousSamplePath(k_DisplayName, sampleName);
|
||||
|
||||
// Remove the previous sample directory.
|
||||
|
@ -51,45 +46,33 @@ namespace Coffee.UIExtensions
|
|||
+ previousPath
|
||||
+ "\n\nIt will be deleted when you update. Are you sure you want to continue?";
|
||||
if (!EditorUtility.DisplayDialog("Sample Importer", msg, "OK", "Cancel"))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
FileUtil.DeleteFileOrDirectory(previousPath);
|
||||
|
||||
var metaFile = previousPath + ".meta";
|
||||
if (File.Exists(metaFile))
|
||||
{
|
||||
FileUtil.DeleteFileOrDirectory(metaFile);
|
||||
}
|
||||
}
|
||||
|
||||
if (!Directory.Exists(dst))
|
||||
{
|
||||
FileUtil.DeleteFileOrDirectory(dst);
|
||||
}
|
||||
|
||||
var dstDir = Path.GetDirectoryName(dst);
|
||||
if (!string.IsNullOrEmpty(dstDir) && !Directory.Exists(dstDir))
|
||||
{
|
||||
if (!Directory.Exists(dstDir))
|
||||
Directory.CreateDirectory(dstDir);
|
||||
}
|
||||
|
||||
if (Directory.Exists(src))
|
||||
{
|
||||
FileUtil.CopyFileOrDirectory(src, dst);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new DirectoryNotFoundException(src);
|
||||
}
|
||||
|
||||
AssetDatabase.Refresh(ImportAssetOptions.ImportRecursive);
|
||||
}
|
||||
|
||||
private static string GetPreviousSamplePath(string displayName, string sampleName)
|
||||
{
|
||||
var sampleRoot = $"Assets/Samples/{displayName}";
|
||||
var sampleRoot = string.Format("Assets/Samples/{0}", displayName);
|
||||
var sampleRootInfo = new DirectoryInfo(sampleRoot);
|
||||
if (!sampleRootInfo.Exists) return null;
|
||||
|
||||
|
|
|
@ -1,24 +1,19 @@
|
|||
#if UNITY_2019_3_11 || UNITY_2019_3_12 || UNITY_2019_3_13 || UNITY_2019_3_14 || UNITY_2019_3_15 || UNITY_2019_4_OR_NEWER
|
||||
#define SERIALIZE_FIELD_MASKABLE
|
||||
#endif
|
||||
using UnityEditor;
|
||||
using UnityEditor.UI;
|
||||
using UnityEngine;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using UnityEditorInternal;
|
||||
using UnityEngine.UI;
|
||||
using System;
|
||||
#if UNITY_2021_2_OR_NEWER
|
||||
using UnityEditor.Overlays;
|
||||
#else
|
||||
using System.Reflection;
|
||||
#endif
|
||||
#if UNITY_2021_2_OR_NEWER
|
||||
using UnityEditor.SceneManagement;
|
||||
#elif UNITY_2018_3_OR_NEWER
|
||||
using UnityEditor.Experimental.SceneManagement;
|
||||
#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
|
||||
{
|
||||
|
@ -28,10 +23,7 @@ namespace Coffee.UIExtensions
|
|||
{
|
||||
#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)]
|
||||
[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
|
||||
|
@ -61,22 +53,24 @@ namespace Coffee.UIExtensions
|
|||
private static readonly GUIContent s_ContentRandom = new GUIContent("Random");
|
||||
private static readonly GUIContent s_ContentScale = new GUIContent("Scale");
|
||||
private static SerializedObject s_SerializedObject;
|
||||
private static bool s_XYZMode;
|
||||
|
||||
private SerializedProperty _maskable;
|
||||
private SerializedProperty _scale3D;
|
||||
private SerializedProperty _animatableProperties;
|
||||
private SerializedProperty _meshSharing;
|
||||
private SerializedProperty _groupId;
|
||||
private SerializedProperty _groupMaxId;
|
||||
private SerializedProperty _positionMode;
|
||||
private SerializedProperty _autoScaling;
|
||||
#if !SERIALIZE_FIELD_MASKABLE
|
||||
private SerializedProperty m_Maskable;
|
||||
#endif
|
||||
private SerializedProperty m_Scale3D;
|
||||
private SerializedProperty m_AnimatableProperties;
|
||||
private SerializedProperty m_MeshSharing;
|
||||
private SerializedProperty m_GroupId;
|
||||
private SerializedProperty m_GroupMaxId;
|
||||
private SerializedProperty m_AbsoluteMode;
|
||||
|
||||
|
||||
private ReorderableList _ro;
|
||||
static private bool _xyzMode;
|
||||
private bool _showMax;
|
||||
|
||||
private static readonly HashSet<Shader> s_Shaders = new HashSet<Shader>();
|
||||
private static readonly List<ParticleSystemVertexStream> s_Streams = new List<ParticleSystemVertexStream>();
|
||||
|
||||
private static readonly List<string> s_MaskablePropertyNames = new List<string>
|
||||
{
|
||||
"_Stencil",
|
||||
|
@ -84,20 +78,21 @@ namespace Coffee.UIExtensions
|
|||
"_StencilOp",
|
||||
"_StencilWriteMask",
|
||||
"_StencilReadMask",
|
||||
"_ColorMask"
|
||||
"_ColorMask",
|
||||
};
|
||||
|
||||
|
||||
[InitializeOnLoadMethod]
|
||||
private static void Init()
|
||||
static void Init()
|
||||
{
|
||||
#if !UNITY_2021_2_OR_NEWER
|
||||
var miSceneViewOverlayWindow = Type.GetType("UnityEditor.SceneViewOverlay, UnityEditor")
|
||||
?.GetMethods(BindingFlags.Public | BindingFlags.Static)
|
||||
.GetMethods(BindingFlags.Public | BindingFlags.Static)
|
||||
.First(x => x.Name == "Window" && 5 <= x.GetParameters().Length);
|
||||
var windowFunction = (Action<Object, SceneView>)WindowFunction;
|
||||
var windowFunction = (Action<UnityEngine.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)));
|
||||
var windowTitle = new GUIContent(ObjectNames.NicifyVariableName(typeof(UIParticle).Name));
|
||||
#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 };
|
||||
|
@ -107,7 +102,7 @@ namespace Coffee.UIExtensions
|
|||
#endif
|
||||
|
||||
#if UNITY_2019_1_OR_NEWER
|
||||
SceneView.duringSceneGui += _ =>
|
||||
SceneView.duringSceneGui += _ => { if (s_SerializedObject != null) miSceneViewOverlayWindow.Invoke(null, sceneViewArgs); };
|
||||
#else
|
||||
SceneView.onSceneGUIDelegate += _ =>
|
||||
#endif
|
||||
|
@ -119,21 +114,25 @@ namespace Coffee.UIExtensions
|
|||
};
|
||||
#endif
|
||||
|
||||
SerializedObject CreateSerializeObject()
|
||||
Func<SerializedObject> createSerializeObject = () =>
|
||||
{
|
||||
var uiParticles = Selection.gameObjects.Select(x => x.GetComponent<ParticleSystem>())
|
||||
var uiParticles = Selection.gameObjects
|
||||
.Select(x => x.GetComponent<ParticleSystem>())
|
||||
.Where(x => x)
|
||||
.Select(x => x.GetComponentInParent<UIParticle>(true))
|
||||
.Select(x => x.GetComponentInParent<UIParticle>())
|
||||
.Where(x => x && x.canvas)
|
||||
.Concat(Selection.gameObjects.Select(x => x.GetComponent<UIParticle>())
|
||||
.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();
|
||||
s_SerializedObject = createSerializeObject();
|
||||
Selection.selectionChanged += () => s_SerializedObject = createSerializeObject();
|
||||
}
|
||||
|
||||
//################################
|
||||
|
@ -146,21 +145,19 @@ namespace Coffee.UIExtensions
|
|||
{
|
||||
base.OnEnable();
|
||||
|
||||
_maskable = serializedObject.FindProperty("m_Maskable");
|
||||
_scale3D = serializedObject.FindProperty("m_Scale3D");
|
||||
_animatableProperties = serializedObject.FindProperty("m_AnimatableProperties");
|
||||
_meshSharing = serializedObject.FindProperty("m_MeshSharing");
|
||||
_groupId = serializedObject.FindProperty("m_GroupId");
|
||||
_groupMaxId = serializedObject.FindProperty("m_GroupMaxId");
|
||||
_positionMode = serializedObject.FindProperty("m_PositionMode");
|
||||
_autoScaling = serializedObject.FindProperty("m_AutoScaling");
|
||||
m_Maskable = serializedObject.FindProperty("m_Maskable");
|
||||
m_Scale3D = serializedObject.FindProperty("m_Scale3D");
|
||||
m_AnimatableProperties = serializedObject.FindProperty("m_AnimatableProperties");
|
||||
m_MeshSharing = serializedObject.FindProperty("m_MeshSharing");
|
||||
m_GroupId = serializedObject.FindProperty("m_GroupId");
|
||||
m_GroupMaxId = serializedObject.FindProperty("m_GroupMaxId");
|
||||
m_AbsoluteMode = serializedObject.FindProperty("m_AbsoluteMode");
|
||||
|
||||
var sp = serializedObject.FindProperty("m_Particles");
|
||||
_ro = new ReorderableList(sp.serializedObject, sp, true, true, true, true)
|
||||
{
|
||||
elementHeight = EditorGUIUtility.singleLineHeight * 3 + 4,
|
||||
elementHeightCallback = _ => 3 * (EditorGUIUtility.singleLineHeight + 2),
|
||||
drawElementCallback = (rect, index, _, __) =>
|
||||
_ro = new ReorderableList(sp.serializedObject, sp, true, true, true, true);
|
||||
_ro.elementHeight = (EditorGUIUtility.singleLineHeight * 3) + 4;
|
||||
_ro.elementHeightCallback = _ => 3 * (EditorGUIUtility.singleLineHeight + 2);
|
||||
_ro.drawElementCallback = (rect, index, _, __) =>
|
||||
{
|
||||
EditorGUI.BeginDisabledGroup(sp.hasMultipleDifferentValues);
|
||||
rect.y += 1;
|
||||
|
@ -182,35 +179,29 @@ namespace Coffee.UIExtensions
|
|||
{
|
||||
materials.serializedObject.ApplyModifiedProperties();
|
||||
}
|
||||
},
|
||||
drawHeaderCallback = rect =>
|
||||
};
|
||||
_ro.drawHeaderCallback = rect =>
|
||||
{
|
||||
#if !UNITY_2019_3_OR_NEWER
|
||||
rect.y -= 1;
|
||||
#endif
|
||||
var pos = new Rect(rect.x, rect.y, 150, rect.height);
|
||||
EditorGUI.LabelField(pos, s_ContentRenderingOrder);
|
||||
EditorGUI.LabelField(new Rect(rect.x, rect.y, 150, rect.height), s_ContentRenderingOrder);
|
||||
|
||||
pos = new Rect(rect.width - 35, rect.y, 60, rect.height);
|
||||
if (GUI.Button(pos, s_ContentRefresh, EditorStyles.miniButton))
|
||||
if (GUI.Button(new Rect(rect.width - 35, rect.y, 60, rect.height), s_ContentRefresh, EditorStyles.miniButton))
|
||||
{
|
||||
foreach (var uip in targets.OfType<UIParticle>())
|
||||
foreach (UIParticle t in targets)
|
||||
{
|
||||
uip.RefreshParticles();
|
||||
EditorUtility.SetDirty(uip);
|
||||
}
|
||||
t.RefreshParticles();
|
||||
EditorUtility.SetDirty(t);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// On select UIParticle, refresh particles.
|
||||
if (!Application.isPlaying)
|
||||
foreach (UIParticle t in targets)
|
||||
{
|
||||
foreach (var uip in targets.OfType<UIParticle>())
|
||||
{
|
||||
if (PrefabUtility.GetPrefabAssetType(uip) != PrefabAssetType.NotAPrefab) continue;
|
||||
uip.RefreshParticles(uip.particles);
|
||||
}
|
||||
if (Application.isPlaying || PrefabUtility.GetPrefabAssetType(t) != PrefabAssetType.NotAPrefab) continue;
|
||||
t.RefreshParticles(t.particles);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -239,11 +230,11 @@ namespace Coffee.UIExtensions
|
|||
serializedObject.Update();
|
||||
|
||||
// Maskable
|
||||
EditorGUILayout.PropertyField(_maskable);
|
||||
EditorGUILayout.PropertyField(m_Maskable);
|
||||
|
||||
// Scale
|
||||
EditorGUI.BeginDisabledGroup(!_meshSharing.hasMultipleDifferentValues && _meshSharing.intValue == 4);
|
||||
s_XYZMode = DrawFloatOrVector3Field(_scale3D, s_XYZMode);
|
||||
EditorGUI.BeginDisabledGroup(!m_MeshSharing.hasMultipleDifferentValues && m_MeshSharing.intValue == 4);
|
||||
_xyzMode = DrawFloatOrVector3Field(m_Scale3D, _xyzMode);
|
||||
EditorGUI.EndDisabledGroup();
|
||||
|
||||
// AnimatableProperties
|
||||
|
@ -253,11 +244,12 @@ namespace Coffee.UIExtensions
|
|||
.Where(x => x)
|
||||
.ToArray();
|
||||
|
||||
AnimatablePropertyEditor.Draw(_animatableProperties, mats);
|
||||
// Animated properties
|
||||
AnimatedPropertiesEditor.DrawAnimatableProperties(m_AnimatableProperties, mats);
|
||||
|
||||
// Mesh sharing
|
||||
EditorGUI.BeginChangeCheck();
|
||||
_showMax = DrawMeshSharing(_meshSharing, _groupId, _groupMaxId, _showMax);
|
||||
_showMax = DrawMeshSharing(m_MeshSharing, m_GroupId, m_GroupMaxId, _showMax);
|
||||
if (EditorGUI.EndChangeCheck())
|
||||
{
|
||||
serializedObject.ApplyModifiedProperties();
|
||||
|
@ -267,11 +259,8 @@ namespace Coffee.UIExtensions
|
|||
}
|
||||
}
|
||||
|
||||
// Position Mode
|
||||
EditorGUILayout.PropertyField(_positionMode);
|
||||
|
||||
// Auto Scaling
|
||||
DrawAutoScaling(_autoScaling, targets.OfType<UIParticle>());
|
||||
// Absolute Mode
|
||||
EditorGUILayout.PropertyField(m_AbsoluteMode);
|
||||
|
||||
// Target ParticleSystems.
|
||||
EditorGUI.BeginChangeCheck();
|
||||
|
@ -287,22 +276,8 @@ namespace Coffee.UIExtensions
|
|||
}
|
||||
}
|
||||
|
||||
// Non-UI built-in shader is not supported.
|
||||
foreach (var mat in current.materials)
|
||||
{
|
||||
if (!mat || !mat.shader) continue;
|
||||
var shader = mat.shader;
|
||||
if (IsBuiltInObject(shader) && !shader.name.StartsWith("UI/"))
|
||||
{
|
||||
EditorGUILayout.HelpBox(
|
||||
$"Built-in shader '{shader.name}' in '{mat.name}' is not supported.\n" +
|
||||
"Use UI shaders instead.",
|
||||
MessageType.Error);
|
||||
}
|
||||
}
|
||||
|
||||
// Does the shader support UI masks?
|
||||
if (current.maskable && current.GetComponentInParent<Mask>(false))
|
||||
if (current.maskable && current.GetComponentInParent<Mask>())
|
||||
{
|
||||
foreach (var mat in current.materials)
|
||||
{
|
||||
|
@ -314,20 +289,15 @@ namespace Coffee.UIExtensions
|
|||
{
|
||||
if (mat.HasProperty(propName)) continue;
|
||||
|
||||
EditorGUILayout.HelpBox(
|
||||
$"Shader '{shader.name}' doesn't have '{propName}' property." +
|
||||
"\nThis graphic cannot be masked.",
|
||||
MessageType.Warning);
|
||||
EditorGUILayout.HelpBox(string.Format("Shader '{0}' doesn't have '{1}' property. This graphic cannot be masked.", shader.name, propName), MessageType.Warning);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
s_Shaders.Clear();
|
||||
|
||||
// UIParticle for trail should be removed.
|
||||
var label = "This UIParticle component should be removed. The UIParticle for trails is no longer needed.";
|
||||
if (FixButton(current.m_IsTrail, label))
|
||||
if (FixButton(current.m_IsTrail, "This UIParticle component should be removed. The UIParticle for trails is no longer needed."))
|
||||
{
|
||||
DestroyUIParticle(current);
|
||||
}
|
||||
|
@ -343,9 +313,7 @@ namespace Coffee.UIExtensions
|
|||
{
|
||||
var so = new SerializedObject(allPsRenderers);
|
||||
var sp = so.FindProperty("m_ApplyActiveColorSpace");
|
||||
label = "When using linear color space, the particle colors are not output correctly.\n" +
|
||||
"To fix, set 'Apply Active Color Space' in renderer module to false.";
|
||||
if (FixButton(sp.boolValue || sp.hasMultipleDifferentValues, label))
|
||||
if (FixButton(sp.boolValue || sp.hasMultipleDifferentValues, "When using linear color space, the particle colors are not output correctly.\nTo fix, set 'Apply Active Color Space' in renderer module to false."))
|
||||
{
|
||||
sp.boolValue = false;
|
||||
so.ApplyModifiedProperties();
|
||||
|
@ -360,21 +328,10 @@ namespace Coffee.UIExtensions
|
|||
|
||||
if (2 < s_Streams.Select(GetUsedComponentCount).Sum())
|
||||
{
|
||||
EditorGUILayout.HelpBox(
|
||||
$"ParticleSystem '{psr.name}' uses 'TEXCOORD*.zw' components as custom vertex stream.\n" +
|
||||
"UIParticle does not support it (See README.md).",
|
||||
MessageType.Warning);
|
||||
}
|
||||
|
||||
s_Streams.Clear();
|
||||
EditorGUILayout.HelpBox(string.Format("ParticleSystem '{0}' uses 'TEXCOORD*.zw' components as custom vertex stream.\nUIParticle does not support it (See README.md).", psr.name), MessageType.Warning);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private bool IsBuiltInObject(Object obj)
|
||||
{
|
||||
return AssetDatabase.TryGetGUIDAndLocalFileIdentifier(obj, out var guid, out long _)
|
||||
&& Regex.IsMatch(guid, "^0{16}.0{15}$", RegexOptions.Compiled);
|
||||
}
|
||||
|
||||
private static int GetUsedComponentCount(ParticleSystemVertexStream s)
|
||||
|
@ -432,12 +389,10 @@ namespace Coffee.UIExtensions
|
|||
case ParticleSystemVertexStream.Custom2XYZW:
|
||||
return 4;
|
||||
}
|
||||
|
||||
return 3;
|
||||
}
|
||||
|
||||
private static bool DrawMeshSharing(SerializedProperty spMeshSharing, SerializedProperty spGroupId,
|
||||
SerializedProperty spGroupMaxId, bool showMax)
|
||||
private static bool DrawMeshSharing(SerializedProperty spMeshSharing, SerializedProperty spGroupId, SerializedProperty spGroupMaxId, bool showMax)
|
||||
{
|
||||
showMax |= spGroupId.intValue != spGroupMaxId.intValue ||
|
||||
spGroupId.hasMultipleDifferentValues ||
|
||||
|
@ -449,10 +404,7 @@ namespace Coffee.UIExtensions
|
|||
EditorGUI.BeginChangeCheck();
|
||||
showMax = GUILayout.Toggle(showMax, s_ContentRandom, EditorStyles.miniButton, GUILayout.Width(60));
|
||||
if (EditorGUI.EndChangeCheck() && !showMax)
|
||||
{
|
||||
spGroupMaxId.intValue = spGroupId.intValue;
|
||||
}
|
||||
|
||||
EditorGUILayout.EndHorizontal();
|
||||
|
||||
EditorGUI.BeginDisabledGroup(spMeshSharing.intValue == 0);
|
||||
|
@ -465,41 +417,20 @@ namespace Coffee.UIExtensions
|
|||
else if (spMeshSharing.intValue == 1 || spMeshSharing.intValue == 4)
|
||||
{
|
||||
EditorGUI.BeginDisabledGroup(true);
|
||||
var obj = UIParticleUpdater.GetPrimary(spGroupId.intValue);
|
||||
EditorGUILayout.ObjectField("Primary", obj, typeof(UIParticle), false);
|
||||
EditorGUILayout.ObjectField("Primary", UIParticleUpdater.GetPrimary(spGroupId.intValue), typeof(UIParticle), false);
|
||||
EditorGUI.EndDisabledGroup();
|
||||
}
|
||||
|
||||
EditorGUI.indentLevel--;
|
||||
EditorGUI.EndDisabledGroup();
|
||||
|
||||
return showMax;
|
||||
}
|
||||
|
||||
private static void DrawAutoScaling(SerializedProperty prop, IEnumerable<UIParticle> uiParticles)
|
||||
{
|
||||
EditorGUI.BeginChangeCheck();
|
||||
EditorGUILayout.PropertyField(prop);
|
||||
if (!EditorGUI.EndChangeCheck()) return;
|
||||
|
||||
// on changed true->false, reset scale.
|
||||
EditorApplication.delayCall += () =>
|
||||
{
|
||||
foreach (var uip in uiParticles)
|
||||
{
|
||||
if (!uip || uip.autoScaling) continue;
|
||||
uip.transform.localScale = Vector3.one;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private static void WindowFunction(Object target, SceneView sceneView)
|
||||
private static void WindowFunction(UnityEngine.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;
|
||||
if (s_SerializedObject.targetObjects.OfType<UIParticle>().Any(x => !x || !x.canvas)) return;
|
||||
|
||||
s_SerializedObject.Update();
|
||||
using (new EditorGUILayout.VerticalScope(GUILayout.Width(220f)))
|
||||
|
@ -507,36 +438,37 @@ namespace Coffee.UIExtensions
|
|||
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_AutoScaling"), uiParticles);
|
||||
_xyzMode = DrawFloatOrVector3Field(s_SerializedObject.FindProperty("m_Scale3D"), _xyzMode);
|
||||
EditorGUILayout.PropertyField(s_SerializedObject.FindProperty("m_AbsoluteMode"));
|
||||
EditorGUIUtility.labelWidth = labelWidth;
|
||||
}
|
||||
|
||||
s_SerializedObject.ApplyModifiedProperties();
|
||||
}
|
||||
catch
|
||||
{
|
||||
// ignored
|
||||
}
|
||||
}
|
||||
|
||||
private void DestroyUIParticle(UIParticle p, bool ignoreCurrent = false)
|
||||
{
|
||||
if (!p || (ignoreCurrent && target == p)) return;
|
||||
if (!p || ignoreCurrent && target == p) return;
|
||||
|
||||
var cr = p.canvasRenderer;
|
||||
DestroyImmediate(p);
|
||||
DestroyImmediate(cr);
|
||||
|
||||
#if UNITY_2021_2_OR_NEWER
|
||||
var stage = UnityEditor.SceneManagement.PrefabStageUtility.GetCurrentPrefabStage();
|
||||
#elif UNITY_2018_3_OR_NEWER
|
||||
var stage = UnityEditor.Experimental.SceneManagement.PrefabStageUtility.GetCurrentPrefabStage();
|
||||
#endif
|
||||
#if UNITY_2018_3_OR_NEWER
|
||||
var stage = PrefabStageUtility.GetCurrentPrefabStage();
|
||||
if (stage != null && stage.scene.isLoaded)
|
||||
{
|
||||
#if UNITY_2020_1_OR_NEWER
|
||||
string prefabAssetPath = stage.assetPath;
|
||||
#else
|
||||
var prefabAssetPath = stage.prefabAssetPath;
|
||||
string prefabAssetPath = stage.prefabAssetPath;
|
||||
#endif
|
||||
PrefabUtility.SaveAsPrefabAsset(stage.prefabContentsRoot, prefabAssetPath);
|
||||
}
|
||||
|
@ -585,10 +517,7 @@ namespace Coffee.UIExtensions
|
|||
EditorGUI.BeginChangeCheck();
|
||||
showXyz = GUILayout.Toggle(showXyz, s_Content3D, EditorStyles.miniButton, GUILayout.Width(30));
|
||||
if (EditorGUI.EndChangeCheck() && !showXyz)
|
||||
{
|
||||
z.floatValue = y.floatValue = x.floatValue;
|
||||
}
|
||||
|
||||
EditorGUILayout.EndHorizontal();
|
||||
|
||||
return showXyz;
|
||||
|
|
|
@ -34,10 +34,10 @@ namespace Coffee.UIExtensions
|
|||
ps.transform.SetParent(uiParticle.transform, false);
|
||||
ps.transform.localPosition = Vector3.zero;
|
||||
|
||||
// Assign default material (UIAdditive).
|
||||
// Assign default material.
|
||||
var renderer = ps.GetComponent<ParticleSystemRenderer>();
|
||||
var path = AssetDatabase.GUIDToAssetPath("9944483a3e009401ba5dcc42f14d5c63");
|
||||
renderer.material = AssetDatabase.LoadAssetAtPath<Material>(path);
|
||||
var defaultMat = AssetDatabase.GetBuiltinExtraResource<Material>("Default-Particle.mat");
|
||||
renderer.material = defaultMat ? defaultMat : renderer.material;
|
||||
|
||||
// Refresh particles.
|
||||
uiParticle.RefreshParticles();
|
||||
|
|
|
@ -10,7 +10,7 @@ namespace Coffee.UIParticleExtensions
|
|||
public static Material Add(Material baseMat, Texture texture, int id)
|
||||
{
|
||||
MatEntry e;
|
||||
for (var i = 0; i < s_Entries.Count; i++)
|
||||
for (var i = 0; i < s_Entries.Count; ++i)
|
||||
{
|
||||
e = s_Entries[i];
|
||||
if (e.baseMat != baseMat || e.texture != texture || e.id != id) continue;
|
||||
|
@ -18,19 +18,15 @@ namespace Coffee.UIParticleExtensions
|
|||
return e.customMat;
|
||||
}
|
||||
|
||||
e = new MatEntry
|
||||
{
|
||||
count = 1,
|
||||
baseMat = baseMat,
|
||||
texture = texture,
|
||||
id = id,
|
||||
customMat = new Material(baseMat)
|
||||
{
|
||||
name = $"{baseMat.name}_{id}",
|
||||
hideFlags = HideFlags.HideAndDontSave,
|
||||
mainTexture = texture ? texture : null
|
||||
}
|
||||
};
|
||||
e = new MatEntry();
|
||||
e.count = 1;
|
||||
e.baseMat = baseMat;
|
||||
e.texture = texture;
|
||||
e.id = id;
|
||||
e.customMat = new Material(baseMat);
|
||||
e.customMat.hideFlags = HideFlags.HideAndDontSave;
|
||||
if (texture)
|
||||
e.customMat.mainTexture = texture;
|
||||
s_Entries.Add(e);
|
||||
//Debug.LogFormat(">>>> ModifiedMaterial.Add -> count = count:{0}, mat:{1}, tex:{2}, id:{3}", s_Entries.Count, baseMat, texture, id);
|
||||
return e.customMat;
|
||||
|
@ -47,8 +43,7 @@ namespace Coffee.UIParticleExtensions
|
|||
if (--e.count == 0)
|
||||
{
|
||||
//Debug.LogFormat(">>>> ModifiedMaterial.Remove -> count:{0}, mat:{1}, tex:{2}, id:{3}", s_Entries.Count - 1, e.customMat, e.texture, e.id);
|
||||
Misc.DestroyImmediate(e.customMat);
|
||||
e.customMat = null;
|
||||
DestroyImmediate(e.customMat);
|
||||
e.baseMat = null;
|
||||
e.texture = null;
|
||||
s_Entries.RemoveAt(i);
|
||||
|
@ -58,13 +53,22 @@ namespace Coffee.UIParticleExtensions
|
|||
}
|
||||
}
|
||||
|
||||
private static void DestroyImmediate(Object obj)
|
||||
{
|
||||
if (!obj) return;
|
||||
if (Application.isEditor)
|
||||
Object.DestroyImmediate(obj);
|
||||
else
|
||||
Object.Destroy(obj);
|
||||
}
|
||||
|
||||
private class MatEntry
|
||||
{
|
||||
public Material baseMat;
|
||||
public int count;
|
||||
public Material customMat;
|
||||
public int id;
|
||||
public int count;
|
||||
public Texture texture;
|
||||
public int id;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,11 +2,11 @@
|
|||
#define SERIALIZE_FIELD_MASKABLE
|
||||
#endif
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Runtime.CompilerServices;
|
||||
using Coffee.UIParticleExtensions;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Rendering;
|
||||
using UnityEngine.Serialization;
|
||||
using UnityEngine.UI;
|
||||
|
||||
[assembly: InternalsVisibleTo("Coffee.UIParticle.Editor")]
|
||||
|
@ -19,7 +19,7 @@ namespace Coffee.UIExtensions
|
|||
[ExecuteAlways]
|
||||
[RequireComponent(typeof(RectTransform))]
|
||||
[RequireComponent(typeof(CanvasRenderer))]
|
||||
public class UIParticle : MaskableGraphic, ISerializationCallbackReceiver
|
||||
public class UIParticle : MaskableGraphic
|
||||
{
|
||||
public enum MeshSharing
|
||||
{
|
||||
|
@ -27,34 +27,16 @@ namespace Coffee.UIExtensions
|
|||
Auto,
|
||||
Primary,
|
||||
PrimarySimulator,
|
||||
Replica
|
||||
Reprica,
|
||||
}
|
||||
|
||||
public enum PositionMode
|
||||
{
|
||||
Relative,
|
||||
Absolute
|
||||
}
|
||||
|
||||
[HideInInspector]
|
||||
[SerializeField]
|
||||
internal bool m_IsTrail;
|
||||
|
||||
[HideInInspector]
|
||||
[FormerlySerializedAs("m_IgnoreParent")]
|
||||
[SerializeField]
|
||||
private bool m_IgnoreCanvasScaler;
|
||||
|
||||
[HideInInspector]
|
||||
[SerializeField]
|
||||
private bool m_AbsoluteMode;
|
||||
[HideInInspector][SerializeField] internal bool m_IsTrail = false;
|
||||
|
||||
[Tooltip("Particle effect scale")]
|
||||
[SerializeField]
|
||||
private Vector3 m_Scale3D = new Vector3(10, 10, 10);
|
||||
|
||||
[Tooltip("Animatable material properties.\n" +
|
||||
"If you want to change the material properties of the ParticleSystem in Animation, enable it.")]
|
||||
[Tooltip("Animatable material properties. If you want to change the material properties of the ParticleSystem in Animation, enable it.")]
|
||||
[SerializeField]
|
||||
internal AnimatableProperty[] m_AnimatableProperties = new AnimatableProperty[0];
|
||||
|
||||
|
@ -62,44 +44,33 @@ namespace Coffee.UIExtensions
|
|||
[SerializeField]
|
||||
private List<ParticleSystem> m_Particles = new List<ParticleSystem>();
|
||||
|
||||
[Tooltip("Mesh sharing.\n" +
|
||||
"None: disable mesh sharing.\n" +
|
||||
"Auto: automatically select Primary/Replica.\n" +
|
||||
"Primary: provides particle simulation results to the same group.\n" +
|
||||
"Primary Simulator: Primary, but do not render the particle (simulation only).\n" +
|
||||
"Replica: render simulation results provided by the primary.")]
|
||||
[Tooltip("Mesh sharing.None: disable mesh sharing.\nAuto: automatically select Primary/Reprica.\nPrimary: provides particle simulation results to the same group.\nPrimary Simulator: Primary, but do not render the particle (simulation only).\nReprica: render simulation results provided by the primary.")]
|
||||
[SerializeField]
|
||||
private MeshSharing m_MeshSharing = MeshSharing.None;
|
||||
|
||||
[Tooltip("Mesh sharing group ID.\n" +
|
||||
"If non-zero is specified, particle simulation results are shared within the group.")]
|
||||
[Tooltip("Mesh sharing group ID. If non-zero is specified, particle simulation results are shared within the group.")]
|
||||
[SerializeField]
|
||||
private int m_GroupId;
|
||||
private int m_GroupId = 0;
|
||||
|
||||
[SerializeField]
|
||||
private int m_GroupMaxId;
|
||||
|
||||
[Tooltip("Relative: The particles will be emitted from the scaled position of ParticleSystem.\n" +
|
||||
"Absolute: The particles will be emitted from the world position of ParticleSystem.")]
|
||||
[SerializeField]
|
||||
private PositionMode m_PositionMode = PositionMode.Relative;
|
||||
private int m_GroupMaxId = 0;
|
||||
|
||||
[SerializeField]
|
||||
[Tooltip("Transform.lossyScale (=world scale) is automatically set to (1, 1, 1), " +
|
||||
"to prevent the root-Canvas scale from affecting the hierarchy-scaled ParticleSystem.")]
|
||||
private bool m_AutoScaling = true;
|
||||
[Tooltip("The particles will be emitted at the ParticleSystem position.\nMove the UIParticle/ParticleSystem to move the particle.")]
|
||||
private bool m_AbsoluteMode = false;
|
||||
|
||||
private List<UIParticleRenderer> m_Renderers = new List<UIParticleRenderer>();
|
||||
|
||||
#if !SERIALIZE_FIELD_MASKABLE
|
||||
[SerializeField]
|
||||
private bool m_Maskable = true;
|
||||
[SerializeField] private bool m_Maskable = true;
|
||||
#endif
|
||||
private readonly List<UIParticleRenderer> _renderers = new List<UIParticleRenderer>();
|
||||
private int _groupId;
|
||||
private Camera _orthoCamera;
|
||||
|
||||
private DrivenRectTransformTracker _tracker;
|
||||
private Camera _orthoCamera;
|
||||
private int _groupId;
|
||||
|
||||
/// <summary>
|
||||
/// Should this graphic be considered a target for ray-casting?
|
||||
/// Should this graphic be considered a target for raycasting?
|
||||
/// </summary>
|
||||
public override bool raycastTarget
|
||||
{
|
||||
|
@ -108,12 +79,11 @@ namespace Coffee.UIExtensions
|
|||
}
|
||||
|
||||
/// <summary>
|
||||
/// Mesh sharing.
|
||||
/// None: disable mesh sharing.
|
||||
/// Auto: automatically select Primary/Replica.
|
||||
/// Mesh sharing.None: disable mesh sharing.
|
||||
/// Auto: automatically select Primary/Reprica.
|
||||
/// 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.
|
||||
/// Reprica: render simulation results provided by the primary.
|
||||
/// </summary>
|
||||
public MeshSharing meshSharing
|
||||
{
|
||||
|
@ -122,8 +92,7 @@ namespace Coffee.UIExtensions
|
|||
}
|
||||
|
||||
/// <summary>
|
||||
/// Mesh sharing group ID.
|
||||
/// If non-zero is specified, particle simulation results are shared within the group.
|
||||
/// Mesh sharing group ID. If non-zero is specified, particle simulation results are shared within the group.
|
||||
/// </summary>
|
||||
public int groupId
|
||||
{
|
||||
|
@ -133,11 +102,9 @@ namespace Coffee.UIExtensions
|
|||
if (m_GroupId == value) return;
|
||||
m_GroupId = value;
|
||||
if (m_GroupId != m_GroupMaxId)
|
||||
{
|
||||
ResetGroupId();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public int groupMaxId
|
||||
{
|
||||
|
@ -151,40 +118,14 @@ namespace Coffee.UIExtensions
|
|||
}
|
||||
|
||||
/// <summary>
|
||||
/// Particle position mode.
|
||||
/// Relative: The particles will be emitted from the scaled position of the ParticleSystem.
|
||||
/// Absolute: The particles will be emitted from the world position of the ParticleSystem.
|
||||
/// </summary>
|
||||
public PositionMode positionMode
|
||||
{
|
||||
get { return m_PositionMode; }
|
||||
set { m_PositionMode = value; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Particle position mode.
|
||||
/// Relative: The particles will be emitted from the scaled position of the ParticleSystem.
|
||||
/// Absolute: The particles will be emitted from the world position of the ParticleSystem.
|
||||
/// Absolute particle position mode.
|
||||
/// The particles will be emitted at the ParticleSystem position.
|
||||
/// Move the UIParticle/ParticleSystem to move the particle.
|
||||
/// </summary>
|
||||
public bool absoluteMode
|
||||
{
|
||||
get { return m_PositionMode == PositionMode.Absolute; }
|
||||
set { positionMode = value ? PositionMode.Absolute : PositionMode.Relative; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Transform.lossyScale (=world scale) will be set to (1, 1, 1) on update.
|
||||
/// It prevents the root-Canvas scale from affecting the hierarchy-scaled ParticleSystem.
|
||||
/// </summary>
|
||||
public bool autoScaling
|
||||
{
|
||||
get { return m_AutoScaling; }
|
||||
set
|
||||
{
|
||||
if (m_AutoScaling == value) return;
|
||||
m_AutoScaling = value;
|
||||
UpdateTracker();
|
||||
}
|
||||
get { return m_AbsoluteMode; }
|
||||
set { m_AbsoluteMode = value; }
|
||||
}
|
||||
|
||||
internal bool useMeshSharing
|
||||
|
@ -194,33 +135,17 @@ namespace Coffee.UIExtensions
|
|||
|
||||
internal bool isPrimary
|
||||
{
|
||||
get
|
||||
{
|
||||
return m_MeshSharing == MeshSharing.Primary
|
||||
|| m_MeshSharing == MeshSharing.PrimarySimulator;
|
||||
}
|
||||
get { return m_MeshSharing == MeshSharing.Primary || m_MeshSharing == MeshSharing.PrimarySimulator; }
|
||||
}
|
||||
|
||||
internal bool canSimulate
|
||||
{
|
||||
get
|
||||
{
|
||||
return m_MeshSharing == MeshSharing.None
|
||||
|| m_MeshSharing == MeshSharing.Auto
|
||||
|| m_MeshSharing == MeshSharing.Primary
|
||||
|| m_MeshSharing == MeshSharing.PrimarySimulator;
|
||||
}
|
||||
get { return m_MeshSharing == MeshSharing.None || m_MeshSharing == MeshSharing.Auto || m_MeshSharing == MeshSharing.Primary || m_MeshSharing == MeshSharing.PrimarySimulator; }
|
||||
}
|
||||
|
||||
internal bool canRender
|
||||
{
|
||||
get
|
||||
{
|
||||
return m_MeshSharing == MeshSharing.None
|
||||
|| m_MeshSharing == MeshSharing.Auto
|
||||
|| m_MeshSharing == MeshSharing.Primary
|
||||
|| m_MeshSharing == MeshSharing.Replica;
|
||||
}
|
||||
get { return m_MeshSharing == MeshSharing.None || m_MeshSharing == MeshSharing.Auto || m_MeshSharing == MeshSharing.Primary || m_MeshSharing == MeshSharing.Reprica; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -253,12 +178,12 @@ namespace Coffee.UIExtensions
|
|||
{
|
||||
get
|
||||
{
|
||||
for (var i = 0; i < _renderers.Count; i++)
|
||||
for (var i = 0; i < m_Renderers.Count; i++)
|
||||
{
|
||||
var r = _renderers[i];
|
||||
if (!r || !r.material) continue;
|
||||
yield return r.material;
|
||||
if (!m_Renderers[i] || !m_Renderers[i].material) continue;
|
||||
yield return m_Renderers[i].material;
|
||||
}
|
||||
yield break;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -270,78 +195,7 @@ namespace Coffee.UIExtensions
|
|||
/// <summary>
|
||||
/// Paused.
|
||||
/// </summary>
|
||||
public bool isPaused { get; private set; }
|
||||
|
||||
public Vector3 parentScale { get; private set; }
|
||||
|
||||
protected override void OnEnable()
|
||||
{
|
||||
#if !SERIALIZE_FIELD_MASKABLE
|
||||
maskable = m_Maskable;
|
||||
#endif
|
||||
ResetGroupId();
|
||||
UpdateTracker();
|
||||
UIParticleUpdater.Register(this);
|
||||
RegisterDirtyMaterialCallback(UpdateRendererMaterial);
|
||||
|
||||
if (0 < particles.Count)
|
||||
{
|
||||
RefreshParticles(particles);
|
||||
}
|
||||
else
|
||||
{
|
||||
RefreshParticles();
|
||||
}
|
||||
|
||||
base.OnEnable();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This function is called when the behaviour becomes disabled.
|
||||
/// </summary>
|
||||
protected override void OnDisable()
|
||||
{
|
||||
UpdateTracker();
|
||||
UIParticleUpdater.Unregister(this);
|
||||
_renderers.ForEach(r => r.Reset());
|
||||
UnregisterDirtyMaterialCallback(UpdateRendererMaterial);
|
||||
|
||||
base.OnDisable();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Callback for when properties have been changed by animation.
|
||||
/// </summary>
|
||||
protected override void OnDidApplyAnimationProperties()
|
||||
{
|
||||
}
|
||||
|
||||
#if UNITY_EDITOR
|
||||
protected override void OnValidate()
|
||||
{
|
||||
base.OnValidate();
|
||||
UpdateTracker();
|
||||
}
|
||||
#endif
|
||||
|
||||
void ISerializationCallbackReceiver.OnBeforeSerialize()
|
||||
{
|
||||
}
|
||||
|
||||
void ISerializationCallbackReceiver.OnAfterDeserialize()
|
||||
{
|
||||
if (m_IgnoreCanvasScaler)
|
||||
{
|
||||
m_IgnoreCanvasScaler = false;
|
||||
m_AutoScaling = false;
|
||||
}
|
||||
|
||||
if (m_AbsoluteMode)
|
||||
{
|
||||
m_AbsoluteMode = false;
|
||||
m_PositionMode = PositionMode.Absolute;
|
||||
}
|
||||
}
|
||||
public bool isPaused { get; internal set; }
|
||||
|
||||
public void Play()
|
||||
{
|
||||
|
@ -366,24 +220,6 @@ namespace Coffee.UIExtensions
|
|||
isPaused = true;
|
||||
}
|
||||
|
||||
public void StartEmission()
|
||||
{
|
||||
particles.Exec(p =>
|
||||
{
|
||||
var emission = p.emission;
|
||||
emission.enabled = true;
|
||||
});
|
||||
}
|
||||
|
||||
public void StopEmission()
|
||||
{
|
||||
particles.Exec(p =>
|
||||
{
|
||||
var emission = p.emission;
|
||||
emission.enabled = false;
|
||||
});
|
||||
}
|
||||
|
||||
public void Clear()
|
||||
{
|
||||
particles.Exec(p => p.Clear());
|
||||
|
@ -403,10 +239,14 @@ namespace Coffee.UIExtensions
|
|||
{
|
||||
var go = child.gameObject;
|
||||
go.SetActive(false);
|
||||
if (destroyOldParticles)
|
||||
{
|
||||
Misc.Destroy(go);
|
||||
}
|
||||
if (!destroyOldParticles) continue;
|
||||
|
||||
#if UNITY_EDITOR
|
||||
if (!Application.isPlaying)
|
||||
DestroyImmediate(go);
|
||||
else
|
||||
#endif
|
||||
Destroy(go);
|
||||
}
|
||||
|
||||
var tr = instance.transform;
|
||||
|
@ -431,60 +271,48 @@ namespace Coffee.UIExtensions
|
|||
private void RefreshParticles(GameObject root)
|
||||
{
|
||||
if (!root) return;
|
||||
root.GetComponentsInChildren(true, particles);
|
||||
particles.RemoveAll(x => x.GetComponentInParent<UIParticle>(true) != this);
|
||||
root.GetComponentsInChildren(particles);
|
||||
particles.RemoveAll(x => x.GetComponentInParent<UIParticle>() != this);
|
||||
|
||||
for (var i = 0; i < particles.Count; i++)
|
||||
foreach (var ps in particles)
|
||||
{
|
||||
var ps = particles[i];
|
||||
var tsa = ps.textureSheetAnimation;
|
||||
if (tsa.mode == ParticleSystemAnimationMode.Sprites && tsa.uvChannelMask == 0)
|
||||
{
|
||||
tsa.uvChannelMask = UVChannelFlags.UV0;
|
||||
}
|
||||
}
|
||||
|
||||
RefreshParticles(particles);
|
||||
}
|
||||
|
||||
public void RefreshParticles(List<ParticleSystem> particles)
|
||||
{
|
||||
// #246: Nullptr exceptions when using nested UIParticle components in hierarchy
|
||||
_renderers.Clear();
|
||||
foreach (Transform child in transform)
|
||||
{
|
||||
var uiParticleRenderer = child.GetComponent<UIParticleRenderer>();
|
||||
|
||||
if (uiParticleRenderer != null)
|
||||
{
|
||||
_renderers.Add(uiParticleRenderer);
|
||||
}
|
||||
}
|
||||
|
||||
for (var i = 0; i < _renderers.Count; i++)
|
||||
{
|
||||
_renderers[i].Reset(i);
|
||||
}
|
||||
GetComponentsInChildren(m_Renderers);
|
||||
|
||||
var j = 0;
|
||||
for (var i = 0; i < particles.Count; i++)
|
||||
{
|
||||
var ps = particles[i];
|
||||
if (!ps) continue;
|
||||
GetRenderer(j++).Set(this, ps, false);
|
||||
if (ps.trails.enabled)
|
||||
if (!particles[i]) continue;
|
||||
GetRenderer(j++).Set(this, particles[i], false);
|
||||
if (particles[i].trails.enabled)
|
||||
{
|
||||
GetRenderer(j++).Set(this, ps, true);
|
||||
GetRenderer(j++).Set(this, particles[i], true);
|
||||
}
|
||||
}
|
||||
|
||||
for (; j < m_Renderers.Count; j++)
|
||||
{
|
||||
GetRenderer(j).Clear(j);
|
||||
}
|
||||
}
|
||||
|
||||
internal void UpdateTransformScale()
|
||||
{
|
||||
parentScale = transform.parent.lossyScale;
|
||||
if (!autoScaling) return;
|
||||
|
||||
var newScale = parentScale.Inverse();
|
||||
//var newScale = Vector3.one;
|
||||
//if (uiScaling)
|
||||
//{
|
||||
// newScale = transform.parent.lossyScale.Inverse();
|
||||
//}
|
||||
var newScale = transform.parent.lossyScale.Inverse();
|
||||
if (transform.localScale != newScale)
|
||||
{
|
||||
transform.localScale = newScale;
|
||||
|
@ -495,40 +323,73 @@ namespace Coffee.UIExtensions
|
|||
{
|
||||
if (!isActiveAndEnabled) return;
|
||||
|
||||
for (var i = 0; i < _renderers.Count; i++)
|
||||
{
|
||||
var r = _renderers[i];
|
||||
if (!r)
|
||||
if (m_Renderers.Any(x => !x))
|
||||
{
|
||||
RefreshParticles(particles);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
var bakeCamera = GetBakeCamera();
|
||||
for (var i = 0; i < _renderers.Count; i++)
|
||||
for (var i = 0; i < m_Renderers.Count; i++)
|
||||
{
|
||||
var r = _renderers[i];
|
||||
if (!r) continue;
|
||||
r.UpdateMesh(bakeCamera);
|
||||
if (!m_Renderers[i]) continue;
|
||||
m_Renderers[i].UpdateMesh(bakeCamera);
|
||||
}
|
||||
}
|
||||
|
||||
internal void UpdateParticleCount()
|
||||
{
|
||||
for (var i = 0; i < _renderers.Count; i++)
|
||||
for (var i = 0; i < m_Renderers.Count; i++)
|
||||
{
|
||||
var r = _renderers[i];
|
||||
if (!r) continue;
|
||||
r.UpdateParticleCount();
|
||||
if (!m_Renderers[i]) continue;
|
||||
m_Renderers[i].UpdateParticleCount();
|
||||
}
|
||||
}
|
||||
|
||||
protected override void OnEnable()
|
||||
{
|
||||
#if !SERIALIZE_FIELD_MASKABLE
|
||||
maskable = m_Maskable;
|
||||
#endif
|
||||
ResetGroupId();
|
||||
_tracker.Add(this, rectTransform, DrivenTransformProperties.Scale);
|
||||
UIParticleUpdater.Register(this);
|
||||
RegisterDirtyMaterialCallback(UpdateRendererMaterial);
|
||||
|
||||
if (0 < particles.Count)
|
||||
{
|
||||
RefreshParticles(particles);
|
||||
}
|
||||
else
|
||||
{
|
||||
RefreshParticles();
|
||||
}
|
||||
|
||||
base.OnEnable();
|
||||
}
|
||||
|
||||
internal void ResetGroupId()
|
||||
{
|
||||
_groupId = m_GroupId == m_GroupMaxId
|
||||
? m_GroupId
|
||||
: Random.Range(m_GroupId, m_GroupMaxId + 1);
|
||||
if (m_GroupId == m_GroupMaxId)
|
||||
{
|
||||
_groupId = m_GroupId;
|
||||
}
|
||||
else
|
||||
{
|
||||
_groupId = Random.Range(m_GroupId, m_GroupMaxId + 1);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This function is called when the behaviour becomes disabled.
|
||||
/// </summary>
|
||||
protected override void OnDisable()
|
||||
{
|
||||
_tracker.Clear();
|
||||
UIParticleUpdater.Unregister(this);
|
||||
m_Renderers.ForEach(r => r.Clear());
|
||||
UnregisterDirtyMaterialCallback(UpdateRendererMaterial);
|
||||
|
||||
base.OnDisable();
|
||||
}
|
||||
|
||||
protected override void UpdateMaterial()
|
||||
|
@ -542,61 +403,54 @@ namespace Coffee.UIExtensions
|
|||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Callback for when properties have been changed by animation.
|
||||
/// </summary>
|
||||
protected override void OnDidApplyAnimationProperties()
|
||||
{
|
||||
}
|
||||
|
||||
private void UpdateRendererMaterial()
|
||||
{
|
||||
for (var i = 0; i < _renderers.Count; i++)
|
||||
for (var i = 0; i < m_Renderers.Count; i++)
|
||||
{
|
||||
var r = _renderers[i];
|
||||
if (!r) continue;
|
||||
r.maskable = maskable;
|
||||
r.SetMaterialDirty();
|
||||
if (!m_Renderers[i]) continue;
|
||||
m_Renderers[i].maskable = maskable;
|
||||
m_Renderers[i].SetMaterialDirty();
|
||||
}
|
||||
}
|
||||
|
||||
internal UIParticleRenderer GetRenderer(int index)
|
||||
{
|
||||
if (_renderers.Count <= index)
|
||||
if (m_Renderers.Count <= index)
|
||||
{
|
||||
_renderers.Add(UIParticleRenderer.AddRenderer(this, index));
|
||||
m_Renderers.Add(UIParticleRenderer.AddRenderer(this, index));
|
||||
}
|
||||
|
||||
if (!_renderers[index])
|
||||
if (!m_Renderers[index])
|
||||
{
|
||||
_renderers[index] = UIParticleRenderer.AddRenderer(this, index);
|
||||
m_Renderers[index] = UIParticleRenderer.AddRenderer(this, index);
|
||||
}
|
||||
|
||||
return _renderers[index];
|
||||
return m_Renderers[index];
|
||||
}
|
||||
|
||||
private Camera GetBakeCamera()
|
||||
{
|
||||
if (!canvas) return Camera.main;
|
||||
|
||||
// When render mode is ScreenSpaceCamera or WorldSpace, use world camera.
|
||||
// World camera.
|
||||
var root = canvas.rootCanvas;
|
||||
if (root.renderMode != RenderMode.ScreenSpaceOverlay)
|
||||
{
|
||||
return root.worldCamera ? root.worldCamera : Camera.main;
|
||||
}
|
||||
|
||||
// When render mode is ScreenSpaceOverlay, use ortho-camera.
|
||||
if (!_orthoCamera)
|
||||
{
|
||||
// Find existing ortho-camera.
|
||||
foreach (Transform child in transform)
|
||||
{
|
||||
var cam = child.GetComponent<Camera>();
|
||||
if (cam && cam.name == "[generated] UIParticleOverlayCamera")
|
||||
{
|
||||
_orthoCamera = cam;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (root.renderMode != RenderMode.ScreenSpaceOverlay) return root.worldCamera ? root.worldCamera : Camera.main;
|
||||
|
||||
// Create ortho-camera.
|
||||
if (!_orthoCamera)
|
||||
{
|
||||
var go = new GameObject("[generated] UIParticleOverlayCamera") { hideFlags = HideFlags.DontSave };
|
||||
_orthoCamera = GetComponentInChildren<Camera>();
|
||||
if (!_orthoCamera)
|
||||
{
|
||||
var go = new GameObject("UIParticleOverlayCamera")
|
||||
{
|
||||
hideFlags = HideFlags.DontSave,
|
||||
};
|
||||
go.SetActive(false);
|
||||
go.transform.SetParent(transform, false);
|
||||
_orthoCamera = go.AddComponent<Camera>();
|
||||
|
@ -613,17 +467,5 @@ namespace Coffee.UIExtensions
|
|||
|
||||
return _orthoCamera;
|
||||
}
|
||||
|
||||
private void UpdateTracker()
|
||||
{
|
||||
if (!enabled || !autoScaling)
|
||||
{
|
||||
_tracker.Clear();
|
||||
}
|
||||
else
|
||||
{
|
||||
_tracker.Add(this, rectTransform, DrivenTransformProperties.Scale);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
using System;
|
||||
using UnityEngine;
|
||||
using Coffee.UIParticleExtensions;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Events;
|
||||
using System;
|
||||
|
||||
namespace Coffee.UIExtensions
|
||||
{
|
||||
|
@ -12,13 +12,7 @@ namespace Coffee.UIExtensions
|
|||
{
|
||||
Linear,
|
||||
Smooth,
|
||||
Sphere
|
||||
}
|
||||
|
||||
public enum UpdateMode
|
||||
{
|
||||
Normal,
|
||||
UnscaledTime
|
||||
Sphere,
|
||||
}
|
||||
|
||||
[SerializeField]
|
||||
|
@ -30,7 +24,7 @@ namespace Coffee.UIExtensions
|
|||
|
||||
[Range(0f, 0.95f)]
|
||||
[SerializeField]
|
||||
private float m_DelayRate;
|
||||
private float m_DelayRate = 0;
|
||||
|
||||
[Range(0.001f, 100f)]
|
||||
[SerializeField]
|
||||
|
@ -39,79 +33,68 @@ namespace Coffee.UIExtensions
|
|||
[SerializeField]
|
||||
private Movement m_Movement;
|
||||
|
||||
[SerializeField]
|
||||
private UpdateMode m_UpdateMode;
|
||||
|
||||
[SerializeField]
|
||||
private UnityEvent m_OnAttracted;
|
||||
|
||||
private UIParticle _uiParticle;
|
||||
|
||||
public float destinationRadius
|
||||
{
|
||||
get { return m_DestinationRadius; }
|
||||
set { m_DestinationRadius = Mathf.Clamp(value, 0.1f, 10f); }
|
||||
}
|
||||
|
||||
public float delay
|
||||
{
|
||||
get { return m_DelayRate; }
|
||||
set { m_DelayRate = value; }
|
||||
get
|
||||
{
|
||||
return m_DelayRate;
|
||||
}
|
||||
set
|
||||
{
|
||||
m_DelayRate = value;
|
||||
}
|
||||
}
|
||||
|
||||
public float maxSpeed
|
||||
{
|
||||
get { return m_MaxSpeed; }
|
||||
set { m_MaxSpeed = value; }
|
||||
get
|
||||
{
|
||||
return m_MaxSpeed;
|
||||
}
|
||||
set
|
||||
{
|
||||
m_MaxSpeed = value;
|
||||
}
|
||||
}
|
||||
|
||||
public Movement movement
|
||||
{
|
||||
get { return m_Movement; }
|
||||
set { m_Movement = value; }
|
||||
}
|
||||
|
||||
public UpdateMode updateMode
|
||||
get
|
||||
{
|
||||
get { return m_UpdateMode; }
|
||||
set { m_UpdateMode = value; }
|
||||
return m_Movement;
|
||||
}
|
||||
|
||||
public UnityEvent onAttracted
|
||||
{
|
||||
get { return m_OnAttracted; }
|
||||
set { m_OnAttracted = value; }
|
||||
}
|
||||
|
||||
#if UNITY_EDITOR
|
||||
public new ParticleSystem particleSystem
|
||||
#else
|
||||
public ParticleSystem particleSystem
|
||||
#endif
|
||||
{
|
||||
get { return m_ParticleSystem; }
|
||||
set
|
||||
{
|
||||
m_ParticleSystem = value;
|
||||
ApplyParticleSystem();
|
||||
m_Movement = value;
|
||||
}
|
||||
}
|
||||
|
||||
private UIParticle _uiParticle;
|
||||
|
||||
private void OnEnable()
|
||||
{
|
||||
ApplyParticleSystem();
|
||||
if (m_ParticleSystem == null)
|
||||
{
|
||||
Debug.LogError("No particle system attached to particle attractor script", this);
|
||||
enabled = false;
|
||||
return;
|
||||
}
|
||||
|
||||
_uiParticle = m_ParticleSystem.GetComponentInParent<UIParticle>();
|
||||
if (_uiParticle && !_uiParticle.particles.Contains(m_ParticleSystem))
|
||||
{
|
||||
_uiParticle = null;
|
||||
}
|
||||
UIParticleUpdater.Register(this);
|
||||
}
|
||||
|
||||
private void OnDisable()
|
||||
{
|
||||
UIParticleUpdater.Unregister(this);
|
||||
}
|
||||
|
||||
private void OnDestroy()
|
||||
{
|
||||
_uiParticle = null;
|
||||
m_ParticleSystem = null;
|
||||
UIParticleUpdater.Unregister(this);
|
||||
}
|
||||
|
||||
internal void Attract()
|
||||
|
@ -145,7 +128,6 @@ namespace Coffee.UIExtensions
|
|||
Debug.LogException(e);
|
||||
}
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -172,51 +154,36 @@ namespace Coffee.UIExtensions
|
|||
var psPos = m_ParticleSystem.transform.position;
|
||||
var attractorPos = transform.position;
|
||||
var dstPos = attractorPos;
|
||||
var isLocalSpace = m_ParticleSystem.IsLocalSpace();
|
||||
|
||||
if (isLocalSpace)
|
||||
if (m_ParticleSystem.main.simulationSpace == ParticleSystemSimulationSpace.Local)
|
||||
{
|
||||
dstPos = m_ParticleSystem.transform.InverseTransformPoint(dstPos);
|
||||
}
|
||||
|
||||
if (isUI)
|
||||
{
|
||||
var inverseScale = _uiParticle.parentScale.Inverse();
|
||||
dstPos = dstPos.GetScaled(inverseScale, _uiParticle.scale3D.Inverse());
|
||||
|
||||
// Relative mode
|
||||
if (_uiParticle.positionMode == UIParticle.PositionMode.Relative)
|
||||
{
|
||||
var diff = _uiParticle.transform.position - psPos;
|
||||
diff.Scale(_uiParticle.scale3D - inverseScale);
|
||||
diff.Scale(_uiParticle.scale3D.Inverse());
|
||||
dstPos += diff;
|
||||
dstPos = dstPos.GetScaled(_uiParticle.transform.localScale, _uiParticle.scale3D.Inverse());
|
||||
}
|
||||
|
||||
#if UNITY_EDITOR
|
||||
if (!Application.isPlaying && !isLocalSpace)
|
||||
}
|
||||
else
|
||||
{
|
||||
dstPos += psPos - psPos.GetScaled(inverseScale, _uiParticle.scale3D.Inverse());
|
||||
#if UNITY_EDITOR
|
||||
if (!Application.isPlaying && isUI)
|
||||
{
|
||||
var diff = dstPos - psPos;
|
||||
diff = diff.GetScaled(_uiParticle.transform.localScale, _uiParticle.scale3D.Inverse());
|
||||
return psPos + diff;
|
||||
}
|
||||
#endif
|
||||
if (isUI)
|
||||
{
|
||||
dstPos.Scale(_uiParticle.transform.localScale);
|
||||
dstPos.Scale(_uiParticle.scale3D.Inverse());
|
||||
}
|
||||
}
|
||||
|
||||
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:
|
||||
|
@ -233,26 +200,5 @@ namespace Coffee.UIExtensions
|
|||
return Vector3.MoveTowards(current, target, speed);
|
||||
}
|
||||
|
||||
private void ApplyParticleSystem()
|
||||
{
|
||||
_uiParticle = null;
|
||||
if (m_ParticleSystem == null)
|
||||
{
|
||||
#if UNITY_EDITOR
|
||||
if (Application.isPlaying)
|
||||
#endif
|
||||
{
|
||||
Debug.LogError("No particle system attached to particle attractor script", this);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
_uiParticle = m_ParticleSystem.GetComponentInParent<UIParticle>(true);
|
||||
if (_uiParticle && !_uiParticle.particles.Contains(m_ParticleSystem))
|
||||
{
|
||||
_uiParticle = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,10 +1,9 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
using Coffee.UIParticleExtensions;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Profiling;
|
||||
using UnityEngine.Rendering;
|
||||
using UnityEngine.UI;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Coffee.UIExtensions
|
||||
{
|
||||
|
@ -14,34 +13,41 @@ namespace Coffee.UIExtensions
|
|||
[AddComponentMenu("")]
|
||||
internal class UIParticleRenderer : MaskableGraphic
|
||||
{
|
||||
private static readonly CombineInstance[] s_CombineInstances = { new CombineInstance() };
|
||||
private static readonly CombineInstance[] s_CombineInstances = new CombineInstance[] { new CombineInstance() };
|
||||
private static readonly List<Material> s_Materials = new List<Material>(2);
|
||||
private static MaterialPropertyBlock s_Mpb;
|
||||
private static readonly List<UIParticleRenderer> s_Renderers = new List<UIParticleRenderer>();
|
||||
private static readonly Vector3[] s_Corners = new Vector3[4];
|
||||
private Material _currentMaterialForRendering;
|
||||
private bool _delay;
|
||||
|
||||
private ParticleSystemRenderer _renderer;
|
||||
private ParticleSystem _particleSystem;
|
||||
private int _prevParticleCount = 0;
|
||||
private UIParticle _parent;
|
||||
private int _index;
|
||||
private bool _isTrail;
|
||||
private Bounds _lastBounds;
|
||||
private Material _modifiedMaterial;
|
||||
private UIParticle _parent;
|
||||
private ParticleSystem _particleSystem;
|
||||
private int _prevParticleCount;
|
||||
private Vector3 _prevPsPos;
|
||||
private Vector3 _prevScale;
|
||||
private Vector3 _prevPsPos;
|
||||
private Vector2Int _prevScreenSize;
|
||||
private bool _prewarm;
|
||||
private ParticleSystemRenderer _renderer;
|
||||
private bool _delay = false;
|
||||
private bool _prewarm = false;
|
||||
private Material _currentMaterialForRendering;
|
||||
private Bounds _lastBounds;
|
||||
|
||||
public override Texture mainTexture
|
||||
{
|
||||
get { return _isTrail ? null : _particleSystem.GetTextureForSprite(); }
|
||||
get
|
||||
{
|
||||
return _isTrail ? null : _particleSystem.GetTextureForSprite();
|
||||
}
|
||||
}
|
||||
|
||||
public override bool raycastTarget
|
||||
{
|
||||
get { return false; }
|
||||
get
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private Rect rootCanvasRect
|
||||
|
@ -56,103 +62,32 @@ namespace Coffee.UIExtensions
|
|||
{
|
||||
var worldToLocalMatrix = canvas.rootCanvas.transform.worldToLocalMatrix;
|
||||
for (var i = 0; i < 4; ++i)
|
||||
{
|
||||
s_Corners[i] = worldToLocalMatrix.MultiplyPoint(s_Corners[i]);
|
||||
}
|
||||
}
|
||||
|
||||
var corner1 = (Vector2)s_Corners[0];
|
||||
var corner2 = (Vector2)s_Corners[0];
|
||||
var corner1 = (Vector2) s_Corners[0];
|
||||
var corner2 = (Vector2) s_Corners[0];
|
||||
for (var i = 1; i < 4; ++i)
|
||||
{
|
||||
if (s_Corners[i].x < corner1.x)
|
||||
{
|
||||
corner1.x = s_Corners[i].x;
|
||||
}
|
||||
else if (s_Corners[i].x > corner2.x)
|
||||
{
|
||||
corner2.x = s_Corners[i].x;
|
||||
}
|
||||
|
||||
if (s_Corners[i].y < corner1.y)
|
||||
{
|
||||
corner1.y = s_Corners[i].y;
|
||||
}
|
||||
else if (s_Corners[i].y > corner2.y)
|
||||
{
|
||||
corner2.y = s_Corners[i].y;
|
||||
}
|
||||
}
|
||||
|
||||
return new Rect(corner1, corner2 - corner1);
|
||||
}
|
||||
}
|
||||
|
||||
public void Reset(int index = -1)
|
||||
{
|
||||
if (_renderer)
|
||||
{
|
||||
_renderer.enabled = true;
|
||||
}
|
||||
|
||||
_parent = null;
|
||||
_particleSystem = null;
|
||||
_renderer = null;
|
||||
_prevParticleCount = 0;
|
||||
if (0 <= index)
|
||||
{
|
||||
_index = index;
|
||||
}
|
||||
|
||||
//_emitter = null;
|
||||
if (this && isActiveAndEnabled)
|
||||
{
|
||||
material = null;
|
||||
workerMesh.Clear();
|
||||
canvasRenderer.SetMesh(workerMesh);
|
||||
_lastBounds = new Bounds();
|
||||
enabled = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
ModifiedMaterial.Remove(_modifiedMaterial);
|
||||
_modifiedMaterial = null;
|
||||
_currentMaterialForRendering = null;
|
||||
}
|
||||
}
|
||||
|
||||
protected override void OnEnable()
|
||||
{
|
||||
base.OnEnable();
|
||||
|
||||
if (!s_CombineInstances[0].mesh)
|
||||
{
|
||||
s_CombineInstances[0].mesh = new Mesh
|
||||
{
|
||||
name = "[UIParticleRenderer] Combine Instance Mesh",
|
||||
hideFlags = HideFlags.HideAndDontSave
|
||||
};
|
||||
}
|
||||
|
||||
_currentMaterialForRendering = null;
|
||||
}
|
||||
|
||||
protected override void OnDisable()
|
||||
{
|
||||
base.OnDisable();
|
||||
|
||||
ModifiedMaterial.Remove(_modifiedMaterial);
|
||||
_modifiedMaterial = null;
|
||||
_currentMaterialForRendering = null;
|
||||
}
|
||||
|
||||
public static UIParticleRenderer AddRenderer(UIParticle parent, int index)
|
||||
{
|
||||
// Create renderer object.
|
||||
var go = new GameObject("[generated] UIParticleRenderer", typeof(UIParticleRenderer))
|
||||
var go = new GameObject("UIParticleRenderer", typeof(UIParticleRenderer))
|
||||
{
|
||||
hideFlags = HideFlags.DontSave,
|
||||
layer = parent.gameObject.layer
|
||||
layer = parent.gameObject.layer,
|
||||
};
|
||||
|
||||
// Set parent.
|
||||
|
@ -177,12 +112,7 @@ namespace Coffee.UIExtensions
|
|||
{
|
||||
_currentMaterialForRendering = null;
|
||||
|
||||
if (!IsActive() || !_parent)
|
||||
{
|
||||
ModifiedMaterial.Remove(_modifiedMaterial);
|
||||
_modifiedMaterial = null;
|
||||
return baseMaterial;
|
||||
}
|
||||
if (!IsActive()) return baseMaterial;
|
||||
|
||||
var modifiedMaterial = base.GetModifiedMaterial(baseMaterial);
|
||||
|
||||
|
@ -204,28 +134,50 @@ namespace Coffee.UIExtensions
|
|||
return modifiedMaterial;
|
||||
}
|
||||
|
||||
public void Set(UIParticle parent, ParticleSystem ps, bool isTrail)
|
||||
public void Clear(int index = -1)
|
||||
{
|
||||
if (_renderer)
|
||||
{
|
||||
_renderer.enabled = true;
|
||||
}
|
||||
_parent = null;
|
||||
_particleSystem = null;
|
||||
_renderer = null;
|
||||
_prevParticleCount = 0;
|
||||
if (0 <= index)
|
||||
{
|
||||
_index = index;
|
||||
}
|
||||
//_emitter = null;
|
||||
if (this && isActiveAndEnabled)
|
||||
{
|
||||
material = null;
|
||||
workerMesh.Clear();
|
||||
canvasRenderer.SetMesh(workerMesh);
|
||||
_lastBounds = new Bounds();
|
||||
enabled = false;
|
||||
}
|
||||
}
|
||||
|
||||
public void Set(UIParticle parent, ParticleSystem particleSystem, bool isTrail)
|
||||
{
|
||||
_parent = parent;
|
||||
maskable = parent.maskable;
|
||||
|
||||
gameObject.layer = parent.gameObject.layer;
|
||||
|
||||
_particleSystem = ps;
|
||||
_prewarm = _particleSystem.main.prewarm;
|
||||
|
||||
_particleSystem = particleSystem;
|
||||
#if UNITY_EDITOR
|
||||
if (Application.isPlaying)
|
||||
#endif
|
||||
{
|
||||
if (_particleSystem.isPlaying || _prewarm)
|
||||
if (_particleSystem.isPlaying)
|
||||
{
|
||||
_particleSystem.Clear();
|
||||
_particleSystem.Pause();
|
||||
}
|
||||
}
|
||||
_prewarm = _particleSystem.main.prewarm;
|
||||
|
||||
_renderer = ps.GetComponent<ParticleSystemRenderer>();
|
||||
_renderer = particleSystem.GetComponent<ParticleSystemRenderer>();
|
||||
_renderer.enabled = false;
|
||||
|
||||
//_emitter = emitter;
|
||||
|
@ -236,11 +188,9 @@ namespace Coffee.UIExtensions
|
|||
s_Materials.Clear();
|
||||
|
||||
// Support sprite.
|
||||
var tsa = ps.textureSheetAnimation;
|
||||
var tsa = particleSystem.textureSheetAnimation;
|
||||
if (tsa.mode == ParticleSystemAnimationMode.Sprites && tsa.uvChannelMask == 0)
|
||||
{
|
||||
tsa.uvChannelMask = UVChannelFlags.UV0;
|
||||
}
|
||||
|
||||
_prevScale = GetWorldScale();
|
||||
_prevPsPos = _particleSystem.transform.position;
|
||||
|
@ -257,15 +207,13 @@ namespace Coffee.UIExtensions
|
|||
{
|
||||
// No particle to render: Clear mesh.
|
||||
if (
|
||||
!isActiveAndEnabled || !_particleSystem || !_parent
|
||||
|| !canvasRenderer || !canvas || !bakeCamera
|
||||
|| _parent.meshSharing == UIParticle.MeshSharing.Replica
|
||||
!isActiveAndEnabled || !_particleSystem || !_parent || !canvasRenderer || !canvas || !bakeCamera
|
||||
|| _parent.meshSharing == UIParticle.MeshSharing.Reprica
|
||||
|| !transform.lossyScale.GetScaled(_parent.scale3D).IsVisible() // Scale is not visible.
|
||||
|| (!_particleSystem.IsAlive() && !_particleSystem.isPlaying) // No particle.
|
||||
|| (_isTrail && !_particleSystem.trails.enabled) // Trail, but it is not enabled.
|
||||
#if UNITY_2018_3_OR_NEWER
|
||||
|| canvasRenderer.GetInheritedAlpha() <
|
||||
0.01f // #102: Do not bake particle system to mesh when the alpha is zero.
|
||||
|| canvasRenderer.GetInheritedAlpha() < 0.01f // #102: Do not bake particle system to mesh when the alpha is zero.
|
||||
#endif
|
||||
)
|
||||
{
|
||||
|
@ -303,25 +251,20 @@ namespace Coffee.UIExtensions
|
|||
}
|
||||
|
||||
// When the ParticleSystem simulation is complete, stop it.
|
||||
if (!main.loop
|
||||
&& main.duration <= _particleSystem.time
|
||||
&& (_particleSystem.IsAlive() || _particleSystem.particleCount == 0)
|
||||
)
|
||||
if (!main.loop && main.duration <= _particleSystem.time && (_particleSystem.IsAlive() || _particleSystem.particleCount == 0))
|
||||
{
|
||||
_particleSystem.Stop(false);
|
||||
}
|
||||
}
|
||||
|
||||
_prevScale = scale;
|
||||
_prevPsPos = psPos;
|
||||
_delay = false;
|
||||
}
|
||||
|
||||
Profiler.EndSample();
|
||||
|
||||
// Bake mesh.
|
||||
Profiler.BeginSample("[UIParticleRenderer] Bake Mesh");
|
||||
if (_isTrail && _parent.canSimulate && 0 < s_CombineInstances[0].mesh.vertexCount)
|
||||
if (_isTrail && _parent.canSimulate)
|
||||
{
|
||||
_renderer.BakeTrailsMesh(s_CombineInstances[0].mesh, bakeCamera, true);
|
||||
}
|
||||
|
@ -333,41 +276,21 @@ namespace Coffee.UIExtensions
|
|||
{
|
||||
s_CombineInstances[0].mesh.Clear(false);
|
||||
}
|
||||
|
||||
// Too many vertices to render.
|
||||
if (65535 <= s_CombineInstances[0].mesh.vertexCount)
|
||||
{
|
||||
s_CombineInstances[0].mesh.Clear(false);
|
||||
Debug.LogErrorFormat(this,
|
||||
"Too many vertices to render. index={0}, isTrail={1}, vertexCount={2}(>=65535)",
|
||||
_index,
|
||||
_isTrail,
|
||||
s_CombineInstances[0].mesh.vertexCount
|
||||
);
|
||||
s_CombineInstances[0].mesh.Clear(false);
|
||||
}
|
||||
|
||||
Profiler.EndSample();
|
||||
|
||||
// Combine mesh to transform. ([ParticleSystem local ->] world -> renderer local)
|
||||
Profiler.BeginSample("[UIParticleRenderer] Combine Mesh");
|
||||
if (_parent.canSimulate)
|
||||
{
|
||||
if (_parent.positionMode == UIParticle.PositionMode.Absolute)
|
||||
if (_parent.absoluteMode)
|
||||
{
|
||||
s_CombineInstances[0].transform =
|
||||
canvasRenderer.transform.worldToLocalMatrix
|
||||
* GetWorldMatrix(psPos, scale);
|
||||
s_CombineInstances[0].transform = canvasRenderer.transform.worldToLocalMatrix * GetWorldMatrix(psPos, scale);
|
||||
}
|
||||
else
|
||||
{
|
||||
var diff = _particleSystem.transform.position - _parent.transform.position;
|
||||
s_CombineInstances[0].transform =
|
||||
canvasRenderer.transform.worldToLocalMatrix
|
||||
* Matrix4x4.Translate(diff.GetScaled(scale - Vector3.one))
|
||||
* GetWorldMatrix(psPos, scale);
|
||||
s_CombineInstances[0].transform = canvasRenderer.transform.worldToLocalMatrix * Matrix4x4.Translate(diff.GetScaled(scale - Vector3.one)) * GetWorldMatrix(psPos, scale);
|
||||
}
|
||||
|
||||
workerMesh.CombineMeshes(s_CombineInstances, true, true);
|
||||
|
||||
workerMesh.RecalculateBounds();
|
||||
|
@ -381,7 +304,6 @@ namespace Coffee.UIExtensions
|
|||
workerMesh.bounds = bounds;
|
||||
_lastBounds = bounds;
|
||||
}
|
||||
|
||||
Profiler.EndSample();
|
||||
|
||||
|
||||
|
@ -394,7 +316,7 @@ namespace Coffee.UIExtensions
|
|||
|
||||
// Set mesh to the CanvasRenderer.
|
||||
Profiler.BeginSample("[UIParticleRenderer] Set Mesh");
|
||||
for (var i = 0; i < s_Renderers.Count; i++)
|
||||
for (int i = 0; i < s_Renderers.Count; i++)
|
||||
{
|
||||
if (s_Renderers[i] == this) continue;
|
||||
s_Renderers[i].canvasRenderer.SetMesh(workerMesh);
|
||||
|
@ -405,7 +327,6 @@ namespace Coffee.UIExtensions
|
|||
{
|
||||
workerMesh.Clear();
|
||||
}
|
||||
|
||||
canvasRenderer.SetMesh(workerMesh);
|
||||
Profiler.EndSample();
|
||||
|
||||
|
@ -418,8 +339,7 @@ namespace Coffee.UIExtensions
|
|||
{
|
||||
_currentMaterialForRendering = materialForRendering;
|
||||
}
|
||||
|
||||
for (var i = 0; i < s_Renderers.Count; i++)
|
||||
for (int i = 0; i < s_Renderers.Count; i++)
|
||||
{
|
||||
if (s_Renderers[i] == this) continue;
|
||||
|
||||
|
@ -427,7 +347,6 @@ namespace Coffee.UIExtensions
|
|||
s_Renderers[i].canvasRenderer.SetMaterial(_currentMaterialForRendering, 0);
|
||||
}
|
||||
}
|
||||
|
||||
Profiler.EndSample();
|
||||
|
||||
s_Renderers.Clear();
|
||||
|
@ -439,6 +358,30 @@ namespace Coffee.UIExtensions
|
|||
_prevParticleCount = _particleSystem.particleCount;
|
||||
}
|
||||
|
||||
protected override void OnEnable()
|
||||
{
|
||||
base.OnEnable();
|
||||
|
||||
if (!s_CombineInstances[0].mesh)
|
||||
{
|
||||
s_CombineInstances[0].mesh = new Mesh()
|
||||
{
|
||||
name = "[UIParticleRenderer] Combine Instance Mesh",
|
||||
hideFlags = HideFlags.HideAndDontSave,
|
||||
};
|
||||
}
|
||||
_currentMaterialForRendering = null;
|
||||
}
|
||||
|
||||
protected override void OnDisable()
|
||||
{
|
||||
base.OnDisable();
|
||||
|
||||
ModifiedMaterial.Remove(_modifiedMaterial);
|
||||
_modifiedMaterial = null;
|
||||
_currentMaterialForRendering = null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Call to update the geometry of the Graphic onto the CanvasRenderer.
|
||||
/// </summary>
|
||||
|
@ -448,9 +391,7 @@ namespace Coffee.UIExtensions
|
|||
|
||||
public override void Cull(Rect clipRect, bool validRect)
|
||||
{
|
||||
var cull = _lastBounds.extents == Vector3.zero
|
||||
|| !validRect
|
||||
|| !clipRect.Overlaps(rootCanvasRect, true);
|
||||
var cull = _lastBounds.extents == Vector3.zero || !validRect || !clipRect.Overlaps(rootCanvasRect, true);
|
||||
if (canvasRenderer.cull == cull) return;
|
||||
|
||||
canvasRenderer.cull = cull;
|
||||
|
@ -462,7 +403,16 @@ namespace Coffee.UIExtensions
|
|||
private Vector3 GetWorldScale()
|
||||
{
|
||||
Profiler.BeginSample("[UIParticleRenderer] GetWorldScale");
|
||||
var scale = _parent.scale3D.GetScaled(_parent.parentScale);
|
||||
var scale = _parent.scale3D;
|
||||
//if (_parent.uiScaling)
|
||||
{
|
||||
scale.Scale(_parent.transform.localScale.Inverse());
|
||||
}
|
||||
//else if (_parent.scalingMode == UIParticle.ScalingMode.UI && _particleSystem.main.scalingMode != ParticleSystemScalingMode.Hierarchy)
|
||||
//{
|
||||
// var gscale = _parent.transform.lossyScale.GetScaled(canvas.transform.lossyScale.Inverse());
|
||||
// scale.Scale(gscale * canvas.scaleFactor);
|
||||
//}
|
||||
Profiler.EndSample();
|
||||
return scale;
|
||||
}
|
||||
|
@ -502,7 +452,7 @@ namespace Coffee.UIExtensions
|
|||
//* Matrix4x4.Translate(-wpos)
|
||||
;
|
||||
default:
|
||||
throw new NotSupportedException();
|
||||
throw new System.NotSupportedException();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -514,9 +464,8 @@ namespace Coffee.UIExtensions
|
|||
private void ResolveResolutionChange(Vector3 psPos, Vector3 scale)
|
||||
{
|
||||
var screenSize = new Vector2Int(Screen.width, Screen.height);
|
||||
var isWorldSpace = _particleSystem.IsWorldSpace();
|
||||
var resolutionChanged = _prevScreenSize != screenSize || _prevScale != scale;
|
||||
if (resolutionChanged && isWorldSpace)
|
||||
//if ((_prevScreenSize != screenSize || _prevScale != scale) && _particleSystem.main.simulationSpace == ParticleSystemSimulationSpace.World && _parent.uiScaling)
|
||||
if ((_prevScreenSize != screenSize || _prevScale != scale) && _particleSystem.main.simulationSpace == ParticleSystemSimulationSpace.World)
|
||||
{
|
||||
// Update particle array size and get particles.
|
||||
var size = _particleSystem.particleCount;
|
||||
|
@ -525,17 +474,13 @@ namespace Coffee.UIExtensions
|
|||
|
||||
// Resolusion resolver:
|
||||
// (psPos / scale) / (prevPsPos / prevScale) -> psPos * scale.inv * prevPsPos.inv * prevScale
|
||||
var modifier = psPos.GetScaled(
|
||||
scale.Inverse(),
|
||||
_prevPsPos.Inverse(),
|
||||
_prevScale);
|
||||
var modifier = psPos.GetScaled(scale.Inverse(), _prevPsPos.Inverse(), _prevScale);
|
||||
for (var i = 0; i < size; i++)
|
||||
{
|
||||
var particle = particles[i];
|
||||
particle.position = particle.position.GetScaled(modifier);
|
||||
particles[i] = particle;
|
||||
}
|
||||
|
||||
_particleSystem.SetParticles(particles, size);
|
||||
|
||||
// Delay: Do not progress in the frame where the resolution has been changed.
|
||||
|
@ -543,7 +488,6 @@ namespace Coffee.UIExtensions
|
|||
_prevScale = scale;
|
||||
_prevPsPos = psPos;
|
||||
}
|
||||
|
||||
_prevScreenSize = screenSize;
|
||||
}
|
||||
|
||||
|
@ -563,8 +507,6 @@ namespace Coffee.UIExtensions
|
|||
_prewarm = false;
|
||||
}
|
||||
|
||||
// (COMMENT OUT) #231: Sub Emitters option is not work in editor playing
|
||||
/*
|
||||
// Emitted particles found.
|
||||
if (_prevParticleCount != _particleSystem.particleCount)
|
||||
{
|
||||
|
@ -580,31 +522,24 @@ namespace Coffee.UIExtensions
|
|||
|
||||
_particleSystem.SetParticles(particles, size);
|
||||
}
|
||||
*/
|
||||
|
||||
// get world position.
|
||||
var isLocalSpace = _particleSystem.IsLocalSpace();
|
||||
var psTransform = _particleSystem.transform;
|
||||
var originWorldPosition = psTransform.position;
|
||||
var originWorldRotation = psTransform.rotation;
|
||||
|
||||
var emission = _particleSystem.emission;
|
||||
var rateOverDistance = emission.enabled
|
||||
&& 0 < emission.rateOverDistance.constant
|
||||
&& 0 < emission.rateOverDistanceMultiplier;
|
||||
if (rateOverDistance && !paused)
|
||||
var rateOverDistance = emission.enabled && 0 < emission.rateOverDistance.constant && 0 < emission.rateOverDistanceMultiplier;
|
||||
if (rateOverDistance)
|
||||
{
|
||||
// (For rate-over-distance emission,) Move to previous scaled position, simulate (delta = 0).
|
||||
var prevScaledPos = isLocalSpace
|
||||
? _prevPsPos
|
||||
: _prevPsPos.GetScaled(_prevScale.Inverse());
|
||||
Vector3 prevScaledPos = _prevPsPos.GetScaled(_prevScale.Inverse());
|
||||
psTransform.SetPositionAndRotation(prevScaledPos, originWorldRotation);
|
||||
_particleSystem.Simulate(0, false, false, false);
|
||||
}
|
||||
|
||||
// Move to scaled position, simulate, revert to origin position.
|
||||
var scaledPos = isLocalSpace
|
||||
? originWorldPosition
|
||||
: originWorldPosition.GetScaled(scale.Inverse());
|
||||
var scaledPos = originWorldPosition.GetScaled(scale.Inverse());
|
||||
psTransform.SetPositionAndRotation(scaledPos, originWorldRotation);
|
||||
_particleSystem.Simulate(deltaTime, false, false, false);
|
||||
psTransform.SetPositionAndRotation(originWorldPosition, originWorldRotation);
|
||||
|
@ -614,8 +549,7 @@ namespace Coffee.UIExtensions
|
|||
private void SimulateForEditor(Vector3 diffPos, Vector3 scale)
|
||||
{
|
||||
// Extra world simulation.
|
||||
var isWorldSpace = _particleSystem.IsWorldSpace();
|
||||
if (isWorldSpace && 0 < Vector3.SqrMagnitude(diffPos))
|
||||
if (_particleSystem.main.simulationSpace == ParticleSystemSimulationSpace.World && 0 < Vector3.SqrMagnitude(diffPos))
|
||||
{
|
||||
Profiler.BeginSample("[UIParticle] Bake Mesh > Extra world simulation");
|
||||
diffPos.x *= 1f - 1f / Mathf.Max(0.001f, scale.x);
|
||||
|
@ -643,9 +577,7 @@ namespace Coffee.UIExtensions
|
|||
if (_parent.m_AnimatableProperties.Length == 0) return;
|
||||
|
||||
if (s_Mpb == null)
|
||||
{
|
||||
s_Mpb = new MaterialPropertyBlock();
|
||||
}
|
||||
|
||||
_renderer.GetPropertyBlock(s_Mpb);
|
||||
if (s_Mpb.isEmpty) return;
|
||||
|
@ -653,9 +585,8 @@ namespace Coffee.UIExtensions
|
|||
// #41: Copy the value from MaterialPropertyBlock to CanvasRenderer
|
||||
if (!_modifiedMaterial) return;
|
||||
|
||||
for (var i = 0; i < _parent.m_AnimatableProperties.Length; i++)
|
||||
foreach (var ap in _parent.m_AnimatableProperties)
|
||||
{
|
||||
var ap = _parent.m_AnimatableProperties[i];
|
||||
ap.UpdateMaterialProperties(_modifiedMaterial, s_Mpb);
|
||||
}
|
||||
|
||||
|
|
|
@ -1,19 +1,21 @@
|
|||
using System.Collections.Generic;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Coffee.UIExtensions
|
||||
{
|
||||
internal static class UIParticleUpdater
|
||||
{
|
||||
private static readonly List<UIParticle> s_ActiveParticles = new List<UIParticle>();
|
||||
private static readonly List<UIParticleAttractor> s_ActiveAttractors = new List<UIParticleAttractor>();
|
||||
private static readonly HashSet<int> s_UpdatedGroupIds = new HashSet<int>();
|
||||
private static int s_FrameCount;
|
||||
static readonly List<UIParticle> s_ActiveParticles = new List<UIParticle>();
|
||||
static readonly List<UIParticleAttractor> s_ActiveAttractors = new List<UIParticleAttractor>();
|
||||
static readonly HashSet<int> s_UpdatedGroupIds = new HashSet<int>();
|
||||
private static int frameCount = 0;
|
||||
|
||||
public static int uiParticleCount
|
||||
{
|
||||
get { return s_ActiveParticles.Count; }
|
||||
get
|
||||
{
|
||||
return s_ActiveParticles.Count;
|
||||
}
|
||||
}
|
||||
|
||||
public static void Register(UIParticle particle)
|
||||
|
@ -41,7 +43,7 @@ namespace Coffee.UIExtensions
|
|||
}
|
||||
|
||||
#if UNITY_EDITOR
|
||||
[InitializeOnLoadMethod]
|
||||
[UnityEditor.InitializeOnLoadMethod]
|
||||
#endif
|
||||
[RuntimeInitializeOnLoadMethod]
|
||||
private static void InitializeOnLoad()
|
||||
|
@ -53,8 +55,8 @@ namespace Coffee.UIExtensions
|
|||
private static void Refresh()
|
||||
{
|
||||
// Do not allow it to be called in the same frame.
|
||||
if (s_FrameCount == Time.frameCount) return;
|
||||
s_FrameCount = Time.frameCount;
|
||||
if (frameCount == Time.frameCount) return;
|
||||
frameCount = Time.frameCount;
|
||||
|
||||
// Simulate -> Primary
|
||||
for (var i = 0; i < s_ActiveParticles.Count; i++)
|
||||
|
@ -127,7 +129,6 @@ namespace Coffee.UIExtensions
|
|||
if (uip.isPrimary) return uip;
|
||||
if (!primary && uip.canSimulate) primary = uip;
|
||||
}
|
||||
|
||||
return primary;
|
||||
}
|
||||
}
|
||||
|
|
104
Scripts/Utils.cs
104
Scripts/Utils.cs
|
@ -46,11 +46,11 @@ namespace Coffee.UIParticleExtensions
|
|||
internal static class SpriteExtensions
|
||||
{
|
||||
#if UNITY_EDITOR
|
||||
private static readonly Type s_SpriteEditorExtensionType =
|
||||
private static Type tSpriteEditorExtension =
|
||||
Type.GetType("UnityEditor.Experimental.U2D.SpriteEditorExtension, UnityEditor")
|
||||
?? Type.GetType("UnityEditor.U2D.SpriteEditorExtension, UnityEditor");
|
||||
|
||||
private static readonly MethodInfo s_GetActiveAtlasTextureMethodInfo = s_SpriteEditorExtensionType
|
||||
private static MethodInfo miGetActiveAtlasTexture = tSpriteEditorExtension
|
||||
.GetMethod("GetActiveAtlasTexture", BindingFlags.Static | BindingFlags.NonPublic);
|
||||
|
||||
public static Texture2D GetActualTexture(this Sprite self)
|
||||
|
@ -58,10 +58,8 @@ namespace Coffee.UIParticleExtensions
|
|||
if (!self) return null;
|
||||
|
||||
if (Application.isPlaying) return self.texture;
|
||||
var ret = s_GetActiveAtlasTextureMethodInfo.Invoke(null, new object[] { self }) as Texture2D;
|
||||
return ret
|
||||
? ret
|
||||
: self.texture;
|
||||
var ret = miGetActiveAtlasTexture.Invoke(null, new[] { self }) as Texture2D;
|
||||
return ret ? ret : self.texture;
|
||||
}
|
||||
#else
|
||||
internal static Texture2D GetActualTexture(this Sprite self)
|
||||
|
@ -79,14 +77,12 @@ namespace Coffee.UIParticleExtensions
|
|||
{
|
||||
if (s_TmpParticles.Length < size)
|
||||
{
|
||||
while (s_TmpParticles.Length < size)
|
||||
while(s_TmpParticles.Length < size)
|
||||
{
|
||||
size = Mathf.NextPowerOfTwo(size);
|
||||
}
|
||||
|
||||
s_TmpParticles = new ParticleSystem.Particle[size];
|
||||
}
|
||||
|
||||
return s_TmpParticles;
|
||||
}
|
||||
|
||||
|
@ -106,69 +102,47 @@ namespace Coffee.UIParticleExtensions
|
|||
var main = self.main;
|
||||
var space = main.simulationSpace;
|
||||
if (space == ParticleSystemSimulationSpace.Custom && !main.customSimulationSpace)
|
||||
{
|
||||
space = ParticleSystemSimulationSpace.Local;
|
||||
}
|
||||
|
||||
return space;
|
||||
}
|
||||
|
||||
public static bool IsLocalSpace(this ParticleSystem self)
|
||||
{
|
||||
return GetActualSimulationSpace(self) == ParticleSystemSimulationSpace.Local;
|
||||
}
|
||||
|
||||
public static bool IsWorldSpace(this ParticleSystem self)
|
||||
{
|
||||
return GetActualSimulationSpace(self) == ParticleSystemSimulationSpace.World;
|
||||
}
|
||||
|
||||
public static void SortForRendering(this List<ParticleSystem> self, Transform transform, bool sortByMaterial)
|
||||
{
|
||||
self.Sort((a, b) =>
|
||||
{
|
||||
var tr = transform;
|
||||
var aRenderer = a.GetComponent<ParticleSystemRenderer>();
|
||||
var bRenderer = b.GetComponent<ParticleSystemRenderer>();
|
||||
|
||||
// Render queue: ascending
|
||||
var aMat = aRenderer.sharedMaterial ? aRenderer.sharedMaterial : aRenderer.trailMaterial;
|
||||
var bMat = bRenderer.sharedMaterial ? bRenderer.sharedMaterial : bRenderer.trailMaterial;
|
||||
var aMat = aRenderer.sharedMaterial ?? aRenderer.trailMaterial;
|
||||
var bMat = bRenderer.sharedMaterial ?? bRenderer.trailMaterial;
|
||||
if (!aMat && !bMat) return 0;
|
||||
if (!aMat) return -1;
|
||||
if (!bMat) return 1;
|
||||
|
||||
if (sortByMaterial)
|
||||
{
|
||||
return aMat.GetInstanceID() - bMat.GetInstanceID();
|
||||
}
|
||||
|
||||
if (aMat.renderQueue != bMat.renderQueue)
|
||||
{
|
||||
return aMat.renderQueue - bMat.renderQueue;
|
||||
}
|
||||
|
||||
// Sorting layer: ascending
|
||||
if (aRenderer.sortingLayerID != bRenderer.sortingLayerID)
|
||||
{
|
||||
return SortingLayer.GetLayerValueFromID(aRenderer.sortingLayerID) -
|
||||
SortingLayer.GetLayerValueFromID(bRenderer.sortingLayerID);
|
||||
}
|
||||
return SortingLayer.GetLayerValueFromID(aRenderer.sortingLayerID) - SortingLayer.GetLayerValueFromID(bRenderer.sortingLayerID);
|
||||
|
||||
// Sorting order: ascending
|
||||
if (aRenderer.sortingOrder != bRenderer.sortingOrder)
|
||||
{
|
||||
return aRenderer.sortingOrder - bRenderer.sortingOrder;
|
||||
}
|
||||
|
||||
// Z position & sortingFudge: descending
|
||||
var aTransform = a.transform;
|
||||
var bTransform = b.transform;
|
||||
var aPos = transform.InverseTransformPoint(aTransform.position).z + aRenderer.sortingFudge;
|
||||
var bPos = transform.InverseTransformPoint(bTransform.position).z + bRenderer.sortingFudge;
|
||||
var aPos = tr.InverseTransformPoint(aTransform.position).z + aRenderer.sortingFudge;
|
||||
var bPos = tr.InverseTransformPoint(bTransform.position).z + bRenderer.sortingFudge;
|
||||
if (!Mathf.Approximately(aPos, bPos))
|
||||
{
|
||||
return (int)Mathf.Sign(bPos - aPos);
|
||||
}
|
||||
|
||||
return (int)Mathf.Sign(GetIndex(self, a) - GetIndex(self, b));
|
||||
});
|
||||
|
@ -178,10 +152,7 @@ namespace Coffee.UIParticleExtensions
|
|||
{
|
||||
for (var i = 0; i < list.Count; i++)
|
||||
{
|
||||
if (list[i].GetInstanceID() == ps.GetInstanceID())
|
||||
{
|
||||
return i;
|
||||
}
|
||||
if (list[i].GetInstanceID() == ps.GetInstanceID()) return i;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
@ -212,55 +183,4 @@ namespace Coffee.UIParticleExtensions
|
|||
self.ForEach(action);
|
||||
}
|
||||
}
|
||||
|
||||
internal static class Misc
|
||||
{
|
||||
public static void Destroy(Object obj)
|
||||
{
|
||||
if (!obj) return;
|
||||
#if UNITY_EDITOR
|
||||
if (!Application.isPlaying)
|
||||
{
|
||||
Object.DestroyImmediate(obj);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
Object.Destroy(obj);
|
||||
}
|
||||
}
|
||||
|
||||
public static void DestroyImmediate(Object obj)
|
||||
{
|
||||
if (!obj) return;
|
||||
#if UNITY_EDITOR
|
||||
if (Application.isEditor)
|
||||
{
|
||||
Object.DestroyImmediate(obj);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
Object.Destroy(obj);
|
||||
}
|
||||
}
|
||||
|
||||
#if !UNITY_2021_2_OR_NEWER || UNITY_2020_3_45 || UNITY_2020_3_46 || UNITY_2020_3_47 || UNITY_2020_3_48
|
||||
public static T GetComponentInParent<T>(this Component self, bool includeInactive) where T : Component
|
||||
{
|
||||
if (!self) return null;
|
||||
if (!includeInactive) return self.GetComponentInParent<T>();
|
||||
|
||||
var current = self.transform;
|
||||
while (current)
|
||||
{
|
||||
var component = current.GetComponent<T>();
|
||||
if (component) return component;
|
||||
current = current.parent;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,85 +0,0 @@
|
|||
%YAML 1.1
|
||||
%TAG !u! tag:unity3d.com,2011:
|
||||
--- !u!21 &2100000
|
||||
Material:
|
||||
serializedVersion: 6
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_Name: UIAdditive
|
||||
m_Shader: {fileID: 4800000, guid: ecfa8f5732b504ef98fba10aa18d0326, type: 3}
|
||||
m_ShaderKeywords:
|
||||
m_LightmapFlags: 4
|
||||
m_EnableInstancingVariants: 0
|
||||
m_DoubleSidedGI: 0
|
||||
m_CustomRenderQueue: -1
|
||||
stringTagMap: {}
|
||||
disabledShaderPasses: []
|
||||
m_SavedProperties:
|
||||
serializedVersion: 3
|
||||
m_TexEnvs:
|
||||
- _BumpMap:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- _DetailAlbedoMap:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- _DetailMask:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- _DetailNormalMap:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- _EmissionMap:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- _MainTex:
|
||||
m_Texture: {fileID: 10300, guid: 0000000000000000f000000000000000, type: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- _MetallicGlossMap:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- _OcclusionMap:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- _ParallaxMap:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
m_Floats:
|
||||
- _BumpScale: 1
|
||||
- _ColorMask: 15
|
||||
- _Cutoff: 0.5
|
||||
- _DetailNormalMapScale: 1
|
||||
- _DstBlend: 0
|
||||
- _GlossMapScale: 1
|
||||
- _Glossiness: 0.5
|
||||
- _GlossyReflections: 1
|
||||
- _Metallic: 0
|
||||
- _Mode: 0
|
||||
- _OcclusionStrength: 1
|
||||
- _Parallax: 0.02
|
||||
- _SmoothnessTextureChannel: 0
|
||||
- _SpecularHighlights: 1
|
||||
- _SrcBlend: 1
|
||||
- _Stencil: 0
|
||||
- _StencilComp: 8
|
||||
- _StencilOp: 0
|
||||
- _StencilReadMask: 255
|
||||
- _StencilWriteMask: 255
|
||||
- _UVSec: 0
|
||||
- _UseUIAlphaClip: 0
|
||||
- _ZWrite: 1
|
||||
m_Colors:
|
||||
- _Color: {r: 1, g: 1, b: 1, a: 1}
|
||||
- _EmissionColor: {r: 0, g: 0, b: 0, a: 1}
|
||||
m_BuildTextureStacks: []
|
|
@ -1,8 +0,0 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 9944483a3e009401ba5dcc42f14d5c63
|
||||
NativeFormatImporter:
|
||||
externalObjects: {}
|
||||
mainObjectFileID: 2100000
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -2,7 +2,7 @@
|
|||
"name": "com.coffee.ui-particle",
|
||||
"displayName": "UI Particle",
|
||||
"description": "This plugin provide a component to render particle effect for uGUI.\nThe particle rendering is maskable and sortable, without Camera, RenderTexture or Canvas.",
|
||||
"version": "4.2.1",
|
||||
"version": "4.1.7",
|
||||
"unity": "2018.2",
|
||||
"license": "MIT",
|
||||
"repository": {
|
||||
|
|
Loading…
Reference in New Issue