Compare commits
21 Commits
67bac3b50d
...
f1d12c3b04
Author | SHA1 | Date |
---|---|---|
|
f1d12c3b04 | |
|
db28f171f7 | |
|
410304125f | |
|
67eff61073 | |
|
4851a1880e | |
|
2fe0bde422 | |
|
c2119c171a | |
|
3df190382a | |
|
35325c8899 | |
|
903f702d7b | |
|
e93051603e | |
|
e4998365c9 | |
|
68d9925a16 | |
|
392ab6dd76 | |
|
f75fcce0da | |
|
fb31db47f2 | |
|
425aad0cba | |
|
8b4ca1add5 | |
|
b308b26833 | |
|
e67e9482e2 | |
|
723a04d0cf |
|
@ -10,26 +10,39 @@ assignees: mob-sakai
|
||||||
NOTE: Your issue may already be reported! Please search on the [issue tracker](../) before creating one.
|
NOTE: Your issue may already be reported! Please search on the [issue tracker](../) before creating one.
|
||||||
|
|
||||||
**Describe the bug**
|
**Describe the bug**
|
||||||
|
|
||||||
A clear and concise description of what the bug is.
|
A clear and concise description of what the bug is.
|
||||||
|
|
||||||
**To Reproduce**
|
**To Reproduce**
|
||||||
|
|
||||||
Steps to reproduce the behavior:
|
Steps to reproduce the behavior:
|
||||||
|
|
||||||
1. Go to '...'
|
1. Go to '...'
|
||||||
2. Click on '....'
|
2. Click on '....'
|
||||||
3. Scroll down to '....'
|
3. Scroll down to '....'
|
||||||
4. See error
|
4. See error
|
||||||
|
|
||||||
**Expected behavior**
|
**Expected behavior**
|
||||||
|
|
||||||
A clear and concise description of what you expected to happen.
|
A clear and concise description of what you expected to happen.
|
||||||
|
|
||||||
**Screenshots**
|
**Screenshots**
|
||||||
|
|
||||||
If applicable, add screenshots to help explain your problem.
|
If applicable, add screenshots to help explain your problem.
|
||||||
|
|
||||||
**Environment (please complete the following information):**
|
**Environment (please complete the following)**
|
||||||
- Version [e.g. 1.0.0]
|
|
||||||
- Platform: [e.g. Editor(Windows/Mac), Standalone(Windows/Mac), iOS, Android, WebGL]
|
- Package version [e.g. 4.2.0, 3.3.14]
|
||||||
- Unity version: [e.g. 2018.2.8f1]
|
- Platform: [e.g. Editor(Windows/Mac), Standalone(Windows/Mac), iOS, Android, WebGL]
|
||||||
- Build options: [e.g. IL2CPP, .Net 4.x, LWRP]
|
- Unity version: [e.g. 2021.3.7f1]
|
||||||
|
- Project options: [e.g. Mono/IL2CPP, .Net Standard 2.1/.Net 4.x, URP/HDRP, GraphicAPIs]
|
||||||
|
|
||||||
**Additional context**
|
**Additional context**
|
||||||
Add any other context about the problem here.
|
|
||||||
|
Please add any other context about the issue here.
|
||||||
|
It will help us resolve the issue.
|
||||||
|
|
||||||
|
- Error messages and crash dump
|
||||||
|
- Screenshots, gif animations and movie files
|
||||||
|
- Reproducible minimal project
|
||||||
|
- The entire project (zipped Assets, Packages, ProjectSettings) is preferred over `.unitypackage`
|
||||||
|
|
|
@ -10,13 +10,17 @@ assignees: mob-sakai
|
||||||
NOTE: Your issue may already be reported! Please search on the [issue tracker](../) before creating one.
|
NOTE: Your issue may already be reported! Please search on the [issue tracker](../) before creating one.
|
||||||
|
|
||||||
**Is your feature request related to a problem? Please describe.**
|
**Is your feature request related to a problem? Please describe.**
|
||||||
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
|
|
||||||
|
A clear and concise description of what the issue is. (e.g. I'm always frustrated when [...])
|
||||||
|
|
||||||
**Describe the solution you'd like**
|
**Describe the solution you'd like**
|
||||||
|
|
||||||
A clear and concise description of what you want to happen.
|
A clear and concise description of what you want to happen.
|
||||||
|
|
||||||
**Describe alternatives you've considered**
|
**Describe alternatives you've considered**
|
||||||
|
|
||||||
A clear and concise description of any alternative solutions or features you've considered.
|
A clear and concise description of any alternative solutions or features you've considered.
|
||||||
|
|
||||||
**Additional context**
|
**Additional context**
|
||||||
|
|
||||||
Add any other context or screenshots about the feature request here.
|
Add any other context or screenshots about the feature request here.
|
||||||
|
|
|
@ -81,4 +81,4 @@ Community Impact Guidelines were inspired by [Mozilla's code of conduct enforcem
|
||||||
[homepage]: https://www.contributor-covenant.org
|
[homepage]: https://www.contributor-covenant.org
|
||||||
|
|
||||||
For answers to common questions about this code of conduct, see the FAQ at
|
For answers to common questions about this code of conduct, see the FAQ at
|
||||||
https://www.contributor-covenant.org/faq. Translations are available at https://www.contributor-covenant.org/translations.
|
https://www.contributor-covenant.org/faq. Translations are available at https://www.contributor-covenant.org/translations.
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
Copyright 2018-2022 mob-sakai
|
Copyright 2018-2023 mob-sakai
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
|
92
README.md
92
README.md
|
@ -2,16 +2,14 @@ Particle Effect For UGUI (UI Particle)
|
||||||
===
|
===
|
||||||
|
|
||||||
This plugin provide a component to render particle effect for uGUI in Unity 2018.2 or later.
|
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.
|
The particle rendering is maskable and sortable, without Camera, RenderTexture or Canvas.
|
||||||
|
|
||||||
|

|
||||||
[](https://openupm.com/packages/com.coffee.ui-particle/)
|
[](https://openupm.com/packages/com.coffee.ui-particle/)
|
||||||
[](https://github.com/mob-sakai/ParticleEffectForUGUI/releases)
|
[](https://github.com/mob-sakai/ParticleEffectForUGUI/releases)
|
||||||
|
[)](https://github.com/mob-sakai/ParticleEffectForUGUI/releases)
|
||||||
[](https://github.com/mob-sakai/ParticleEffectForUGUI/releases) [](https://github.com/mob-sakai/ParticleEffectForUGUI/blob/master/LICENSE.txt)
|
[](https://github.com/mob-sakai/ParticleEffectForUGUI/releases) [](https://github.com/mob-sakai/ParticleEffectForUGUI/blob/master/LICENSE.txt)
|
||||||
[](http://makeapullrequest.com)
|
[](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) >>
|
<< [Description](#Description) | [Demo](#demo) | [Installation](#installation) | [Usage](#usage) | [Development Note](#development-note) | [Change log](https://github.com/mob-sakai/ParticleEffectForUGUI/blob/upm/CHANGELOG.md) >>
|
||||||
|
@ -58,6 +56,8 @@ Compares this "Baking mesh" approach with the conventional approach:
|
||||||
* Support CanvasGroup alpha
|
* Support CanvasGroup alpha
|
||||||
* No allocations
|
* No allocations
|
||||||
* Support overlay, camera space and world space
|
* 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)
|
* Support changing material property with AnimationClip (AnimatableProperty)
|
||||||

|

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

|
Unity 2018.2 or later
|
||||||

|
|
||||||

|
|
||||||

|
|
||||||
|
|
||||||
### Using OpenUPM
|
### Install via OpenUPM
|
||||||
|
|
||||||
This package is available on [OpenUPM](https://openupm.com).
|
This package is available on [OpenUPM](https://openupm.com).
|
||||||
You can install it via [openupm-cli](https://github.com/openupm/openupm-cli).
|
It's recommended to install it via [openupm-cli](https://github.com/openupm/openupm-cli).
|
||||||
```
|
```
|
||||||
openupm add com.coffee.ui-particle
|
openupm add com.coffee.ui-particle
|
||||||
```
|
```
|
||||||
|
|
||||||
### Using Git
|
### Install via Package Manager Window (using Git URL)
|
||||||
|
|
||||||
Find the manifest.json file in the Packages folder of your project and add a line to `dependencies` field.
|
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`
|
||||||
|

|
||||||
|
|
||||||
* `"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.
|
Or, use [UpmGitExtension](https://github.com/mob-sakai/UpmGitExtension) to install and update the package.
|
||||||
|
|
||||||
### For Unity 2018.2
|
### Install via manifest.json (using Git URL)
|
||||||
|
|
||||||
Unity 2018.2 supports embedded packages.
|
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
|
||||||
|
|
||||||
1. Download a source code zip file from [Releases](https://github.com/mob-sakai/ParticleEffectForUGUI/releases) page
|
1. Download a source code zip file from [Releases](https://github.com/mob-sakai/ParticleEffectForUGUI/releases) page
|
||||||
2. Extract it
|
2. Extract it and place it under `Packages` directory in your project.
|
||||||
3. Import it under `Packages` directory in your Unity project
|

|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<br><br><br><br>
|
<br><br><br><br>
|
||||||
|
@ -161,17 +163,17 @@ Unity 2018.2 supports embedded packages.
|
||||||
|
|
||||||
`UIParticle` controls the ParticleSystems that is attached to its own game objects and child game objects.
|
`UIParticle` controls the ParticleSystems that is attached to its own game objects and child game objects.
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
| Properties | Description |
|
| Properties | Description |
|
||||||
| -- | -- |
|
| -- | -- |
|
||||||
| Maskable | Does this graphic allow masking. |
|
| 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. |
|
| 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. |
|
| 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. |
|
| 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. |
|
||||||
| Absolute Mode | The particles will be emitted at the ParticleSystem position.<br>Move the UIParticle/ParticleSystem to move the particle. |
|
| Position Mode | **Absolute:** Emit from the world position of the `ParticleSystem`.<br>**Relative:** Emit from the scaled position of the `ParticleSystem`. |
|
||||||
| Rendering Order | The ParticleSystems to be rendered.<br>You can change the rendering order and the materials. |
|
| Auto Scaling | Transform.lossyScale (=world scale) will be set to `(1, 1, 1)` on update.<br>It prevents the root-Canvas scale from affecting the hierarchy-scaled `ParticleSystem`. |
|
||||||
|
| Rendering Order | The ParticleSystem list to be rendered.<br>You can change the order and the materials. |
|
||||||
|
|
||||||
NOTE: Press `Refresh` button to reconstruct rendering order based on children ParticleSystem's sorting order and z position.
|
NOTE: Press `Refresh` button to reconstruct rendering order based on children ParticleSystem's sorting order and z position.
|
||||||
|
|
||||||
|
@ -227,7 +229,7 @@ uiParticle.Stop();
|
||||||
|
|
||||||
`UIParticleAttractor` attracts particles generated by the specified ParticleSystem.
|
`UIParticleAttractor` attracts particles generated by the specified ParticleSystem.
|
||||||
|
|
||||||

|

|
||||||

|

|
||||||
|
|
||||||
| Properties | Description |
|
| Properties | Description |
|
||||||
|
@ -237,6 +239,7 @@ uiParticle.Stop();
|
||||||
| Delay Rate | Delay to start attracting.<br>It is a percentage of the particle's start lifetime. |
|
| Delay Rate | Delay to start attracting.<br>It is a percentage of the particle's start lifetime. |
|
||||||
| Max Speed | Maximum speed of attracting.<br> If this value is too small, attracting may not be completed by the end of the lifetime and `OnAttracted` may not be called. |
|
| 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) |
|
| 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). |
|
| OnAttracted | An event called when attracting is complete (per particle). |
|
||||||
|
|
||||||
<br><br><br><br>
|
<br><br><br><br>
|
||||||
|
@ -245,14 +248,31 @@ uiParticle.Stop();
|
||||||
|
|
||||||
### Shader Limitation
|
### Shader Limitation
|
||||||
|
|
||||||
UIParticles are based on UIVertex.
|
The use of UI shaders is recommended.
|
||||||
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.
|
|
||||||
When using custom vertex streams, you can fill zw components with "unnecessary" data.
|
|
||||||
https://github.com/mob-sakai/ParticleEffectForUGUI/issues/191
|
|
||||||
|
|
||||||
- If you need a simple Additive shader, use the `UI/Additive` shader instead.
|
- 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 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).
|
||||||
|
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>
|
||||||
|
|
||||||
### Overheads
|
### Overheads
|
||||||
|
|
||||||
|
|
|
@ -1,85 +1,87 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using Coffee.UIExtensions;
|
|
||||||
using UnityEditor;
|
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
using UnityEngine.SceneManagement;
|
using UnityEngine.SceneManagement;
|
||||||
using UnityEngine.UI;
|
using UnityEngine.UI;
|
||||||
using Object = UnityEngine.Object;
|
using Object = UnityEngine.Object;
|
||||||
|
|
||||||
public class CFX_Demo_With_UIParticle : MonoBehaviour
|
namespace Coffee.UIExtensions.Demo
|
||||||
{
|
{
|
||||||
private UIParticle UiParticle;
|
public class CFX_Demo_With_UIParticle : MonoBehaviour
|
||||||
private Toggle spawnOnUI;
|
|
||||||
private MonoBehaviour demo;
|
|
||||||
|
|
||||||
// Start is called before the first frame update
|
|
||||||
private void Start()
|
|
||||||
{
|
{
|
||||||
UiParticle = GetComponentInChildren<UIParticle>();
|
private MonoBehaviour _demo;
|
||||||
spawnOnUI = GetComponentInChildren<Toggle>();
|
private Toggle _spawnOnUI;
|
||||||
|
private UIParticle _uiParticle;
|
||||||
|
|
||||||
demo = FindObjectOfType("CFX_Demo_New") as MonoBehaviour
|
// Start is called before the first frame update
|
||||||
?? FindObjectOfType("WFX_Demo_New") as MonoBehaviour;
|
private void Start()
|
||||||
|
|
||||||
SetCanvasWidth(800);
|
|
||||||
SetCanvasRenderOverlay(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
private Object FindObjectOfType(string typeName)
|
|
||||||
{
|
|
||||||
var type = AppDomain.CurrentDomain.GetAssemblies()
|
|
||||||
.SelectMany(x => x.GetTypes())
|
|
||||||
.FirstOrDefault(x => x.Name == typeName);
|
|
||||||
|
|
||||||
return type == null ? null : FindObjectOfType(type);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Update is called once per frame
|
|
||||||
private void Update()
|
|
||||||
{
|
|
||||||
if (!spawnOnUI.isOn || !demo || !Input.GetMouseButtonDown(0)) return;
|
|
||||||
|
|
||||||
foreach (Transform child in UiParticle.transform)
|
|
||||||
{
|
{
|
||||||
Destroy(child.gameObject);
|
_uiParticle = GetComponentInChildren<UIParticle>();
|
||||||
|
_spawnOnUI = GetComponentInChildren<Toggle>();
|
||||||
|
_demo = FindObjectOfType("CFX_Demo_New") as MonoBehaviour
|
||||||
|
?? FindObjectOfType("WFX_Demo_New") as MonoBehaviour;
|
||||||
|
|
||||||
|
SetCanvasWidth(800);
|
||||||
|
SetCanvasRenderOverlay(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
var particle = demo.GetType()
|
// Update is called once per frame
|
||||||
.GetMethod("spawnParticle", BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public)
|
private void Update()
|
||||||
.Invoke(demo, new object[0]) as GameObject;
|
|
||||||
particle.transform.localScale = Vector3.one;
|
|
||||||
UiParticle.SetParticleSystemInstance(particle);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void SetCanvasWidth(int width)
|
|
||||||
{
|
|
||||||
var scaler = GetComponentInParent<CanvasScaler>();
|
|
||||||
scaler.screenMatchMode = CanvasScaler.ScreenMatchMode.MatchWidthOrHeight;
|
|
||||||
scaler.matchWidthOrHeight = 0;
|
|
||||||
var resolution = scaler.referenceResolution;
|
|
||||||
resolution.x = width;
|
|
||||||
scaler.referenceResolution = resolution;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void SetCanvasRenderOverlay(bool enable)
|
|
||||||
{
|
|
||||||
var canvas = GetComponentInParent<Canvas>();
|
|
||||||
if (enable)
|
|
||||||
{
|
{
|
||||||
canvas.renderMode = RenderMode.ScreenSpaceOverlay;
|
if (!_spawnOnUI.isOn || !_demo || !Input.GetMouseButtonDown(0)) return;
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
canvas.worldCamera = Camera.main;
|
|
||||||
canvas.renderMode = RenderMode.ScreenSpaceCamera;
|
|
||||||
canvas.planeDistance = 5;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void LoadScene(string scene)
|
foreach (Transform child in _uiParticle.transform)
|
||||||
{
|
{
|
||||||
SceneManager.LoadScene(scene);
|
Destroy(child.gameObject);
|
||||||
|
}
|
||||||
|
|
||||||
|
var particle = _demo.GetType()
|
||||||
|
.GetMethod("spawnParticle", BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public)
|
||||||
|
?.Invoke(_demo, Array.Empty<object>()) as GameObject;
|
||||||
|
if (!particle) return;
|
||||||
|
|
||||||
|
particle.transform.localScale = Vector3.one;
|
||||||
|
_uiParticle.SetParticleSystemInstance(particle);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Object FindObjectOfType(string typeName)
|
||||||
|
{
|
||||||
|
var type = AppDomain.CurrentDomain.GetAssemblies()
|
||||||
|
.SelectMany(x => x.GetTypes())
|
||||||
|
.FirstOrDefault(x => x.Name == typeName);
|
||||||
|
|
||||||
|
return type == null ? null : FindObjectOfType(type);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SetCanvasWidth(int width)
|
||||||
|
{
|
||||||
|
var scaler = GetComponentInParent<CanvasScaler>();
|
||||||
|
scaler.screenMatchMode = CanvasScaler.ScreenMatchMode.MatchWidthOrHeight;
|
||||||
|
scaler.matchWidthOrHeight = 0;
|
||||||
|
var resolution = scaler.referenceResolution;
|
||||||
|
resolution.x = width;
|
||||||
|
scaler.referenceResolution = resolution;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SetCanvasRenderOverlay(bool enable)
|
||||||
|
{
|
||||||
|
var canvas = GetComponentInParent<Canvas>();
|
||||||
|
if (enable)
|
||||||
|
{
|
||||||
|
canvas.renderMode = RenderMode.ScreenSpaceOverlay;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
canvas.worldCamera = Camera.main;
|
||||||
|
canvas.renderMode = RenderMode.ScreenSpaceCamera;
|
||||||
|
canvas.planeDistance = 5;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void LoadScene(string scene)
|
||||||
|
{
|
||||||
|
SceneManager.LoadScene(scene);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
Cartoon FX & War FX Demo
|
Cartoon FX & War FX Demo
|
||||||
===
|
===
|
||||||
|
|
||||||
Please import assets "Cartoon FX Free" and/or "War FX Free" from Unity asset store.
|
Please import assets "Cartoon FX Free" and/or "War FX Free" from Unity asset store.
|
||||||
|
|
|
@ -1,25 +1,31 @@
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
|
using UnityEngine.Serialization;
|
||||||
|
|
||||||
namespace Coffee.UIExtensions.Demo
|
namespace Coffee.UIExtensions.Demo
|
||||||
{
|
{
|
||||||
public class CopyItemOnStart : MonoBehaviour
|
public class CopyItemOnStart : MonoBehaviour
|
||||||
{
|
{
|
||||||
public GameObject origin;
|
[FormerlySerializedAs("origin")]
|
||||||
public int count;
|
[SerializeField]
|
||||||
|
private GameObject m_Origin;
|
||||||
|
|
||||||
|
[FormerlySerializedAs("count")]
|
||||||
|
[SerializeField]
|
||||||
|
private int m_Count;
|
||||||
|
|
||||||
private void Start()
|
private void Start()
|
||||||
{
|
{
|
||||||
if (!origin) return;
|
if (!m_Origin) return;
|
||||||
origin.SetActive(false);
|
m_Origin.SetActive(false);
|
||||||
|
|
||||||
var parent = origin.transform.parent;
|
var parent = m_Origin.transform.parent;
|
||||||
for (var i = 0; i < count; i++)
|
for (var i = 0; i < m_Count; i++)
|
||||||
{
|
{
|
||||||
var go = Instantiate(origin, parent, false);
|
var go = Instantiate(m_Origin, parent, false);
|
||||||
go.name = string.Format("{0} {1}", origin.name, i + 1);
|
go.name = $"{m_Origin.name} {i + 1}";
|
||||||
go.hideFlags = HideFlags.DontSave;
|
go.hideFlags = HideFlags.DontSave;
|
||||||
go.SetActive(true);
|
go.SetActive(true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,25 +1,31 @@
|
||||||
using UnityEngine;
|
using System;
|
||||||
|
using UnityEngine;
|
||||||
using UnityEngine.EventSystems;
|
using UnityEngine.EventSystems;
|
||||||
|
using UnityEngine.Serialization;
|
||||||
|
|
||||||
public class UIElementDragger : MonoBehaviour, IBeginDragHandler, IDragHandler, IEndDragHandler
|
public class UIElementDragger : MonoBehaviour, IBeginDragHandler, IDragHandler, IEndDragHandler
|
||||||
{
|
{
|
||||||
public enum Target
|
[SerializeField]
|
||||||
{
|
private Target m_Target;
|
||||||
Self,
|
|
||||||
Parent,
|
|
||||||
Custom,
|
|
||||||
}
|
|
||||||
|
|
||||||
private RectTransform rectTransform;
|
[SerializeField]
|
||||||
private Canvas canvas;
|
private Transform m_CustomTarget;
|
||||||
public Target m_Target;
|
|
||||||
public Transform m_CustomTarget;
|
[FormerlySerializedAs("ex2")]
|
||||||
public bool ex2;
|
[SerializeField]
|
||||||
|
private bool m_UseCanvasScale;
|
||||||
|
|
||||||
|
private Canvas _canvas;
|
||||||
|
private RectTransform _rectTransform;
|
||||||
|
|
||||||
private void OnEnable()
|
private void OnEnable()
|
||||||
{
|
{
|
||||||
rectTransform = GetComponent<RectTransform>();
|
_rectTransform = GetComponent<RectTransform>();
|
||||||
canvas = GetComponentInParent<Canvas>();
|
_canvas = GetComponentInParent<Canvas>();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void OnBeginDrag(PointerEventData eventData)
|
||||||
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
public void OnDrag(PointerEventData eventData)
|
public void OnDrag(PointerEventData eventData)
|
||||||
|
@ -29,57 +35,59 @@ public class UIElementDragger : MonoBehaviour, IBeginDragHandler, IDragHandler,
|
||||||
switch (m_Target)
|
switch (m_Target)
|
||||||
{
|
{
|
||||||
case Target.Self:
|
case Target.Self:
|
||||||
rectTransform.localPosition += delta;
|
_rectTransform.localPosition += delta;
|
||||||
break;
|
break;
|
||||||
case Target.Parent:
|
case Target.Parent:
|
||||||
rectTransform.parent.localPosition += delta;
|
_rectTransform.parent.localPosition += delta;
|
||||||
break;
|
break;
|
||||||
case Target.Custom:
|
case Target.Custom:
|
||||||
rectTransform.localPosition += delta;
|
_rectTransform.localPosition += delta;
|
||||||
if (m_CustomTarget)
|
if (m_CustomTarget)
|
||||||
{
|
{
|
||||||
if (ex2)
|
if (m_UseCanvasScale)
|
||||||
delta.Scale(canvas.rootCanvas.transform.localScale);
|
{
|
||||||
|
delta.Scale(_canvas.rootCanvas.transform.localScale);
|
||||||
|
}
|
||||||
|
|
||||||
m_CustomTarget.localPosition += delta;
|
m_CustomTarget.localPosition += delta;
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void OnBeginDrag(PointerEventData eventData)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
public void OnEndDrag(PointerEventData eventData)
|
public void OnEndDrag(PointerEventData eventData)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
private Vector2 GetLocalDelta(Vector2 evDelta)
|
private Vector2 GetLocalDelta(Vector2 evDelta)
|
||||||
{
|
{
|
||||||
switch (canvas.renderMode)
|
switch (_canvas.renderMode)
|
||||||
{
|
{
|
||||||
case RenderMode.ScreenSpaceOverlay:
|
case RenderMode.ScreenSpaceOverlay:
|
||||||
{
|
{
|
||||||
var zero = transform.InverseTransformPoint(Vector2.zero);
|
var zero = transform.InverseTransformPoint(Vector2.zero);
|
||||||
var delta = transform.InverseTransformPoint(evDelta);
|
var delta = transform.InverseTransformPoint(evDelta);
|
||||||
return delta - zero;
|
return delta - zero;
|
||||||
}
|
}
|
||||||
case RenderMode.ScreenSpaceCamera:
|
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:
|
case RenderMode.WorldSpace:
|
||||||
{
|
{
|
||||||
Vector3 zero, delta;
|
RectTransformUtility.ScreenPointToLocalPointInRectangle(_rectTransform, Vector2.zero,
|
||||||
RectTransformUtility.ScreenPointToWorldPointInRectangle(rectTransform, Vector2.zero, canvas.worldCamera, out zero);
|
_canvas.worldCamera, out var zero);
|
||||||
RectTransformUtility.ScreenPointToWorldPointInRectangle(rectTransform, evDelta, canvas.worldCamera, out delta);
|
RectTransformUtility.ScreenPointToLocalPointInRectangle(_rectTransform, evDelta,
|
||||||
return delta - zero;
|
_canvas.worldCamera, out var delta);
|
||||||
}
|
return delta - zero;
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
throw new System.NotSupportedException();
|
throw new NotSupportedException();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
private enum Target
|
||||||
|
{
|
||||||
|
Self,
|
||||||
|
Parent,
|
||||||
|
Custom
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -1,14 +1,18 @@
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
|
using UnityEngine.Serialization;
|
||||||
using UnityEngine.UI;
|
using UnityEngine.UI;
|
||||||
|
|
||||||
namespace Coffee.UIExtensions.Demo
|
namespace Coffee.UIExtensions.Demo
|
||||||
{
|
{
|
||||||
public class UIParticle_Demo : MonoBehaviour
|
public class UIParticle_Demo : MonoBehaviour
|
||||||
{
|
{
|
||||||
public Canvas root;
|
[FormerlySerializedAs("root")]
|
||||||
|
[SerializeField]
|
||||||
|
private Canvas m_RootCanvas;
|
||||||
|
|
||||||
private int _width;
|
|
||||||
private int _height;
|
private int _height;
|
||||||
|
private int _score;
|
||||||
|
private int _width;
|
||||||
|
|
||||||
private void Start()
|
private void Start()
|
||||||
{
|
{
|
||||||
|
@ -24,11 +28,18 @@ namespace Coffee.UIExtensions.Demo
|
||||||
case RuntimePlatform.WindowsPlayer:
|
case RuntimePlatform.WindowsPlayer:
|
||||||
case RuntimePlatform.LinuxPlayer:
|
case RuntimePlatform.LinuxPlayer:
|
||||||
if (Screen.width == _width && Screen.height == _height)
|
if (Screen.width == _width && Screen.height == _height)
|
||||||
|
{
|
||||||
Screen.SetResolution(_height, _width, Screen.fullScreen);
|
Screen.SetResolution(_height, _width, Screen.fullScreen);
|
||||||
|
}
|
||||||
else if (Screen.width == _height && Screen.height == _width)
|
else if (Screen.width == _height && Screen.height == _width)
|
||||||
|
{
|
||||||
Screen.SetResolution(Mathf.Min(_width, _height), Mathf.Min(_width, _height), Screen.fullScreen);
|
Screen.SetResolution(Mathf.Min(_width, _height), Mathf.Min(_width, _height), Screen.fullScreen);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
Screen.SetResolution(_width, _height, Screen.fullScreen);
|
Screen.SetResolution(_width, _height, Screen.fullScreen);
|
||||||
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -38,27 +49,31 @@ namespace Coffee.UIExtensions.Demo
|
||||||
Screen.fullScreen = !Screen.fullScreen;
|
Screen.fullScreen = !Screen.fullScreen;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void EnableAnimations(bool enabled)
|
public void EnableAnimations(bool flag)
|
||||||
{
|
{
|
||||||
foreach (var animator in FindObjectsOfType<Animator>())
|
foreach (var animator in FindObjectsOfType<Animator>())
|
||||||
{
|
{
|
||||||
animator.enabled = enabled;
|
animator.enabled = flag;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void UIParticle_MeshSharing(bool enabled)
|
public void UIParticle_MeshSharing(bool flag)
|
||||||
{
|
{
|
||||||
foreach (var uip in root.GetComponentsInChildren<UIParticle>(true))
|
foreach (var uip in m_RootCanvas.GetComponentsInChildren<UIParticle>(true))
|
||||||
{
|
{
|
||||||
uip.meshSharing = enabled ? UIParticle.MeshSharing.Auto : UIParticle.MeshSharing.None;
|
uip.meshSharing = flag
|
||||||
|
? UIParticle.MeshSharing.Auto
|
||||||
|
: UIParticle.MeshSharing.None;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void UIParticle_RandomGroup(bool enabled)
|
public void UIParticle_RandomGroup(bool flag)
|
||||||
{
|
{
|
||||||
foreach (var uip in root.GetComponentsInChildren<UIParticle>(true))
|
foreach (var uip in m_RootCanvas.GetComponentsInChildren<UIParticle>(true))
|
||||||
{
|
{
|
||||||
uip.groupMaxId = enabled ? 4 : 0;
|
uip.groupMaxId = flag
|
||||||
|
? 4
|
||||||
|
: 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -70,38 +85,40 @@ namespace Coffee.UIExtensions.Demo
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void ParticleSystem_WorldSpaseSimulation(bool enabled)
|
public void ParticleSystem_WorldSpaseSimulation(bool flag)
|
||||||
{
|
{
|
||||||
foreach (var ps in FindObjectsOfType<ParticleSystem>())
|
foreach (var p in FindObjectsOfType<ParticleSystem>())
|
||||||
{
|
{
|
||||||
var main = ps.main;
|
var main = p.main;
|
||||||
main.simulationSpace = enabled ? ParticleSystemSimulationSpace.World : ParticleSystemSimulationSpace.Local;
|
main.simulationSpace = flag
|
||||||
|
? ParticleSystemSimulationSpace.World
|
||||||
|
: ParticleSystemSimulationSpace.Local;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void ParticleSystem_WorldSpaseSimulation(ParticleSystem particleSystem)
|
public void ParticleSystem_WorldSpaseSimulation(ParticleSystem ps)
|
||||||
{
|
{
|
||||||
foreach (var ps in particleSystem.GetComponentsInChildren<ParticleSystem>())
|
foreach (var p in ps.GetComponentsInChildren<ParticleSystem>())
|
||||||
{
|
{
|
||||||
var main = ps.main;
|
var main = p.main;
|
||||||
main.simulationSpace = ParticleSystemSimulationSpace.World;
|
main.simulationSpace = ParticleSystemSimulationSpace.World;
|
||||||
ps.Clear();
|
p.Clear();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void ParticleSystem_LocalSpaseSimulation(ParticleSystem particleSystem)
|
public void ParticleSystem_LocalSpaseSimulation(ParticleSystem ps)
|
||||||
{
|
{
|
||||||
foreach (var ps in particleSystem.GetComponentsInChildren<ParticleSystem>())
|
foreach (var p in ps.GetComponentsInChildren<ParticleSystem>())
|
||||||
{
|
{
|
||||||
var main = ps.main;
|
var main = p.main;
|
||||||
main.simulationSpace = ParticleSystemSimulationSpace.Local;
|
main.simulationSpace = ParticleSystemSimulationSpace.Local;
|
||||||
ps.Clear();
|
p.Clear();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void ParticleSystem_Emit(ParticleSystem particleSystem)
|
public void ParticleSystem_Emit(ParticleSystem ps)
|
||||||
{
|
{
|
||||||
particleSystem.Emit(5);
|
ps.Emit(5);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void ParticleSystem_SetScale(float scale)
|
public void ParticleSystem_SetScale(float scale)
|
||||||
|
@ -127,41 +144,37 @@ namespace Coffee.UIExtensions.Demo
|
||||||
attractor.movement = UIParticleAttractor.Movement.Sphere;
|
attractor.movement = UIParticleAttractor.Movement.Sphere;
|
||||||
}
|
}
|
||||||
|
|
||||||
int score = 0;
|
|
||||||
public void UIParticleAttractor_OnAttract(Text scoreText)
|
public void UIParticleAttractor_OnAttract(Text scoreText)
|
||||||
{
|
{
|
||||||
score++;
|
_score++;
|
||||||
scoreText.text = score.ToString();
|
scoreText.text = _score.ToString();
|
||||||
scoreText.GetComponent<Animator>().Play(0);
|
scoreText.GetComponent<Animator>().Play(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Canvas_WorldSpace(bool flag)
|
public void Canvas_WorldSpace(bool flag)
|
||||||
{
|
{
|
||||||
if (flag)
|
if (!flag) return;
|
||||||
{
|
|
||||||
var canvas = FindObjectOfType<Canvas>();
|
var canvas = FindObjectOfType<Canvas>();
|
||||||
canvas.renderMode = RenderMode.ScreenSpaceCamera;
|
canvas.renderMode = RenderMode.ScreenSpaceCamera;
|
||||||
canvas.renderMode = RenderMode.WorldSpace;
|
canvas.renderMode = RenderMode.WorldSpace;
|
||||||
canvas.transform.rotation = Quaternion.Euler(new Vector3(0, 10, 0));
|
canvas.transform.rotation = Quaternion.Euler(new Vector3(0, 10, 0));
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Canvas_CameraSpace(bool flag)
|
public void Canvas_CameraSpace(bool flag)
|
||||||
{
|
{
|
||||||
if (flag)
|
if (!flag) return;
|
||||||
{
|
|
||||||
var canvas = FindObjectOfType<Canvas>();
|
var canvas = FindObjectOfType<Canvas>();
|
||||||
canvas.renderMode = RenderMode.ScreenSpaceCamera;
|
canvas.renderMode = RenderMode.ScreenSpaceCamera;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Canvas_Overlay(bool flag)
|
public void Canvas_Overlay(bool flag)
|
||||||
{
|
{
|
||||||
if (flag)
|
if (!flag) return;
|
||||||
{
|
|
||||||
var canvas = FindObjectOfType<Canvas>();
|
var canvas = FindObjectOfType<Canvas>();
|
||||||
canvas.renderMode = RenderMode.ScreenSpaceOverlay;
|
canvas.renderMode = RenderMode.ScreenSpaceOverlay;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,30 +1,37 @@
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
|
using UnityEngine.Serialization;
|
||||||
|
|
||||||
namespace Coffee.UIExtensions.Demo
|
namespace Coffee.UIExtensions.Demo
|
||||||
{
|
{
|
||||||
public class UIParticle_Demo_UIParticleController : MonoBehaviour
|
public class UIParticle_Demo_UIParticleController : MonoBehaviour
|
||||||
{
|
{
|
||||||
public Transform root;
|
[FormerlySerializedAs("root")]
|
||||||
|
[SerializeField]
|
||||||
|
private Transform m_RootTransform;
|
||||||
|
|
||||||
public void UIParticle_MeshSharing(bool enabled)
|
public void UIParticle_MeshSharing(bool flag)
|
||||||
{
|
{
|
||||||
foreach (var uip in root.GetComponentsInChildren<UIParticle>(true))
|
foreach (var uip in m_RootTransform.GetComponentsInChildren<UIParticle>(true))
|
||||||
{
|
{
|
||||||
uip.meshSharing = enabled ? UIParticle.MeshSharing.Auto : UIParticle.MeshSharing.None;
|
uip.meshSharing = flag
|
||||||
|
? UIParticle.MeshSharing.Auto
|
||||||
|
: UIParticle.MeshSharing.None;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void UIParticle_RandomGroup(bool enabled)
|
public void UIParticle_RandomGroup(bool flag)
|
||||||
{
|
{
|
||||||
foreach (var uip in root.GetComponentsInChildren<UIParticle>(true))
|
foreach (var uip in m_RootTransform.GetComponentsInChildren<UIParticle>(true))
|
||||||
{
|
{
|
||||||
uip.groupMaxId = enabled ? 4 : 0;
|
uip.groupMaxId = flag
|
||||||
|
? 4
|
||||||
|
: 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void UIParticle_Scale(float scale)
|
public void UIParticle_Scale(float scale)
|
||||||
{
|
{
|
||||||
foreach (var uip in root.GetComponentsInChildren<UIParticle>(true))
|
foreach (var uip in m_RootTransform.GetComponentsInChildren<UIParticle>(true))
|
||||||
{
|
{
|
||||||
uip.scale = scale;
|
uip.scale = scale;
|
||||||
}
|
}
|
||||||
|
|
Binary file not shown.
Binary file not shown.
|
@ -1,5 +1,5 @@
|
||||||
fileFormatVersion: 2
|
fileFormatVersion: 2
|
||||||
guid: 70069a8db1df148ae8b4c8108c079acf
|
guid: d07e6c2670f164cf7939ab011061a9bf
|
||||||
TrueTypeFontImporter:
|
TrueTypeFontImporter:
|
||||||
externalObjects: {}
|
externalObjects: {}
|
||||||
serializedVersion: 4
|
serializedVersion: 4
|
||||||
|
@ -8,9 +8,9 @@ TrueTypeFontImporter:
|
||||||
characterSpacing: 0
|
characterSpacing: 0
|
||||||
characterPadding: 1
|
characterPadding: 1
|
||||||
includeFontData: 1
|
includeFontData: 1
|
||||||
fontName: Falstin
|
fontName: Share Tech Mono
|
||||||
fontNames:
|
fontNames:
|
||||||
- Falstin
|
- Share Tech Mono
|
||||||
fallbackFontReferences: []
|
fallbackFontReferences: []
|
||||||
customCharacters:
|
customCharacters:
|
||||||
fontRenderingMode: 1
|
fontRenderingMode: 1
|
|
@ -127,7 +127,7 @@ MonoBehaviour:
|
||||||
m_PersistentCalls:
|
m_PersistentCalls:
|
||||||
m_Calls: []
|
m_Calls: []
|
||||||
m_FontData:
|
m_FontData:
|
||||||
m_Font: {fileID: 12800000, guid: 70069a8db1df148ae8b4c8108c079acf, type: 3}
|
m_Font: {fileID: 12800000, guid: d07e6c2670f164cf7939ab011061a9bf, type: 3}
|
||||||
m_FontSize: 14
|
m_FontSize: 14
|
||||||
m_FontStyle: 0
|
m_FontStyle: 0
|
||||||
m_BestFit: 0
|
m_BestFit: 0
|
||||||
|
@ -206,7 +206,7 @@ MonoBehaviour:
|
||||||
m_PersistentCalls:
|
m_PersistentCalls:
|
||||||
m_Calls: []
|
m_Calls: []
|
||||||
m_FontData:
|
m_FontData:
|
||||||
m_Font: {fileID: 12800000, guid: 70069a8db1df148ae8b4c8108c079acf, type: 3}
|
m_Font: {fileID: 12800000, guid: d07e6c2670f164cf7939ab011061a9bf, type: 3}
|
||||||
m_FontSize: 14
|
m_FontSize: 14
|
||||||
m_FontStyle: 0
|
m_FontStyle: 0
|
||||||
m_BestFit: 0
|
m_BestFit: 0
|
||||||
|
@ -285,7 +285,7 @@ MonoBehaviour:
|
||||||
m_PersistentCalls:
|
m_PersistentCalls:
|
||||||
m_Calls: []
|
m_Calls: []
|
||||||
m_FontData:
|
m_FontData:
|
||||||
m_Font: {fileID: 12800000, guid: 70069a8db1df148ae8b4c8108c079acf, type: 3}
|
m_Font: {fileID: 12800000, guid: d07e6c2670f164cf7939ab011061a9bf, type: 3}
|
||||||
m_FontSize: 14
|
m_FontSize: 14
|
||||||
m_FontStyle: 0
|
m_FontStyle: 0
|
||||||
m_BestFit: 0
|
m_BestFit: 0
|
||||||
|
@ -366,7 +366,7 @@ MonoBehaviour:
|
||||||
m_PersistentCalls:
|
m_PersistentCalls:
|
||||||
m_Calls: []
|
m_Calls: []
|
||||||
m_FontData:
|
m_FontData:
|
||||||
m_Font: {fileID: 12800000, guid: 70069a8db1df148ae8b4c8108c079acf, type: 3}
|
m_Font: {fileID: 12800000, guid: d07e6c2670f164cf7939ab011061a9bf, type: 3}
|
||||||
m_FontSize: 14
|
m_FontSize: 14
|
||||||
m_FontStyle: 0
|
m_FontStyle: 0
|
||||||
m_BestFit: 0
|
m_BestFit: 0
|
||||||
|
@ -516,7 +516,7 @@ MonoBehaviour:
|
||||||
m_PersistentCalls:
|
m_PersistentCalls:
|
||||||
m_Calls: []
|
m_Calls: []
|
||||||
m_FontData:
|
m_FontData:
|
||||||
m_Font: {fileID: 12800000, guid: 70069a8db1df148ae8b4c8108c079acf, type: 3}
|
m_Font: {fileID: 12800000, guid: d07e6c2670f164cf7939ab011061a9bf, type: 3}
|
||||||
m_FontSize: 14
|
m_FontSize: 14
|
||||||
m_FontStyle: 0
|
m_FontStyle: 0
|
||||||
m_BestFit: 0
|
m_BestFit: 0
|
||||||
|
@ -595,7 +595,7 @@ MonoBehaviour:
|
||||||
m_PersistentCalls:
|
m_PersistentCalls:
|
||||||
m_Calls: []
|
m_Calls: []
|
||||||
m_FontData:
|
m_FontData:
|
||||||
m_Font: {fileID: 12800000, guid: 70069a8db1df148ae8b4c8108c079acf, type: 3}
|
m_Font: {fileID: 12800000, guid: d07e6c2670f164cf7939ab011061a9bf, type: 3}
|
||||||
m_FontSize: 14
|
m_FontSize: 14
|
||||||
m_FontStyle: 0
|
m_FontStyle: 0
|
||||||
m_BestFit: 0
|
m_BestFit: 0
|
||||||
|
@ -736,7 +736,7 @@ MonoBehaviour:
|
||||||
m_PersistentCalls:
|
m_PersistentCalls:
|
||||||
m_Calls: []
|
m_Calls: []
|
||||||
m_FontData:
|
m_FontData:
|
||||||
m_Font: {fileID: 12800000, guid: 70069a8db1df148ae8b4c8108c079acf, type: 3}
|
m_Font: {fileID: 12800000, guid: d07e6c2670f164cf7939ab011061a9bf, type: 3}
|
||||||
m_FontSize: 16
|
m_FontSize: 16
|
||||||
m_FontStyle: 0
|
m_FontStyle: 0
|
||||||
m_BestFit: 0
|
m_BestFit: 0
|
||||||
|
@ -889,7 +889,7 @@ MonoBehaviour:
|
||||||
m_PersistentCalls:
|
m_PersistentCalls:
|
||||||
m_Calls: []
|
m_Calls: []
|
||||||
m_FontData:
|
m_FontData:
|
||||||
m_Font: {fileID: 12800000, guid: 70069a8db1df148ae8b4c8108c079acf, type: 3}
|
m_Font: {fileID: 12800000, guid: d07e6c2670f164cf7939ab011061a9bf, type: 3}
|
||||||
m_FontSize: 16
|
m_FontSize: 16
|
||||||
m_FontStyle: 0
|
m_FontStyle: 0
|
||||||
m_BestFit: 0
|
m_BestFit: 0
|
||||||
|
@ -1042,7 +1042,7 @@ MonoBehaviour:
|
||||||
m_PersistentCalls:
|
m_PersistentCalls:
|
||||||
m_Calls: []
|
m_Calls: []
|
||||||
m_FontData:
|
m_FontData:
|
||||||
m_Font: {fileID: 12800000, guid: 70069a8db1df148ae8b4c8108c079acf, type: 3}
|
m_Font: {fileID: 12800000, guid: d07e6c2670f164cf7939ab011061a9bf, type: 3}
|
||||||
m_FontSize: 14
|
m_FontSize: 14
|
||||||
m_FontStyle: 0
|
m_FontStyle: 0
|
||||||
m_BestFit: 0
|
m_BestFit: 0
|
||||||
|
@ -1206,7 +1206,7 @@ MonoBehaviour:
|
||||||
m_PersistentCalls:
|
m_PersistentCalls:
|
||||||
m_Calls: []
|
m_Calls: []
|
||||||
m_FontData:
|
m_FontData:
|
||||||
m_Font: {fileID: 12800000, guid: 70069a8db1df148ae8b4c8108c079acf, type: 3}
|
m_Font: {fileID: 12800000, guid: d07e6c2670f164cf7939ab011061a9bf, type: 3}
|
||||||
m_FontSize: 16
|
m_FontSize: 16
|
||||||
m_FontStyle: 0
|
m_FontStyle: 0
|
||||||
m_BestFit: 0
|
m_BestFit: 0
|
||||||
|
@ -1418,7 +1418,7 @@ MonoBehaviour:
|
||||||
m_EditorClassIdentifier:
|
m_EditorClassIdentifier:
|
||||||
m_Interval: 0.5
|
m_Interval: 0.5
|
||||||
m_Precision: 2
|
m_Precision: 2
|
||||||
m_Font: {fileID: 12800000, guid: 70069a8db1df148ae8b4c8108c079acf, type: 3}
|
m_Font: {fileID: 12800000, guid: d07e6c2670f164cf7939ab011061a9bf, type: 3}
|
||||||
m_Opened: 1
|
m_Opened: 1
|
||||||
m_FoldoutObject: {fileID: 8720459857733317289}
|
m_FoldoutObject: {fileID: 8720459857733317289}
|
||||||
m_OpenButton: {fileID: 2149219299373497733}
|
m_OpenButton: {fileID: 2149219299373497733}
|
||||||
|
@ -1502,7 +1502,7 @@ MonoBehaviour:
|
||||||
m_PersistentCalls:
|
m_PersistentCalls:
|
||||||
m_Calls: []
|
m_Calls: []
|
||||||
m_FontData:
|
m_FontData:
|
||||||
m_Font: {fileID: 12800000, guid: 70069a8db1df148ae8b4c8108c079acf, type: 3}
|
m_Font: {fileID: 12800000, guid: d07e6c2670f164cf7939ab011061a9bf, type: 3}
|
||||||
m_FontSize: 16
|
m_FontSize: 16
|
||||||
m_FontStyle: 0
|
m_FontStyle: 0
|
||||||
m_BestFit: 0
|
m_BestFit: 0
|
||||||
|
@ -1695,7 +1695,7 @@ MonoBehaviour:
|
||||||
m_PersistentCalls:
|
m_PersistentCalls:
|
||||||
m_Calls: []
|
m_Calls: []
|
||||||
m_FontData:
|
m_FontData:
|
||||||
m_Font: {fileID: 12800000, guid: 70069a8db1df148ae8b4c8108c079acf, type: 3}
|
m_Font: {fileID: 12800000, guid: d07e6c2670f164cf7939ab011061a9bf, type: 3}
|
||||||
m_FontSize: 14
|
m_FontSize: 14
|
||||||
m_FontStyle: 0
|
m_FontStyle: 0
|
||||||
m_BestFit: 0
|
m_BestFit: 0
|
||||||
|
|
|
@ -1,10 +1,11 @@
|
||||||
using System;
|
using System;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
|
using UnityEngine.Profiling;
|
||||||
using UnityEngine.Serialization;
|
using UnityEngine.Serialization;
|
||||||
using UnityEngine.UI;
|
using UnityEngine.UI;
|
||||||
#if UNITY_EDITOR
|
#if UNITY_EDITOR
|
||||||
using UnityEditor;
|
using UnityEditor;
|
||||||
|
using UnityEditorInternal;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
namespace Coffee.NanoMonitor
|
namespace Coffee.NanoMonitor
|
||||||
|
@ -13,24 +14,29 @@ namespace Coffee.NanoMonitor
|
||||||
[CustomEditor(typeof(NanoMonitor))]
|
[CustomEditor(typeof(NanoMonitor))]
|
||||||
internal class NanoMonitorEditor : Editor
|
internal class NanoMonitorEditor : Editor
|
||||||
{
|
{
|
||||||
private UnityEditorInternal.ReorderableList m_MonitorItemList;
|
private ReorderableList _monitorItemList;
|
||||||
|
|
||||||
private void OnEnable()
|
private void OnEnable()
|
||||||
{
|
{
|
||||||
var items = serializedObject.FindProperty("m_CustomMonitorItems");
|
var items = serializedObject.FindProperty("m_CustomMonitorItems");
|
||||||
m_MonitorItemList = new UnityEditorInternal.ReorderableList(serializedObject, items)
|
_monitorItemList = new ReorderableList(serializedObject, items)
|
||||||
{
|
{
|
||||||
draggable = false,
|
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, _, __) =>
|
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;
|
var labelWidth = EditorGUIUtility.labelWidth;
|
||||||
EditorGUIUtility.labelWidth = 80;
|
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;
|
EditorGUIUtility.labelWidth = labelWidth;
|
||||||
},
|
},
|
||||||
elementHeightCallback = i => EditorGUI.GetPropertyHeight(items.GetArrayElementAtIndex(i)) + 6,
|
elementHeightCallback = i => EditorGUI.GetPropertyHeight(items.GetArrayElementAtIndex(i)) + 6
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -38,7 +44,7 @@ namespace Coffee.NanoMonitor
|
||||||
{
|
{
|
||||||
base.OnInspectorGUI();
|
base.OnInspectorGUI();
|
||||||
|
|
||||||
m_MonitorItemList.DoLayoutList();
|
_monitorItemList.DoLayoutList();
|
||||||
serializedObject.ApplyModifiedProperties();
|
serializedObject.ApplyModifiedProperties();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -52,38 +58,50 @@ namespace Coffee.NanoMonitor
|
||||||
// Serialize Members.
|
// Serialize Members.
|
||||||
//################################
|
//################################
|
||||||
// Settings
|
// Settings
|
||||||
[Header("Settings")] [SerializeField] [Range(0.01f, 2f)]
|
[Header("Settings")]
|
||||||
|
[SerializeField]
|
||||||
|
[Range(0.01f, 2f)]
|
||||||
private float m_Interval = 1f;
|
private float m_Interval = 1f;
|
||||||
|
|
||||||
[SerializeField] [Range(0, 3)] private int m_Precision = 2;
|
[SerializeField]
|
||||||
[SerializeField] private Font m_Font;
|
[Range(0, 3)]
|
||||||
|
private int m_Precision = 2;
|
||||||
|
|
||||||
|
[SerializeField]
|
||||||
|
private Font m_Font;
|
||||||
|
|
||||||
// Foldout
|
// Foldout
|
||||||
[Header("Foldout")] [SerializeField] private bool m_Opened = false;
|
[Header("Foldout")]
|
||||||
|
[SerializeField]
|
||||||
|
private bool m_Opened;
|
||||||
|
|
||||||
[FormerlySerializedAs("m_Collapse")] [SerializeField]
|
[FormerlySerializedAs("m_Collapse")]
|
||||||
private GameObject m_FoldoutObject = null;
|
[SerializeField]
|
||||||
|
private GameObject m_FoldoutObject;
|
||||||
|
|
||||||
[SerializeField] private Button m_OpenButton = null;
|
[SerializeField]
|
||||||
[SerializeField] private Button m_CloseButton = null;
|
private Button m_OpenButton;
|
||||||
|
|
||||||
|
[SerializeField]
|
||||||
|
private Button m_CloseButton;
|
||||||
|
|
||||||
// View
|
// View
|
||||||
[Header("View")] [SerializeField] private MonitorUI m_Fps = null;
|
[Header("View")]
|
||||||
[SerializeField] private MonitorUI m_Gc = null;
|
[SerializeField]
|
||||||
[SerializeField] private MonitorUI m_MonoUsage = null;
|
private MonitorUI m_Fps;
|
||||||
[SerializeField] private MonitorUI m_UnityUsage = null;
|
|
||||||
|
|
||||||
[HideInInspector] [SerializeField] private CustomMonitorItem[] m_CustomMonitorItems = new CustomMonitorItem[0];
|
[SerializeField]
|
||||||
|
private MonitorUI m_Gc;
|
||||||
|
|
||||||
|
[SerializeField]
|
||||||
|
private MonitorUI m_MonoUsage;
|
||||||
|
|
||||||
//################################
|
[SerializeField]
|
||||||
// Public Members.
|
private MonitorUI m_UnityUsage;
|
||||||
//################################
|
|
||||||
public void Clean()
|
[HideInInspector]
|
||||||
{
|
[SerializeField]
|
||||||
Resources.UnloadUnusedAssets();
|
private CustomMonitorItem[] m_CustomMonitorItems = new CustomMonitorItem[0];
|
||||||
GC.Collect();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//################################
|
//################################
|
||||||
|
@ -93,44 +111,75 @@ namespace Coffee.NanoMonitor
|
||||||
private double _fpsElapsed;
|
private double _fpsElapsed;
|
||||||
private int _frames;
|
private int _frames;
|
||||||
|
|
||||||
private void Open()
|
private void Update()
|
||||||
{
|
{
|
||||||
|
_frames++;
|
||||||
|
_elapsed += Time.unscaledDeltaTime;
|
||||||
|
_fpsElapsed += Time.unscaledDeltaTime;
|
||||||
|
if (_elapsed < m_Interval) return;
|
||||||
|
|
||||||
|
if (m_Fps)
|
||||||
|
{
|
||||||
|
m_Fps.SetText("FPS: {0}", (int)(_frames / _fpsElapsed));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_Gc)
|
||||||
|
{
|
||||||
|
m_Gc.SetText("GC: {0}", GC.CollectionCount(0));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_MonoUsage)
|
||||||
|
{
|
||||||
|
var monoUsed = (Profiler.GetMonoUsedSizeLong() >> 10) / 1024f;
|
||||||
|
var monoTotal = (Profiler.GetMonoHeapSizeLong() >> 10) / 1024f;
|
||||||
|
if (m_Precision == 3)
|
||||||
|
{
|
||||||
|
m_MonoUsage.SetText("Mono: {0:N3}/{1:N3}MB", monoUsed, monoTotal);
|
||||||
|
}
|
||||||
|
else if (m_Precision == 2)
|
||||||
|
{
|
||||||
|
m_MonoUsage.SetText("Mono: {0:N2}/{1:N2}MB", monoUsed, monoTotal);
|
||||||
|
}
|
||||||
|
else if (m_Precision == 1)
|
||||||
|
{
|
||||||
|
m_MonoUsage.SetText("Mono: {0:N1}/{1:N1}MB", monoUsed, monoTotal);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_MonoUsage.SetText("Mono: {0:N0}/{1:N0}MB", monoUsed, monoTotal);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_UnityUsage)
|
||||||
|
{
|
||||||
|
var unityUsed = (Profiler.GetTotalAllocatedMemoryLong() >> 10) / 1024f;
|
||||||
|
var unityTotal = (Profiler.GetTotalReservedMemoryLong() >> 10) / 1024f;
|
||||||
|
if (m_Precision == 3)
|
||||||
|
{
|
||||||
|
m_UnityUsage.SetText("Unity: {0:N3}/{1:N3}MB", unityUsed, unityTotal);
|
||||||
|
}
|
||||||
|
else if (m_Precision == 2)
|
||||||
|
{
|
||||||
|
m_UnityUsage.SetText("Unity: {0:N2}/{1:N2}MB", unityUsed, unityTotal);
|
||||||
|
}
|
||||||
|
else if (m_Precision == 1)
|
||||||
|
{
|
||||||
|
m_UnityUsage.SetText("Unity: {0:N1}/{1:N1}MB", unityUsed, unityTotal);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_UnityUsage.SetText("Unity: {0:N0}/{1:N0}MB", unityUsed, unityTotal);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (var item in m_CustomMonitorItems)
|
||||||
|
{
|
||||||
|
item.UpdateText();
|
||||||
|
}
|
||||||
|
|
||||||
_frames = 0;
|
_frames = 0;
|
||||||
_elapsed = m_Interval;
|
_elapsed %= m_Interval;
|
||||||
_fpsElapsed = 0;
|
_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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -172,77 +221,6 @@ 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
|
#if UNITY_EDITOR
|
||||||
private void OnValidate()
|
private void OnValidate()
|
||||||
{
|
{
|
||||||
|
@ -264,5 +242,55 @@ namespace Coffee.NanoMonitor
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#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,14 +2,17 @@
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
using UnityEngine.UI;
|
using UnityEngine.UI;
|
||||||
|
|
||||||
namespace Coffee.NanoMonitor{
|
namespace Coffee.NanoMonitor
|
||||||
|
{
|
||||||
public class FixedFont
|
public class FixedFont
|
||||||
{
|
{
|
||||||
private readonly UIVertex[] _tmpVerts = new UIVertex[4];
|
private const string k_Characters =
|
||||||
private static readonly Dictionary<Font, FixedFont> _fonts = new Dictionary<Font, FixedFont>();
|
"_!\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~";
|
||||||
private static readonly TextGenerator _textGenerator = new TextGenerator(100);
|
|
||||||
|
|
||||||
private static TextGenerationSettings _settings = new TextGenerationSettings
|
private static readonly Dictionary<Font, FixedFont> s_Fonts = new Dictionary<Font, FixedFont>();
|
||||||
|
private static readonly TextGenerator s_TextGenerator = new TextGenerator(100);
|
||||||
|
|
||||||
|
private static TextGenerationSettings s_Settings = new TextGenerationSettings
|
||||||
{
|
{
|
||||||
scaleFactor = 1,
|
scaleFactor = 1,
|
||||||
horizontalOverflow = HorizontalWrapMode.Overflow,
|
horizontalOverflow = HorizontalWrapMode.Overflow,
|
||||||
|
@ -19,25 +22,33 @@ namespace Coffee.NanoMonitor{
|
||||||
color = Color.white
|
color = Color.white
|
||||||
};
|
};
|
||||||
|
|
||||||
private int _resolution = 0;
|
|
||||||
private readonly Font _font;
|
private readonly Font _font;
|
||||||
private UIVertex[] _verts;
|
private readonly UIVertex[] _tmpVerts = new UIVertex[4];
|
||||||
private UICharInfo[] _charInfos;
|
private UICharInfo[] _charInfos;
|
||||||
|
|
||||||
|
private int _resolution;
|
||||||
|
private UIVertex[] _verts;
|
||||||
|
|
||||||
private FixedFont(Font font)
|
private FixedFont(Font font)
|
||||||
{
|
{
|
||||||
_font = font;
|
_font = font;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int fontSize => _font.dynamic ? 32 : _font.fontSize;
|
public int fontSize
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return _font.dynamic ? 32 : _font.fontSize;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public static FixedFont GetOrCreate(Font font)
|
public static FixedFont GetOrCreate(Font font)
|
||||||
{
|
{
|
||||||
if (font == null) return null;
|
if (font == null) return null;
|
||||||
if (_fonts.TryGetValue(font, out var data)) return data;
|
if (s_Fonts.TryGetValue(font, out var data)) return data;
|
||||||
|
|
||||||
data = new FixedFont(font);
|
data = new FixedFont(font);
|
||||||
_fonts.Add(font, data);
|
s_Fonts.Add(font, data);
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -61,18 +72,20 @@ namespace Coffee.NanoMonitor{
|
||||||
if (_resolution == currentResolution) return;
|
if (_resolution == currentResolution) return;
|
||||||
_resolution = currentResolution;
|
_resolution = currentResolution;
|
||||||
|
|
||||||
_settings.font = _font;
|
s_Settings.font = _font;
|
||||||
_textGenerator.Invalidate();
|
s_TextGenerator.Invalidate();
|
||||||
_textGenerator.Populate("_!\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~", _settings);
|
s_TextGenerator.Populate(k_Characters, s_Settings);
|
||||||
|
|
||||||
_verts = _textGenerator.GetVerticesArray();
|
_verts = s_TextGenerator.GetVerticesArray();
|
||||||
_charInfos = _textGenerator.GetCharactersArray();
|
_charInfos = s_TextGenerator.GetCharactersArray();
|
||||||
|
|
||||||
float offsetX = 0;
|
float offsetX = 0;
|
||||||
for (var i = 0; i < _verts.Length; i++)
|
for (var i = 0; i < _verts.Length; i++)
|
||||||
{
|
{
|
||||||
if ((i & 3) == 0)
|
if ((i & 3) == 0)
|
||||||
|
{
|
||||||
offsetX = _verts[i].position.x;
|
offsetX = _verts[i].position.x;
|
||||||
|
}
|
||||||
|
|
||||||
var v = _verts[i];
|
var v = _verts[i];
|
||||||
v.position -= new Vector3(offsetX, 0);
|
v.position -= new Vector3(offsetX, 0);
|
||||||
|
@ -118,18 +131,27 @@ namespace Coffee.NanoMonitor{
|
||||||
|
|
||||||
for (var i = 0; i < 4; i++)
|
for (var i = 0; i < 4; i++)
|
||||||
{
|
{
|
||||||
_tmpVerts[i] = new UIVertex();
|
_tmpVerts[i] = new UIVertex
|
||||||
_tmpVerts[i].uv0 = uv;
|
{
|
||||||
_tmpVerts[i].color = color;
|
uv0 = uv,
|
||||||
|
color = color
|
||||||
|
};
|
||||||
|
|
||||||
if (i == 0)
|
switch (i)
|
||||||
_tmpVerts[i].position = new Vector2(-size.x, -size.y) + offset;
|
{
|
||||||
else if (i == 1)
|
case 0:
|
||||||
_tmpVerts[i].position = new Vector2(-size.x, size.y) + offset;
|
_tmpVerts[i].position = new Vector2(-size.x, -size.y) + offset;
|
||||||
else if (i == 2)
|
break;
|
||||||
_tmpVerts[i].position = new Vector2(size.x, size.y) + offset;
|
case 1:
|
||||||
else
|
_tmpVerts[i].position = new Vector2(-size.x, size.y) + offset;
|
||||||
_tmpVerts[i].position = new Vector2(size.x, -size.y) + offset;
|
break;
|
||||||
|
case 2:
|
||||||
|
_tmpVerts[i].position = new Vector2(size.x, size.y) + offset;
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
_tmpVerts[i].position = new Vector2(size.x, -size.y) + offset;
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
toFill.AddUIVertexQuad(_tmpVerts);
|
toFill.AddUIVertexQuad(_tmpVerts);
|
||||||
|
|
|
@ -1,50 +1,46 @@
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
using UnityEditor;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
using UnityEngine.UI;
|
using UnityEngine.UI;
|
||||||
|
|
||||||
namespace Coffee.NanoMonitor{
|
namespace Coffee.NanoMonitor
|
||||||
|
{
|
||||||
#if UNITY_EDITOR
|
#if UNITY_EDITOR
|
||||||
using UnityEditor;
|
|
||||||
|
|
||||||
[CustomEditor(typeof(MonitorUI))]
|
[CustomEditor(typeof(MonitorUI))]
|
||||||
public class MonitorTextEditor : Editor
|
public class MonitorTextEditor : Editor
|
||||||
{
|
{
|
||||||
private SerializedProperty m_Mode;
|
private SerializedProperty _color;
|
||||||
private SerializedProperty m_TextAnchor;
|
private SerializedProperty _font;
|
||||||
private SerializedProperty m_FontSize;
|
private SerializedProperty _fontSize;
|
||||||
private SerializedProperty m_Font;
|
private SerializedProperty _mode;
|
||||||
private SerializedProperty m_Text;
|
private SerializedProperty _text;
|
||||||
private SerializedProperty m_Color;
|
private SerializedProperty _textAnchor;
|
||||||
|
|
||||||
private void OnEnable()
|
private void OnEnable()
|
||||||
{
|
{
|
||||||
m_Mode = serializedObject.FindProperty("m_Mode");
|
_mode = serializedObject.FindProperty("m_Mode");
|
||||||
|
_text = serializedObject.FindProperty("m_Text");
|
||||||
m_Text = serializedObject.FindProperty("m_Text");
|
_color = serializedObject.FindProperty("m_Color");
|
||||||
m_Color = serializedObject.FindProperty("m_Color");
|
|
||||||
var fontData = serializedObject.FindProperty("m_FontData");
|
var fontData = serializedObject.FindProperty("m_FontData");
|
||||||
m_FontSize = fontData.FindPropertyRelative("m_FontSize");
|
_fontSize = fontData.FindPropertyRelative("m_FontSize");
|
||||||
m_Font = fontData.FindPropertyRelative("m_Font");
|
_font = fontData.FindPropertyRelative("m_Font");
|
||||||
m_TextAnchor = serializedObject.FindProperty("m_TextAnchor");
|
_textAnchor = serializedObject.FindProperty("m_TextAnchor");
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void OnInspectorGUI()
|
public override void OnInspectorGUI()
|
||||||
{
|
{
|
||||||
serializedObject.Update();
|
serializedObject.Update();
|
||||||
|
|
||||||
EditorGUILayout.PropertyField(m_Mode);
|
EditorGUILayout.PropertyField(_mode);
|
||||||
if ((MonitorUI.Mode) m_Mode.intValue == MonitorUI.Mode.Text)
|
if ((MonitorUI.Mode)_mode.intValue == MonitorUI.Mode.Text)
|
||||||
{
|
{
|
||||||
EditorGUILayout.PropertyField(m_Text);
|
EditorGUILayout.PropertyField(_text);
|
||||||
EditorGUILayout.PropertyField(m_FontSize);
|
EditorGUILayout.PropertyField(_fontSize);
|
||||||
EditorGUILayout.PropertyField(m_TextAnchor);
|
EditorGUILayout.PropertyField(_textAnchor);
|
||||||
|
EditorGUILayout.PropertyField(_font);
|
||||||
//EditorGUI.BeginDisabledGroup(true);
|
|
||||||
EditorGUILayout.PropertyField(m_Font);
|
|
||||||
//EditorGUI.EndDisabledGroup();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
EditorGUILayout.PropertyField(m_Color);
|
EditorGUILayout.PropertyField(_color);
|
||||||
|
|
||||||
serializedObject.ApplyModifiedProperties();
|
serializedObject.ApplyModifiedProperties();
|
||||||
}
|
}
|
||||||
|
@ -56,7 +52,7 @@ namespace Coffee.NanoMonitor{
|
||||||
public enum Mode
|
public enum Mode
|
||||||
{
|
{
|
||||||
Text,
|
Text,
|
||||||
Fill,
|
Fill
|
||||||
}
|
}
|
||||||
|
|
||||||
public enum TextAnchor
|
public enum TextAnchor
|
||||||
|
@ -74,26 +70,38 @@ namespace Coffee.NanoMonitor{
|
||||||
[SerializeField] private TextAnchor m_TextAnchor;
|
[SerializeField] private TextAnchor m_TextAnchor;
|
||||||
|
|
||||||
|
|
||||||
|
//################################
|
||||||
|
// Private Members.
|
||||||
|
//################################
|
||||||
|
private readonly StringBuilder _sb = new StringBuilder(64);
|
||||||
|
|
||||||
|
|
||||||
//################################
|
//################################
|
||||||
// Public Members.
|
// Public Members.
|
||||||
//################################
|
//################################
|
||||||
public override string text
|
public override string text
|
||||||
{
|
{
|
||||||
get => m_StringBuilder.ToString();
|
get
|
||||||
|
{
|
||||||
|
return _sb.ToString();
|
||||||
|
}
|
||||||
set
|
set
|
||||||
{
|
{
|
||||||
m_Text = value;
|
m_Text = value;
|
||||||
if (m_StringBuilder.IsEqual(m_Text)) return;
|
if (_sb.IsEqual(m_Text)) return;
|
||||||
|
|
||||||
m_StringBuilder.Length = 0;
|
_sb.Length = 0;
|
||||||
m_StringBuilder.Append(m_Text);
|
_sb.Append(m_Text);
|
||||||
SetVerticesDirty();
|
SetVerticesDirty();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public TextAnchor textAnchor
|
public TextAnchor textAnchor
|
||||||
{
|
{
|
||||||
get => m_TextAnchor;
|
get
|
||||||
|
{
|
||||||
|
return m_TextAnchor;
|
||||||
|
}
|
||||||
set
|
set
|
||||||
{
|
{
|
||||||
if (m_TextAnchor == value) return;
|
if (m_TextAnchor == value) return;
|
||||||
|
@ -105,44 +113,11 @@ namespace Coffee.NanoMonitor{
|
||||||
|
|
||||||
public override bool raycastTarget
|
public override bool raycastTarget
|
||||||
{
|
{
|
||||||
get => m_Mode == Mode.Fill;
|
get
|
||||||
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();
|
return m_Mode == Mode.Fill;
|
||||||
fontData.UpdateFont();
|
|
||||||
}
|
}
|
||||||
|
set { }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -151,19 +126,17 @@ namespace Coffee.NanoMonitor{
|
||||||
//################################
|
//################################
|
||||||
protected override void OnEnable()
|
protected override void OnEnable()
|
||||||
{
|
{
|
||||||
//NaNanoMonitortings.Instance.onFontChanged += UpdateFont;
|
|
||||||
RegisterDirtyMaterialCallback(UpdateFont);
|
RegisterDirtyMaterialCallback(UpdateFont);
|
||||||
|
|
||||||
base.OnEnable();
|
base.OnEnable();
|
||||||
raycastTarget = false;
|
raycastTarget = false;
|
||||||
maskable = false;
|
maskable = false;
|
||||||
m_StringBuilder.Length = 0;
|
_sb.Length = 0;
|
||||||
m_StringBuilder.Append(m_Text);
|
_sb.Append(m_Text);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void OnDisable()
|
protected override void OnDisable()
|
||||||
{
|
{
|
||||||
//NanNanoMonitorings.Instance.onFontChanged -= UpdateFont;
|
|
||||||
UnregisterDirtyMaterialCallback(UpdateFont);
|
UnregisterDirtyMaterialCallback(UpdateFont);
|
||||||
|
|
||||||
base.OnDisable();
|
base.OnDisable();
|
||||||
|
@ -174,14 +147,38 @@ namespace Coffee.NanoMonitor{
|
||||||
{
|
{
|
||||||
base.OnValidate();
|
base.OnValidate();
|
||||||
|
|
||||||
if (!m_StringBuilder.IsEqual(m_Text))
|
if (!_sb.IsEqual(m_Text))
|
||||||
{
|
{
|
||||||
m_StringBuilder.Length = 0;
|
_sb.Length = 0;
|
||||||
m_StringBuilder.Append(m_Text);
|
_sb.Append(m_Text);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#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)
|
protected override void OnPopulateMesh(VertexHelper toFill)
|
||||||
{
|
{
|
||||||
toFill.Clear();
|
toFill.Clear();
|
||||||
|
@ -197,7 +194,7 @@ namespace Coffee.NanoMonitor{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var scale = (float) fontSize / fontData.fontSize;
|
var scale = (float)fontSize / fontData.fontSize;
|
||||||
float offset = 0;
|
float offset = 0;
|
||||||
switch (textAnchor)
|
switch (textAnchor)
|
||||||
{
|
{
|
||||||
|
@ -205,20 +202,26 @@ namespace Coffee.NanoMonitor{
|
||||||
offset = rectTransform.rect.xMin;
|
offset = rectTransform.rect.xMin;
|
||||||
break;
|
break;
|
||||||
case TextAnchor.Center:
|
case TextAnchor.Center:
|
||||||
for (var i = 0; i < m_StringBuilder.Length; i++)
|
for (var i = 0; i < _sb.Length; i++)
|
||||||
offset = fontData.Layout(m_StringBuilder[i], offset, scale);
|
{
|
||||||
|
offset = fontData.Layout(_sb[i], offset, scale);
|
||||||
|
}
|
||||||
|
|
||||||
offset = -offset / 2;
|
offset = -offset / 2;
|
||||||
break;
|
break;
|
||||||
case TextAnchor.Right:
|
case TextAnchor.Right:
|
||||||
for (var i = 0; i < m_StringBuilder.Length; i++)
|
for (var i = 0; i < _sb.Length; i++)
|
||||||
offset = fontData.Layout(m_StringBuilder[i], offset, scale);
|
{
|
||||||
|
offset = fontData.Layout(_sb[i], offset, scale);
|
||||||
|
}
|
||||||
|
|
||||||
offset = rectTransform.rect.xMax - offset;
|
offset = rectTransform.rect.xMax - offset;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (var i = 0; i < m_StringBuilder.Length; i++)
|
for (var i = 0; i < _sb.Length; i++)
|
||||||
{
|
{
|
||||||
offset = fontData.Append(toFill, m_StringBuilder[i], offset, scale, color);
|
offset = fontData.Append(toFill, _sb[i], offset, scale, color);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,55 +0,0 @@
|
||||||
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
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,13 +0,0 @@
|
||||||
fileFormatVersion: 2
|
|
||||||
guid: 647dad4f8226a49b9874b68b79413d64
|
|
||||||
MonoImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
serializedVersion: 2
|
|
||||||
defaultReferences:
|
|
||||||
- miniProfilerPrefab: {fileID: 7211429669315726685, guid: 784696794bc6345bc80bf49623581c2e,
|
|
||||||
type: 3}
|
|
||||||
executionOrder: 0
|
|
||||||
icon: {instanceID: 0}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
|
@ -1,280 +0,0 @@
|
||||||
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
|
|
||||||
}
|
|
|
@ -1,11 +0,0 @@
|
||||||
fileFormatVersion: 2
|
|
||||||
guid: 6ea9606f69cee413e9f96f52de99fa5e
|
|
||||||
MonoImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
serializedVersion: 2
|
|
||||||
defaultReferences: []
|
|
||||||
executionOrder: 0
|
|
||||||
icon: {instanceID: 0}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
|
@ -1,4 +1,5 @@
|
||||||
using UnityEngine;
|
using System;
|
||||||
|
using UnityEngine;
|
||||||
#if UNITY_EDITOR
|
#if UNITY_EDITOR
|
||||||
using UnityEditor;
|
using UnityEditor;
|
||||||
#endif
|
#endif
|
||||||
|
@ -11,12 +12,17 @@ namespace Coffee.NanoMonitor
|
||||||
{
|
{
|
||||||
public override void OnGUI(Rect p, SerializedProperty property, GUIContent label)
|
public override void OnGUI(Rect p, SerializedProperty property, GUIContent label)
|
||||||
{
|
{
|
||||||
EditorGUI.PropertyField(new Rect(p.x, p.y + 18 * 0, p.width, 16), property.FindPropertyRelative("m_Text"));
|
var pos = new Rect(p.x, p.y + 18 * 0, p.width, 16);
|
||||||
EditorGUI.PropertyField(new Rect(p.x, p.y + 18 * 1, p.width, 16), property.FindPropertyRelative("m_Format"));
|
EditorGUI.PropertyField(pos, property.FindPropertyRelative("m_Text"));
|
||||||
|
pos.y += 18;
|
||||||
|
EditorGUI.PropertyField(pos, property.FindPropertyRelative("m_Format"));
|
||||||
|
pos.y += 18;
|
||||||
EditorGUI.indentLevel++;
|
EditorGUI.indentLevel++;
|
||||||
EditorGUI.PropertyField(new Rect(p.x, p.y + 18 * 2, p.width, 16), property.FindPropertyRelative("m_Arg0"));
|
EditorGUI.PropertyField(pos, property.FindPropertyRelative("m_Arg0"));
|
||||||
EditorGUI.PropertyField(new Rect(p.x, p.y + 18 * 3, p.width, 16), property.FindPropertyRelative("m_Arg1"));
|
pos.y += 18;
|
||||||
EditorGUI.PropertyField(new Rect(p.x, p.y + 18 * 4, p.width, 16), property.FindPropertyRelative("m_Arg2"));
|
EditorGUI.PropertyField(pos, property.FindPropertyRelative("m_Arg1"));
|
||||||
|
pos.y += 18;
|
||||||
|
EditorGUI.PropertyField(pos, property.FindPropertyRelative("m_Arg2"));
|
||||||
EditorGUI.indentLevel--;
|
EditorGUI.indentLevel--;
|
||||||
|
|
||||||
property.serializedObject.ApplyModifiedProperties();
|
property.serializedObject.ApplyModifiedProperties();
|
||||||
|
@ -29,19 +35,21 @@ namespace Coffee.NanoMonitor
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
[System.Serializable]
|
[Serializable]
|
||||||
public class CustomMonitorItem
|
public class CustomMonitorItem
|
||||||
{
|
{
|
||||||
[SerializeField] private MonitorUI m_Text = null;
|
[SerializeField] private MonitorUI m_Text;
|
||||||
[SerializeField] private string m_Format = "";
|
[SerializeField] private string m_Format = "";
|
||||||
[SerializeField] private NumericProperty m_Arg0 = null;
|
[SerializeField] private NumericProperty m_Arg0;
|
||||||
[SerializeField] private NumericProperty m_Arg1 = null;
|
[SerializeField] private NumericProperty m_Arg1;
|
||||||
[SerializeField] private NumericProperty m_Arg2 = null;
|
[SerializeField] private NumericProperty m_Arg2;
|
||||||
|
|
||||||
public void UpdateText()
|
public void UpdateText()
|
||||||
{
|
{
|
||||||
if (m_Text)
|
if (m_Text)
|
||||||
|
{
|
||||||
m_Text.SetText(m_Format, m_Arg0.Get(), m_Arg1.Get(), m_Arg2.Get());
|
m_Text.SetText(m_Format, m_Arg0.Get(), m_Arg1.Get(), m_Arg2.Get());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,12 +2,8 @@
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using UnityEngine;
|
|
||||||
using UnityEngine.Serialization;
|
|
||||||
#if UNITY_EDITOR
|
|
||||||
using UnityEditor;
|
using UnityEditor;
|
||||||
|
using UnityEngine;
|
||||||
#endif
|
|
||||||
|
|
||||||
namespace Coffee.NanoMonitor
|
namespace Coffee.NanoMonitor
|
||||||
{
|
{
|
||||||
|
@ -20,39 +16,45 @@ namespace Coffee.NanoMonitor
|
||||||
|
|
||||||
private static readonly Dictionary<Type, string> s_SupportedTypes = new Dictionary<Type, string>
|
private static readonly Dictionary<Type, string> s_SupportedTypes = new Dictionary<Type, string>
|
||||||
{
|
{
|
||||||
{typeof(bool), "bool"},
|
{ typeof(bool), "bool" },
|
||||||
{typeof(sbyte), "sbyte"},
|
{ typeof(sbyte), "sbyte" },
|
||||||
{typeof(short), "short"},
|
{ typeof(short), "short" },
|
||||||
{typeof(int), "int"},
|
{ typeof(int), "int" },
|
||||||
{typeof(long), "long"},
|
{ typeof(long), "long" },
|
||||||
{typeof(byte), "byte"},
|
{ typeof(byte), "byte" },
|
||||||
{typeof(ushort), "ushort"},
|
{ typeof(ushort), "ushort" },
|
||||||
{typeof(uint), "uint"},
|
{ typeof(uint), "uint" },
|
||||||
{typeof(ulong), "ulong"},
|
{ typeof(ulong), "ulong" },
|
||||||
{typeof(float), "float"},
|
{ typeof(float), "float" },
|
||||||
{typeof(double), "double"},
|
{ typeof(double), "double" },
|
||||||
{typeof(decimal), "decimal"},
|
{ typeof(decimal), "decimal" }
|
||||||
};
|
};
|
||||||
|
|
||||||
private static void Init()
|
private static void Init()
|
||||||
{
|
{
|
||||||
if (s_PropertyMenu != null) return;
|
if (s_PropertyMenu != null) return;
|
||||||
|
|
||||||
|
const BindingFlags bindingFlags = BindingFlags.Public
|
||||||
|
| BindingFlags.NonPublic
|
||||||
|
| BindingFlags.Static
|
||||||
|
| BindingFlags.GetProperty;
|
||||||
var properties = AppDomain.CurrentDomain.GetAssemblies()
|
var properties = AppDomain.CurrentDomain.GetAssemblies()
|
||||||
.SelectMany(assembly => assembly.GetTypes())
|
.SelectMany(assembly => assembly.GetTypes())
|
||||||
.SelectMany(type => type.GetProperties(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.GetProperty))
|
.SelectMany(type => type.GetProperties(bindingFlags))
|
||||||
.Where(pi => pi.GetMethod != null && s_SupportedTypes.ContainsKey(pi.PropertyType))
|
.Where(pi => pi.GetMethod != null && s_SupportedTypes.ContainsKey(pi.PropertyType))
|
||||||
.OrderBy(pi => ConvertToMenuItem(pi, false))
|
.OrderBy(pi => ConvertToMenuItem(pi, false))
|
||||||
.ToArray();
|
.ToArray();
|
||||||
|
|
||||||
s_PropertyMenu = new GenericMenu();
|
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("No Property"), false,
|
||||||
s_PropertyMenu.AddItem(new GUIContent("(Non Public Properties)/"), false, ()=>{});
|
arg => s_OnMenuSelected?.Invoke(arg as PropertyInfo), null);
|
||||||
|
s_PropertyMenu.AddItem(new GUIContent("(Non Public Properties)/"), false, () => { });
|
||||||
s_PropertyMenu.AddSeparator("");
|
s_PropertyMenu.AddSeparator("");
|
||||||
|
|
||||||
foreach (var pi in properties)
|
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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -60,11 +62,17 @@ namespace Coffee.NanoMonitor
|
||||||
{
|
{
|
||||||
var type = p.DeclaringType;
|
var type = p.DeclaringType;
|
||||||
if (type == null) return "";
|
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 typeName = type.FullName;
|
||||||
var asmName = type.Assembly.GetName().Name;
|
var asmName = type.Assembly.GetName().Name;
|
||||||
if (asmName == "UnityEngine.CoreModule")
|
if (asmName == "UnityEngine.CoreModule")
|
||||||
|
{
|
||||||
asmName = "UnityEngine";
|
asmName = "UnityEngine";
|
||||||
|
}
|
||||||
|
|
||||||
return propertyType
|
return propertyType
|
||||||
? $"{category}{asmName}/{typeName}/{s_SupportedTypes[p.PropertyType]} {p.Name}"
|
? $"{category}{asmName}/{typeName}/{s_SupportedTypes[p.PropertyType]} {p.Name}"
|
||||||
: $"{category}{asmName}/{typeName}/{p.Name}";
|
: $"{category}{asmName}/{typeName}/{p.Name}";
|
||||||
|
@ -84,7 +92,9 @@ namespace Coffee.NanoMonitor
|
||||||
{
|
{
|
||||||
s_OnMenuSelected = p =>
|
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();
|
property.serializedObject.ApplyModifiedProperties();
|
||||||
};
|
};
|
||||||
s_PropertyMenu.DropDown(position);
|
s_PropertyMenu.DropDown(position);
|
||||||
|
@ -104,6 +114,22 @@ namespace Coffee.NanoMonitor
|
||||||
[SerializeField] private string m_Path = "";
|
[SerializeField] private string m_Path = "";
|
||||||
|
|
||||||
|
|
||||||
|
//################################
|
||||||
|
// Private Members.
|
||||||
|
//################################
|
||||||
|
private Func<double> _get;
|
||||||
|
|
||||||
|
void ISerializationCallbackReceiver.OnBeforeSerialize()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void ISerializationCallbackReceiver.OnAfterDeserialize()
|
||||||
|
{
|
||||||
|
var pInfo = GetPropertyInfo(m_Path);
|
||||||
|
_get = CreateFunc(pInfo?.GetMethod);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
//################################
|
//################################
|
||||||
// Public Members.
|
// Public Members.
|
||||||
//################################
|
//################################
|
||||||
|
@ -112,12 +138,6 @@ namespace Coffee.NanoMonitor
|
||||||
return _get?.Invoke() ?? -1;
|
return _get?.Invoke() ?? -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//################################
|
|
||||||
// Private Members.
|
|
||||||
//################################
|
|
||||||
private Func<double> _get = null;
|
|
||||||
|
|
||||||
private static PropertyInfo GetPropertyInfo(string path)
|
private static PropertyInfo GetPropertyInfo(string path)
|
||||||
{
|
{
|
||||||
var p = path.Split(';');
|
var p = path.Split(';');
|
||||||
|
@ -126,14 +146,14 @@ namespace Coffee.NanoMonitor
|
||||||
var type = Type.GetType(p[0]);
|
var type = Type.GetType(p[0]);
|
||||||
if (type == null)
|
if (type == null)
|
||||||
{
|
{
|
||||||
UnityEngine.Debug.LogException(new Exception($"Type '{p[0]}' is not found"));
|
Debug.LogException(new Exception($"Type '{p[0]}' is not found"));
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
var pInfo = type.GetProperty(p[1], BindingFlags.GetProperty | BindingFlags.Public | BindingFlags.Static);
|
var pInfo = type.GetProperty(p[1], BindingFlags.GetProperty | BindingFlags.Public | BindingFlags.Static);
|
||||||
if (pInfo == null)
|
if (pInfo == null)
|
||||||
{
|
{
|
||||||
UnityEngine.Debug.LogException(new Exception($"Member '{p[1]}' is not found in type '{type}'"));
|
Debug.LogException(new Exception($"Member '{p[1]}' is not found in type '{type}'"));
|
||||||
}
|
}
|
||||||
|
|
||||||
return pInfo;
|
return pInfo;
|
||||||
|
@ -145,55 +165,72 @@ namespace Coffee.NanoMonitor
|
||||||
switch (Type.GetTypeCode(mInfo.ReturnType))
|
switch (Type.GetTypeCode(mInfo.ReturnType))
|
||||||
{
|
{
|
||||||
case TypeCode.Boolean:
|
case TypeCode.Boolean:
|
||||||
var f_bool = (Func<bool>) mInfo.CreateDelegate(typeof(Func<bool>));
|
{
|
||||||
return () => f_bool() ? 1 : 0;
|
var func = (Func<bool>)mInfo.CreateDelegate(typeof(Func<bool>));
|
||||||
|
return () => func() ? 1 : 0;
|
||||||
|
}
|
||||||
case TypeCode.Byte:
|
case TypeCode.Byte:
|
||||||
var f_byte = (Func<byte>) mInfo.CreateDelegate(typeof(Func<byte>));
|
{
|
||||||
return () => f_byte();
|
var func = (Func<byte>)mInfo.CreateDelegate(typeof(Func<byte>));
|
||||||
|
return () => func();
|
||||||
|
}
|
||||||
case TypeCode.SByte:
|
case TypeCode.SByte:
|
||||||
var f_sbyte = (Func<sbyte>) mInfo.CreateDelegate(typeof(Func<sbyte>));
|
{
|
||||||
return () => f_sbyte();
|
var func = (Func<sbyte>)mInfo.CreateDelegate(typeof(Func<sbyte>));
|
||||||
|
return () => func();
|
||||||
|
}
|
||||||
case TypeCode.UInt16:
|
case TypeCode.UInt16:
|
||||||
var f_ushort = (Func<ushort>) mInfo.CreateDelegate(typeof(Func<ushort>));
|
{
|
||||||
return () => f_ushort();
|
var func = (Func<ushort>)mInfo.CreateDelegate(typeof(Func<ushort>));
|
||||||
|
return () => func();
|
||||||
|
}
|
||||||
case TypeCode.UInt32:
|
case TypeCode.UInt32:
|
||||||
var f_uint = (Func<uint>) mInfo.CreateDelegate(typeof(Func<uint>));
|
{
|
||||||
return () => f_uint();
|
var func = (Func<uint>)mInfo.CreateDelegate(typeof(Func<uint>));
|
||||||
|
return () => func();
|
||||||
|
}
|
||||||
case TypeCode.UInt64:
|
case TypeCode.UInt64:
|
||||||
var f_ulong = (Func<ulong>) mInfo.CreateDelegate(typeof(Func<ulong>));
|
{
|
||||||
return () => f_ulong();
|
var func = (Func<ulong>)mInfo.CreateDelegate(typeof(Func<ulong>));
|
||||||
|
return () => func();
|
||||||
|
}
|
||||||
case TypeCode.Int16:
|
case TypeCode.Int16:
|
||||||
var f_short = (Func<short>) mInfo.CreateDelegate(typeof(Func<short>));
|
{
|
||||||
return () => f_short();
|
var func = (Func<short>)mInfo.CreateDelegate(typeof(Func<short>));
|
||||||
|
return () => func();
|
||||||
|
}
|
||||||
case TypeCode.Int32:
|
case TypeCode.Int32:
|
||||||
var f_int = (Func<int>) mInfo.CreateDelegate(typeof(Func<int>));
|
{
|
||||||
return () => f_int();
|
var f = (Func<int>)mInfo.CreateDelegate(typeof(Func<int>));
|
||||||
|
return () => f();
|
||||||
|
}
|
||||||
case TypeCode.Int64:
|
case TypeCode.Int64:
|
||||||
var f_long = (Func<long>) mInfo.CreateDelegate(typeof(Func<long>));
|
{
|
||||||
return () => f_long();
|
var f = (Func<long>)mInfo.CreateDelegate(typeof(Func<long>));
|
||||||
|
return () => f();
|
||||||
|
}
|
||||||
case TypeCode.Decimal:
|
case TypeCode.Decimal:
|
||||||
var f_decimal = (Func<decimal>) mInfo.CreateDelegate(typeof(Func<decimal>));
|
{
|
||||||
return () => (double) f_decimal();
|
var f = (Func<decimal>)mInfo.CreateDelegate(typeof(Func<decimal>));
|
||||||
|
return () => (double)f();
|
||||||
|
}
|
||||||
case TypeCode.Double:
|
case TypeCode.Double:
|
||||||
var f_double = (Func<double>) mInfo.CreateDelegate(typeof(Func<double>));
|
{
|
||||||
return f_double;
|
var f = (Func<double>)mInfo.CreateDelegate(typeof(Func<double>));
|
||||||
|
return f;
|
||||||
|
}
|
||||||
case TypeCode.Single:
|
case TypeCode.Single:
|
||||||
var f_float = (Func<float>) mInfo.CreateDelegate(typeof(Func<float>));
|
{
|
||||||
return () => f_float();
|
var f = (Func<float>)mInfo.CreateDelegate(typeof(Func<float>));
|
||||||
|
return () => f();
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
UnityEngine.Debug.LogException(new Exception(string.Format("Method '{1}.{0}' is not supported.", mInfo.Name, mInfo.DeclaringType)));
|
{
|
||||||
|
var message = $"Method '{mInfo.DeclaringType}.{mInfo.Name} ({mInfo.ReturnType})' is not supported.";
|
||||||
|
Debug.LogException(new Exception(message));
|
||||||
return null;
|
return null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ISerializationCallbackReceiver.OnBeforeSerialize()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void ISerializationCallbackReceiver.OnAfterDeserialize()
|
|
||||||
{
|
|
||||||
var pInfo = GetPropertyInfo(m_Path);
|
|
||||||
_get = CreateFunc(pInfo?.GetMethod);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,7 +21,8 @@ namespace Coffee.NanoMonitor
|
||||||
return true;
|
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++)
|
for (var i = 0; i < format.Length; i++)
|
||||||
{
|
{
|
||||||
|
@ -56,7 +57,7 @@ namespace Coffee.NanoMonitor
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
internal static void AppendInteger(this StringBuilder sb, double number, int padding, int precision, int alignment)
|
private static void AppendInteger(this StringBuilder sb, double number, int padding, int alignment)
|
||||||
{
|
{
|
||||||
number = Math.Truncate(number);
|
number = Math.Truncate(number);
|
||||||
var sign = number < 0;
|
var sign = number < 0;
|
||||||
|
@ -68,8 +69,8 @@ namespace Coffee.NanoMonitor
|
||||||
var n = Math.Truncate(number % 10);
|
var n = Math.Truncate(number % 10);
|
||||||
number /= 10;
|
number /= 10;
|
||||||
|
|
||||||
sb.Append((char) (n + 48));
|
sb.Append((char)(n + 48));
|
||||||
} while (1 <= number || (sb.Length - startIndex) < padding);
|
} while (1 <= number || sb.Length - startIndex < padding);
|
||||||
|
|
||||||
if (sign)
|
if (sign)
|
||||||
{
|
{
|
||||||
|
@ -82,11 +83,12 @@ namespace Coffee.NanoMonitor
|
||||||
sb.Alignment(alignment, startIndex, endIndex);
|
sb.Alignment(alignment, startIndex, endIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
internal static void AppendDouble(this StringBuilder sb, double number, int padding, int precision, int alignment)
|
private static void AppendDouble(this StringBuilder sb, double number, int padding, int precision,
|
||||||
|
int alignment)
|
||||||
{
|
{
|
||||||
var integer = Math.Truncate(number);
|
var integer = Math.Truncate(number);
|
||||||
var startIndex = sb.Length;
|
var startIndex = sb.Length;
|
||||||
sb.AppendInteger(integer, padding, precision, 0);
|
sb.AppendInteger(integer, padding, 0);
|
||||||
|
|
||||||
if (0 < precision)
|
if (0 < precision)
|
||||||
{
|
{
|
||||||
|
@ -96,8 +98,8 @@ namespace Coffee.NanoMonitor
|
||||||
for (var p = 0; p < precision; p++)
|
for (var p = 0; p < precision; p++)
|
||||||
{
|
{
|
||||||
number *= 10;
|
number *= 10;
|
||||||
integer = (long) number;
|
integer = (long)number;
|
||||||
sb.Append((char) (integer + 48));
|
sb.Append((char)(integer + 48));
|
||||||
number -= integer;
|
number -= integer;
|
||||||
number = Math.Round(number, precision);
|
number = Math.Round(number, precision);
|
||||||
}
|
}
|
||||||
|
@ -106,20 +108,18 @@ namespace Coffee.NanoMonitor
|
||||||
sb.Alignment(alignment, startIndex, sb.Length - 1);
|
sb.Alignment(alignment, startIndex, sb.Length - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
internal static void Reverse(this StringBuilder sb, int start, int end)
|
private static void Reverse(this StringBuilder sb, int start, int end)
|
||||||
{
|
{
|
||||||
while (start < end)
|
while (start < end)
|
||||||
{
|
{
|
||||||
var c = sb[start];
|
// swap
|
||||||
sb[start] = sb[end];
|
(sb[start], sb[end]) = (sb[end], sb[start]);
|
||||||
sb[end] = c;
|
|
||||||
|
|
||||||
start++;
|
start++;
|
||||||
end--;
|
end--;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
internal static void Alignment(this StringBuilder sb, int alignment, int start, int end)
|
private static void Alignment(this StringBuilder sb, int alignment, int start, int end)
|
||||||
{
|
{
|
||||||
if (alignment == 0) return;
|
if (alignment == 0) return;
|
||||||
|
|
||||||
|
@ -129,9 +129,8 @@ namespace Coffee.NanoMonitor
|
||||||
sb.Append(' ', alignment - len);
|
sb.Append(' ', alignment - len);
|
||||||
for (var i = 0; i < len; i++)
|
for (var i = 0; i < len; i++)
|
||||||
{
|
{
|
||||||
var c = sb[end - i];
|
// swap
|
||||||
sb[end - i] = sb[start + alignment - i - 1];
|
(sb[end - i], sb[start + alignment - i - 1]) = (sb[start + alignment - i - 1], sb[end - i]);
|
||||||
sb[start + alignment - i - 1] = c;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (alignment < 0 && len < -alignment)
|
else if (alignment < 0 && len < -alignment)
|
||||||
|
@ -140,7 +139,8 @@ namespace Coffee.NanoMonitor
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
internal static int GetFormat(string format, int i, out int argIndex, out int padding, out int precision, out int alignment)
|
private static int GetFormat(string format, int i, out int argIndex, out int padding, out int precision,
|
||||||
|
out int alignment)
|
||||||
{
|
{
|
||||||
argIndex = -1;
|
argIndex = -1;
|
||||||
padding = 0;
|
padding = 0;
|
||||||
|
|
|
@ -1,26 +1,35 @@
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
|
using UnityEngine.Serialization;
|
||||||
|
|
||||||
namespace Coffee.UIExtensions.Demo
|
namespace Coffee.UIExtensions.Demo
|
||||||
{
|
{
|
||||||
public class UIParticle_PerformanceDemo : MonoBehaviour
|
public class UIParticle_PerformanceDemo : MonoBehaviour
|
||||||
{
|
{
|
||||||
public GameObject copyOrigin;
|
[FormerlySerializedAs("copyOrigin")]
|
||||||
public int copyCount;
|
[SerializeField]
|
||||||
public Canvas root;
|
private GameObject m_CopyOrigin;
|
||||||
|
|
||||||
|
[FormerlySerializedAs("copyCount")]
|
||||||
|
[SerializeField]
|
||||||
|
public int m_CopyCount;
|
||||||
|
|
||||||
|
[FormerlySerializedAs("root")]
|
||||||
|
[SerializeField]
|
||||||
|
public Canvas m_RootCanvas;
|
||||||
|
|
||||||
private void Start()
|
private void Start()
|
||||||
{
|
{
|
||||||
Application.targetFrameRate = 60;
|
Application.targetFrameRate = 60;
|
||||||
|
|
||||||
if (copyOrigin)
|
if (m_CopyOrigin)
|
||||||
{
|
{
|
||||||
copyOrigin.SetActive(false);
|
m_CopyOrigin.SetActive(false);
|
||||||
|
|
||||||
var parent = copyOrigin.transform.parent;
|
var parent = m_CopyOrigin.transform.parent;
|
||||||
for (var i = 0; i < copyCount; i++)
|
for (var i = 0; i < m_CopyCount; i++)
|
||||||
{
|
{
|
||||||
var go = GameObject.Instantiate(copyOrigin, parent, false);
|
var go = Instantiate(m_CopyOrigin, parent, false);
|
||||||
go.name = string.Format("{0} {1}", copyOrigin.name, i + 1);
|
go.name = string.Format("{0} {1}", m_CopyOrigin.name, i + 1);
|
||||||
go.hideFlags = HideFlags.DontSave;
|
go.hideFlags = HideFlags.DontSave;
|
||||||
|
|
||||||
go.SetActive(true);
|
go.SetActive(true);
|
||||||
|
@ -28,32 +37,14 @@ namespace Coffee.UIExtensions.Demo
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void ChangeScreenSize()
|
public void UIParticle_Enable(bool flag)
|
||||||
{
|
{
|
||||||
if (Screen.width == 400 && Screen.height == 720)
|
foreach (var uip in m_RootCanvas.GetComponentsInChildren<UIParticle>(true))
|
||||||
Screen.SetResolution(720, 720, false);
|
|
||||||
else if (Screen.width == 720 && Screen.height == 720)
|
|
||||||
Screen.SetResolution(720, 400, false);
|
|
||||||
else
|
|
||||||
Screen.SetResolution(400, 720, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void EnableAnimations(bool enabled)
|
|
||||||
{
|
|
||||||
foreach (var animator in FindObjectsOfType<Animator>())
|
|
||||||
{
|
{
|
||||||
animator.enabled = enabled;
|
uip.enabled = flag;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
public void UIParticle_Enable(bool enabled)
|
if (!flag)
|
||||||
{
|
|
||||||
|
|
||||||
foreach (var uip in root.GetComponentsInChildren<UIParticle>(true))
|
|
||||||
{
|
|
||||||
uip.enabled = enabled;
|
|
||||||
}
|
|
||||||
if (!enabled)
|
|
||||||
{
|
{
|
||||||
foreach (var ps in FindObjectsOfType<ParticleSystem>())
|
foreach (var ps in FindObjectsOfType<ParticleSystem>())
|
||||||
{
|
{
|
||||||
|
@ -62,36 +53,23 @@ namespace Coffee.UIExtensions.Demo
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void UIParticle_MeshSharing(bool enabled)
|
public void UIParticle_MeshSharing(bool flag)
|
||||||
{
|
{
|
||||||
foreach (var uip in root.GetComponentsInChildren<UIParticle>(true))
|
foreach (var uip in m_RootCanvas.GetComponentsInChildren<UIParticle>(true))
|
||||||
{
|
{
|
||||||
uip.meshSharing = enabled ? UIParticle.MeshSharing.Auto : UIParticle.MeshSharing.None;
|
uip.meshSharing = flag
|
||||||
|
? UIParticle.MeshSharing.Auto
|
||||||
|
: UIParticle.MeshSharing.None;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void UIParticle_RandomGroup(bool enabled)
|
public void UIParticle_RandomGroup(bool flag)
|
||||||
{
|
{
|
||||||
foreach (var uip in root.GetComponentsInChildren<UIParticle>(true))
|
foreach (var uip in m_RootCanvas.GetComponentsInChildren<UIParticle>(true))
|
||||||
{
|
{
|
||||||
uip.groupMaxId = enabled ? 4 : 0;
|
uip.groupMaxId = flag
|
||||||
}
|
? 4
|
||||||
}
|
: 0;
|
||||||
|
|
||||||
public void UIParticle_Scale(float scale)
|
|
||||||
{
|
|
||||||
foreach (var uip in FindObjectsOfType<UIParticle>())
|
|
||||||
{
|
|
||||||
uip.scale = scale;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void ParticleSystem_WorldSpaseSimulation(bool enabled)
|
|
||||||
{
|
|
||||||
foreach (var ps in FindObjectsOfType<ParticleSystem>())
|
|
||||||
{
|
|
||||||
var main = ps.main;
|
|
||||||
main.simulationSpace = enabled ? ParticleSystemSimulationSpace.World : ParticleSystemSimulationSpace.Local;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -102,34 +80,5 @@ namespace Coffee.UIExtensions.Demo
|
||||||
ps.transform.localScale = new Vector3(scale, scale, scale);
|
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_ReflectionIntensity: 1
|
||||||
m_CustomReflection: {fileID: 0}
|
m_CustomReflection: {fileID: 0}
|
||||||
m_Sun: {fileID: 0}
|
m_Sun: {fileID: 0}
|
||||||
m_IndirectSpecularColor: {r: 0.12731704, g: 0.13414726, b: 0.1210787, a: 1}
|
m_IndirectSpecularColor: {r: 0.12731689, g: 0.13414702, b: 0.1210784, a: 1}
|
||||||
m_UseRadianceAmbientProbe: 0
|
m_UseRadianceAmbientProbe: 0
|
||||||
--- !u!157 &3
|
--- !u!157 &3
|
||||||
LightmapSettings:
|
LightmapSettings:
|
||||||
|
@ -757,85 +757,6 @@ Transform:
|
||||||
m_Father: {fileID: 0}
|
m_Father: {fileID: 0}
|
||||||
m_RootOrder: 2
|
m_RootOrder: 2
|
||||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
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
|
--- !u!1 &496349153
|
||||||
GameObject:
|
GameObject:
|
||||||
m_ObjectHideFlags: 0
|
m_ObjectHideFlags: 0
|
||||||
|
@ -972,12 +893,12 @@ PrefabInstance:
|
||||||
- target: {fileID: 864895766138689324, guid: a4669dfbba654429bbcddf0c9b79fb8b,
|
- target: {fileID: 864895766138689324, guid: a4669dfbba654429bbcddf0c9b79fb8b,
|
||||||
type: 3}
|
type: 3}
|
||||||
propertyPath: m_AnchoredPosition.x
|
propertyPath: m_AnchoredPosition.x
|
||||||
value: 240.00002
|
value: 240
|
||||||
objectReference: {fileID: 0}
|
objectReference: {fileID: 0}
|
||||||
- target: {fileID: 864895766138689324, guid: a4669dfbba654429bbcddf0c9b79fb8b,
|
- target: {fileID: 864895766138689324, guid: a4669dfbba654429bbcddf0c9b79fb8b,
|
||||||
type: 3}
|
type: 3}
|
||||||
propertyPath: m_AnchoredPosition.y
|
propertyPath: m_AnchoredPosition.y
|
||||||
value: -179.99998
|
value: -180
|
||||||
objectReference: {fileID: 0}
|
objectReference: {fileID: 0}
|
||||||
- target: {fileID: 864895766138689324, guid: a4669dfbba654429bbcddf0c9b79fb8b,
|
- target: {fileID: 864895766138689324, guid: a4669dfbba654429bbcddf0c9b79fb8b,
|
||||||
type: 3}
|
type: 3}
|
||||||
|
@ -1160,6 +1081,85 @@ CanvasRenderer:
|
||||||
m_PrefabAsset: {fileID: 0}
|
m_PrefabAsset: {fileID: 0}
|
||||||
m_GameObject: {fileID: 608849065}
|
m_GameObject: {fileID: 608849065}
|
||||||
m_CullTransparentMesh: 0
|
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
|
--- !u!1 &879285143
|
||||||
GameObject:
|
GameObject:
|
||||||
m_ObjectHideFlags: 0
|
m_ObjectHideFlags: 0
|
||||||
|
@ -1287,9 +1287,9 @@ MonoBehaviour:
|
||||||
m_Script: {fileID: 11500000, guid: 3a595cf9cf93f4e0686f247a5e7e19ce, type: 3}
|
m_Script: {fileID: 11500000, guid: 3a595cf9cf93f4e0686f247a5e7e19ce, type: 3}
|
||||||
m_Name:
|
m_Name:
|
||||||
m_EditorClassIdentifier:
|
m_EditorClassIdentifier:
|
||||||
copyOrigin: {fileID: 1581241706}
|
m_CopyOrigin: {fileID: 1581241706}
|
||||||
copyCount: 266
|
m_CopyCount: 266
|
||||||
root: {fileID: 919637305}
|
m_RootCanvas: {fileID: 919637305}
|
||||||
--- !u!4 &903906985
|
--- !u!4 &903906985
|
||||||
Transform:
|
Transform:
|
||||||
m_ObjectHideFlags: 0
|
m_ObjectHideFlags: 0
|
||||||
|
@ -1505,11 +1505,6 @@ PrefabInstance:
|
||||||
propertyPath: m_SizeDelta.x
|
propertyPath: m_SizeDelta.x
|
||||||
value: 0
|
value: 0
|
||||||
objectReference: {fileID: 0}
|
objectReference: {fileID: 0}
|
||||||
- target: {fileID: 151878254403844079, guid: 784696794bc6345bc80bf49623581c2e,
|
|
||||||
type: 3}
|
|
||||||
propertyPath: m_TargetGraphic
|
|
||||||
value:
|
|
||||||
objectReference: {fileID: 1002673091}
|
|
||||||
- target: {fileID: 323826319202443003, guid: 784696794bc6345bc80bf49623581c2e,
|
- target: {fileID: 323826319202443003, guid: 784696794bc6345bc80bf49623581c2e,
|
||||||
type: 3}
|
type: 3}
|
||||||
propertyPath: m_AnchorMin.y
|
propertyPath: m_AnchorMin.y
|
||||||
|
@ -1530,11 +1525,6 @@ PrefabInstance:
|
||||||
propertyPath: m_AnchoredPosition.y
|
propertyPath: m_AnchoredPosition.y
|
||||||
value: 0
|
value: 0
|
||||||
objectReference: {fileID: 0}
|
objectReference: {fileID: 0}
|
||||||
- target: {fileID: 1087632561348207336, guid: 784696794bc6345bc80bf49623581c2e,
|
|
||||||
type: 3}
|
|
||||||
propertyPath: m_TargetGraphic
|
|
||||||
value:
|
|
||||||
objectReference: {fileID: 1002673092}
|
|
||||||
- target: {fileID: 1458366075964155596, guid: 784696794bc6345bc80bf49623581c2e,
|
- target: {fileID: 1458366075964155596, guid: 784696794bc6345bc80bf49623581c2e,
|
||||||
type: 3}
|
type: 3}
|
||||||
propertyPath: m_AnchorMin.y
|
propertyPath: m_AnchorMin.y
|
||||||
|
@ -1564,7 +1554,7 @@ PrefabInstance:
|
||||||
type: 3}
|
type: 3}
|
||||||
propertyPath: m_CustomMonitorItems.Array.data[1].m_Text
|
propertyPath: m_CustomMonitorItems.Array.data[1].m_Text
|
||||||
value:
|
value:
|
||||||
objectReference: {fileID: 455490118}
|
objectReference: {fileID: 733597320}
|
||||||
- target: {fileID: 4567906826058368312, guid: 784696794bc6345bc80bf49623581c2e,
|
- target: {fileID: 4567906826058368312, guid: 784696794bc6345bc80bf49623581c2e,
|
||||||
type: 3}
|
type: 3}
|
||||||
propertyPath: m_CustomMonitorItems.Array.data[1].m_Format
|
propertyPath: m_CustomMonitorItems.Array.data[1].m_Format
|
||||||
|
@ -1630,16 +1620,6 @@ PrefabInstance:
|
||||||
propertyPath: m_SizeDelta.x
|
propertyPath: m_SizeDelta.x
|
||||||
value: 0
|
value: 0
|
||||||
objectReference: {fileID: 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,
|
- target: {fileID: 5758968653464739090, guid: 784696794bc6345bc80bf49623581c2e,
|
||||||
type: 3}
|
type: 3}
|
||||||
propertyPath: m_SizeDelta.y
|
propertyPath: m_SizeDelta.y
|
||||||
|
@ -1803,54 +1783,6 @@ RectTransform:
|
||||||
type: 3}
|
type: 3}
|
||||||
m_PrefabInstance: {fileID: 1002673087}
|
m_PrefabInstance: {fileID: 1002673087}
|
||||||
m_PrefabAsset: {fileID: 0}
|
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
|
--- !u!1 &1023851109
|
||||||
GameObject:
|
GameObject:
|
||||||
m_ObjectHideFlags: 0
|
m_ObjectHideFlags: 0
|
||||||
|
@ -3632,6 +3564,11 @@ PrefabInstance:
|
||||||
m_Modification:
|
m_Modification:
|
||||||
m_TransformParent: {fileID: 1924051224}
|
m_TransformParent: {fileID: 1924051224}
|
||||||
m_Modifications:
|
m_Modifications:
|
||||||
|
- target: {fileID: 864895764861262036, guid: a4669dfbba654429bbcddf0c9b79fb8b,
|
||||||
|
type: 3}
|
||||||
|
propertyPath: m_IgnoreCanvasScaler
|
||||||
|
value: 1
|
||||||
|
objectReference: {fileID: 0}
|
||||||
- target: {fileID: 864895765507486433, guid: a4669dfbba654429bbcddf0c9b79fb8b,
|
- target: {fileID: 864895765507486433, guid: a4669dfbba654429bbcddf0c9b79fb8b,
|
||||||
type: 3}
|
type: 3}
|
||||||
propertyPath: m_AnchorMax.x
|
propertyPath: m_AnchorMax.x
|
||||||
|
@ -3790,17 +3727,17 @@ PrefabInstance:
|
||||||
- target: {fileID: 1088568576793901561, guid: a4669dfbba654429bbcddf0c9b79fb8b,
|
- target: {fileID: 1088568576793901561, guid: a4669dfbba654429bbcddf0c9b79fb8b,
|
||||||
type: 3}
|
type: 3}
|
||||||
propertyPath: m_LocalScale.x
|
propertyPath: m_LocalScale.x
|
||||||
value: 0
|
value: 1
|
||||||
objectReference: {fileID: 0}
|
objectReference: {fileID: 0}
|
||||||
- target: {fileID: 1088568576793901561, guid: a4669dfbba654429bbcddf0c9b79fb8b,
|
- target: {fileID: 1088568576793901561, guid: a4669dfbba654429bbcddf0c9b79fb8b,
|
||||||
type: 3}
|
type: 3}
|
||||||
propertyPath: m_LocalScale.y
|
propertyPath: m_LocalScale.y
|
||||||
value: 0
|
value: 1
|
||||||
objectReference: {fileID: 0}
|
objectReference: {fileID: 0}
|
||||||
- target: {fileID: 1088568576793901561, guid: a4669dfbba654429bbcddf0c9b79fb8b,
|
- target: {fileID: 1088568576793901561, guid: a4669dfbba654429bbcddf0c9b79fb8b,
|
||||||
type: 3}
|
type: 3}
|
||||||
propertyPath: m_LocalScale.z
|
propertyPath: m_LocalScale.z
|
||||||
value: 0
|
value: 1
|
||||||
objectReference: {fileID: 0}
|
objectReference: {fileID: 0}
|
||||||
m_RemovedComponents: []
|
m_RemovedComponents: []
|
||||||
m_SourcePrefab: {fileID: 100100000, guid: a4669dfbba654429bbcddf0c9b79fb8b, type: 3}
|
m_SourcePrefab: {fileID: 100100000, guid: a4669dfbba654429bbcddf0c9b79fb8b, type: 3}
|
||||||
|
|
|
@ -1,8 +1,9 @@
|
||||||
using UnityEngine;
|
using System;
|
||||||
|
using UnityEngine;
|
||||||
|
|
||||||
namespace Coffee.UIExtensions
|
namespace Coffee.UIExtensions
|
||||||
{
|
{
|
||||||
[System.Serializable]
|
[Serializable]
|
||||||
public class AnimatableProperty : ISerializationCallbackReceiver
|
public class AnimatableProperty : ISerializationCallbackReceiver
|
||||||
{
|
{
|
||||||
public enum ShaderPropertyType
|
public enum ShaderPropertyType
|
||||||
|
@ -11,11 +12,11 @@ namespace Coffee.UIExtensions
|
||||||
Vector,
|
Vector,
|
||||||
Float,
|
Float,
|
||||||
Range,
|
Range,
|
||||||
Texture,
|
Texture
|
||||||
}
|
}
|
||||||
|
|
||||||
[SerializeField] string m_Name = "";
|
[SerializeField] private string m_Name = "";
|
||||||
[SerializeField] ShaderPropertyType m_Type = ShaderPropertyType.Vector;
|
[SerializeField] private ShaderPropertyType m_Type = ShaderPropertyType.Vector;
|
||||||
public int id { get; private set; }
|
public int id { get; private set; }
|
||||||
|
|
||||||
public ShaderPropertyType type
|
public ShaderPropertyType type
|
||||||
|
@ -23,6 +24,15 @@ namespace Coffee.UIExtensions
|
||||||
get { return m_Type; }
|
get { return m_Type; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ISerializationCallbackReceiver.OnBeforeSerialize()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void ISerializationCallbackReceiver.OnAfterDeserialize()
|
||||||
|
{
|
||||||
|
id = Shader.PropertyToID(m_Name);
|
||||||
|
}
|
||||||
|
|
||||||
public void UpdateMaterialProperties(Material material, MaterialPropertyBlock mpb)
|
public void UpdateMaterialProperties(Material material, MaterialPropertyBlock mpb)
|
||||||
{
|
{
|
||||||
if (!material.HasProperty(id)) return;
|
if (!material.HasProperty(id)) return;
|
||||||
|
@ -31,35 +41,38 @@ namespace Coffee.UIExtensions
|
||||||
{
|
{
|
||||||
case ShaderPropertyType.Color:
|
case ShaderPropertyType.Color:
|
||||||
var color = mpb.GetColor(id);
|
var color = mpb.GetColor(id);
|
||||||
if (color != default(Color))
|
if (color != default)
|
||||||
|
{
|
||||||
material.SetColor(id, color);
|
material.SetColor(id, color);
|
||||||
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case ShaderPropertyType.Vector:
|
case ShaderPropertyType.Vector:
|
||||||
var vector = mpb.GetVector(id);
|
var vector = mpb.GetVector(id);
|
||||||
if (vector != default(Vector4))
|
if (vector != default)
|
||||||
|
{
|
||||||
material.SetVector(id, vector);
|
material.SetVector(id, vector);
|
||||||
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case ShaderPropertyType.Float:
|
case ShaderPropertyType.Float:
|
||||||
case ShaderPropertyType.Range:
|
case ShaderPropertyType.Range:
|
||||||
var value = mpb.GetFloat(id);
|
var value = mpb.GetFloat(id);
|
||||||
if (value != default(float))
|
if (!Mathf.Approximately(value, 0))
|
||||||
|
{
|
||||||
material.SetFloat(id, value);
|
material.SetFloat(id, value);
|
||||||
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case ShaderPropertyType.Texture:
|
case ShaderPropertyType.Texture:
|
||||||
var tex = mpb.GetTexture(id);
|
var tex = mpb.GetTexture(id);
|
||||||
if (tex != default(Texture))
|
if (tex != default(Texture))
|
||||||
|
{
|
||||||
material.SetTexture(id, tex);
|
material.SetTexture(id, tex);
|
||||||
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void OnBeforeSerialize()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
public void OnAfterDeserialize()
|
|
||||||
{
|
|
||||||
id = Shader.PropertyToID(m_Name);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,143 @@
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,123 +0,0 @@
|
||||||
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,11 +32,16 @@ namespace Coffee.UIExtensions
|
||||||
private static void ImportSample(string jsonGuid, string sampleName)
|
private static void ImportSample(string jsonGuid, string sampleName)
|
||||||
{
|
{
|
||||||
var jsonPath = AssetDatabase.GUIDToAssetPath(jsonGuid);
|
var jsonPath = AssetDatabase.GUIDToAssetPath(jsonGuid);
|
||||||
var packageRoot = Path.GetDirectoryName(jsonPath).Replace('\\', '/');
|
if (string.IsNullOrEmpty(jsonPath)) return;
|
||||||
|
|
||||||
|
var jsonDir = Path.GetDirectoryName(jsonPath);
|
||||||
|
if (string.IsNullOrEmpty(jsonDir)) return;
|
||||||
|
|
||||||
|
var packageRoot = jsonDir.Replace('\\', '/');
|
||||||
var json = File.ReadAllText(jsonPath);
|
var json = File.ReadAllText(jsonPath);
|
||||||
var version = Regex.Match(json, "\"version\"\\s*:\\s*\"([^\"]+)\"").Groups[1].Value;
|
var version = Regex.Match(json, "\"version\"\\s*:\\s*\"([^\"]+)\"").Groups[1].Value;
|
||||||
var src = string.Format("{0}/Samples~/{1}", packageRoot, sampleName);
|
var src = $"{packageRoot}/Samples~/{sampleName}";
|
||||||
var dst = string.Format("Assets/Samples/{0}/{1}/{2}", k_DisplayName, version, sampleName);
|
var dst = $"Assets/Samples/{k_DisplayName}/{version}/{sampleName}";
|
||||||
var previousPath = GetPreviousSamplePath(k_DisplayName, sampleName);
|
var previousPath = GetPreviousSamplePath(k_DisplayName, sampleName);
|
||||||
|
|
||||||
// Remove the previous sample directory.
|
// Remove the previous sample directory.
|
||||||
|
@ -46,33 +51,45 @@ namespace Coffee.UIExtensions
|
||||||
+ previousPath
|
+ previousPath
|
||||||
+ "\n\nIt will be deleted when you update. Are you sure you want to continue?";
|
+ "\n\nIt will be deleted when you update. Are you sure you want to continue?";
|
||||||
if (!EditorUtility.DisplayDialog("Sample Importer", msg, "OK", "Cancel"))
|
if (!EditorUtility.DisplayDialog("Sample Importer", msg, "OK", "Cancel"))
|
||||||
|
{
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
FileUtil.DeleteFileOrDirectory(previousPath);
|
FileUtil.DeleteFileOrDirectory(previousPath);
|
||||||
|
|
||||||
var metaFile = previousPath + ".meta";
|
var metaFile = previousPath + ".meta";
|
||||||
if (File.Exists(metaFile))
|
if (File.Exists(metaFile))
|
||||||
|
{
|
||||||
FileUtil.DeleteFileOrDirectory(metaFile);
|
FileUtil.DeleteFileOrDirectory(metaFile);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!Directory.Exists(dst))
|
if (!Directory.Exists(dst))
|
||||||
|
{
|
||||||
FileUtil.DeleteFileOrDirectory(dst);
|
FileUtil.DeleteFileOrDirectory(dst);
|
||||||
|
}
|
||||||
|
|
||||||
var dstDir = Path.GetDirectoryName(dst);
|
var dstDir = Path.GetDirectoryName(dst);
|
||||||
if (!Directory.Exists(dstDir))
|
if (!string.IsNullOrEmpty(dstDir) && !Directory.Exists(dstDir))
|
||||||
|
{
|
||||||
Directory.CreateDirectory(dstDir);
|
Directory.CreateDirectory(dstDir);
|
||||||
|
}
|
||||||
|
|
||||||
if (Directory.Exists(src))
|
if (Directory.Exists(src))
|
||||||
|
{
|
||||||
FileUtil.CopyFileOrDirectory(src, dst);
|
FileUtil.CopyFileOrDirectory(src, dst);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
throw new DirectoryNotFoundException(src);
|
throw new DirectoryNotFoundException(src);
|
||||||
|
}
|
||||||
|
|
||||||
AssetDatabase.Refresh(ImportAssetOptions.ImportRecursive);
|
AssetDatabase.Refresh(ImportAssetOptions.ImportRecursive);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static string GetPreviousSamplePath(string displayName, string sampleName)
|
private static string GetPreviousSamplePath(string displayName, string sampleName)
|
||||||
{
|
{
|
||||||
var sampleRoot = string.Format("Assets/Samples/{0}", displayName);
|
var sampleRoot = $"Assets/Samples/{displayName}";
|
||||||
var sampleRootInfo = new DirectoryInfo(sampleRoot);
|
var sampleRootInfo = new DirectoryInfo(sampleRoot);
|
||||||
if (!sampleRootInfo.Exists) return null;
|
if (!sampleRootInfo.Exists) return null;
|
||||||
|
|
||||||
|
|
|
@ -1,19 +1,24 @@
|
||||||
#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
|
#if UNITY_2021_2_OR_NEWER
|
||||||
using UnityEditor.Overlays;
|
using UnityEditor.Overlays;
|
||||||
#else
|
#else
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
#endif
|
#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
|
namespace Coffee.UIExtensions
|
||||||
{
|
{
|
||||||
|
@ -23,7 +28,10 @@ namespace Coffee.UIExtensions
|
||||||
{
|
{
|
||||||
#if UNITY_2021_2_OR_NEWER
|
#if UNITY_2021_2_OR_NEWER
|
||||||
#if UNITY_2022_1_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
|
#else
|
||||||
[Overlay(typeof(SceneView), "Scene View/UI Particles", "UI Particles", true)]
|
[Overlay(typeof(SceneView), "Scene View/UI Particles", "UI Particles", true)]
|
||||||
#endif
|
#endif
|
||||||
|
@ -53,24 +61,22 @@ namespace Coffee.UIExtensions
|
||||||
private static readonly GUIContent s_ContentRandom = new GUIContent("Random");
|
private static readonly GUIContent s_ContentRandom = new GUIContent("Random");
|
||||||
private static readonly GUIContent s_ContentScale = new GUIContent("Scale");
|
private static readonly GUIContent s_ContentScale = new GUIContent("Scale");
|
||||||
private static SerializedObject s_SerializedObject;
|
private static SerializedObject s_SerializedObject;
|
||||||
|
private static bool s_XYZMode;
|
||||||
|
|
||||||
#if !SERIALIZE_FIELD_MASKABLE
|
private SerializedProperty _maskable;
|
||||||
private SerializedProperty m_Maskable;
|
private SerializedProperty _scale3D;
|
||||||
#endif
|
private SerializedProperty _animatableProperties;
|
||||||
private SerializedProperty m_Scale3D;
|
private SerializedProperty _meshSharing;
|
||||||
private SerializedProperty m_AnimatableProperties;
|
private SerializedProperty _groupId;
|
||||||
private SerializedProperty m_MeshSharing;
|
private SerializedProperty _groupMaxId;
|
||||||
private SerializedProperty m_GroupId;
|
private SerializedProperty _positionMode;
|
||||||
private SerializedProperty m_GroupMaxId;
|
private SerializedProperty _autoScaling;
|
||||||
private SerializedProperty m_AbsoluteMode;
|
|
||||||
|
|
||||||
|
|
||||||
private ReorderableList _ro;
|
private ReorderableList _ro;
|
||||||
static private bool _xyzMode;
|
|
||||||
private bool _showMax;
|
private bool _showMax;
|
||||||
|
|
||||||
private static readonly HashSet<Shader> s_Shaders = new HashSet<Shader>();
|
private static readonly HashSet<Shader> s_Shaders = new HashSet<Shader>();
|
||||||
private static readonly List<ParticleSystemVertexStream> s_Streams = new List<ParticleSystemVertexStream>();
|
private static readonly List<ParticleSystemVertexStream> s_Streams = new List<ParticleSystemVertexStream>();
|
||||||
|
|
||||||
private static readonly List<string> s_MaskablePropertyNames = new List<string>
|
private static readonly List<string> s_MaskablePropertyNames = new List<string>
|
||||||
{
|
{
|
||||||
"_Stencil",
|
"_Stencil",
|
||||||
|
@ -78,21 +84,20 @@ namespace Coffee.UIExtensions
|
||||||
"_StencilOp",
|
"_StencilOp",
|
||||||
"_StencilWriteMask",
|
"_StencilWriteMask",
|
||||||
"_StencilReadMask",
|
"_StencilReadMask",
|
||||||
"_ColorMask",
|
"_ColorMask"
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
[InitializeOnLoadMethod]
|
[InitializeOnLoadMethod]
|
||||||
static void Init()
|
private static void Init()
|
||||||
{
|
{
|
||||||
#if !UNITY_2021_2_OR_NEWER
|
#if !UNITY_2021_2_OR_NEWER
|
||||||
var miSceneViewOverlayWindow = Type.GetType("UnityEditor.SceneViewOverlay, UnityEditor")
|
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);
|
.First(x => x.Name == "Window" && 5 <= x.GetParameters().Length);
|
||||||
var windowFunction = (Action<UnityEngine.Object, SceneView>)WindowFunction;
|
var windowFunction = (Action<Object, SceneView>)WindowFunction;
|
||||||
var windowFunctionType = Type.GetType("UnityEditor.SceneViewOverlay+WindowFunction, UnityEditor");
|
var windowFunctionType = Type.GetType("UnityEditor.SceneViewOverlay+WindowFunction, UnityEditor");
|
||||||
var windowFunctionDelegate = Delegate.CreateDelegate(windowFunctionType, windowFunction.Method);
|
var windowFunctionDelegate = Delegate.CreateDelegate(windowFunctionType, windowFunction.Method);
|
||||||
var windowTitle = new GUIContent(ObjectNames.NicifyVariableName(typeof(UIParticle).Name));
|
var windowTitle = new GUIContent(ObjectNames.NicifyVariableName(nameof(UIParticle)));
|
||||||
#if UNITY_2019_2_OR_NEWER
|
#if UNITY_2019_2_OR_NEWER
|
||||||
//public static void Window(GUIContent title, WindowFunction sceneViewFunc, int order, Object target, WindowDisplayOption option, EditorWindow window = null)
|
//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 };
|
var sceneViewArgs = new object[] { windowTitle, windowFunctionDelegate, 599, null, 2, null };
|
||||||
|
@ -102,7 +107,7 @@ namespace Coffee.UIExtensions
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if UNITY_2019_1_OR_NEWER
|
#if UNITY_2019_1_OR_NEWER
|
||||||
SceneView.duringSceneGui += _ => { if (s_SerializedObject != null) miSceneViewOverlayWindow.Invoke(null, sceneViewArgs); };
|
SceneView.duringSceneGui += _ =>
|
||||||
#else
|
#else
|
||||||
SceneView.onSceneGUIDelegate += _ =>
|
SceneView.onSceneGUIDelegate += _ =>
|
||||||
#endif
|
#endif
|
||||||
|
@ -114,25 +119,21 @@ namespace Coffee.UIExtensions
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
Func<SerializedObject> createSerializeObject = () =>
|
SerializedObject CreateSerializeObject()
|
||||||
{
|
{
|
||||||
var uiParticles = Selection.gameObjects
|
var uiParticles = Selection.gameObjects.Select(x => x.GetComponent<ParticleSystem>())
|
||||||
.Select(x => x.GetComponent<ParticleSystem>())
|
.Where(x => x)
|
||||||
.Where(x => x)
|
.Select(x => x.GetComponentInParent<UIParticle>(true))
|
||||||
.Select(x => x.GetComponentInParent<UIParticle>())
|
.Where(x => x && x.canvas)
|
||||||
.Where(x => x && x.canvas)
|
.Concat(Selection.gameObjects.Select(x => x.GetComponent<UIParticle>())
|
||||||
.Concat(
|
.Where(x => x && x.canvas))
|
||||||
Selection.gameObjects
|
.Distinct()
|
||||||
.Select(x => x.GetComponent<UIParticle>())
|
.ToArray();
|
||||||
.Where(x => x && x.canvas)
|
|
||||||
)
|
|
||||||
.Distinct()
|
|
||||||
.ToArray();
|
|
||||||
return 0 < uiParticles.Length ? new SerializedObject(uiParticles) : null;
|
return 0 < uiParticles.Length ? new SerializedObject(uiParticles) : null;
|
||||||
};
|
}
|
||||||
|
|
||||||
s_SerializedObject = createSerializeObject();
|
s_SerializedObject = CreateSerializeObject();
|
||||||
Selection.selectionChanged += () => s_SerializedObject = createSerializeObject();
|
Selection.selectionChanged += () => s_SerializedObject = CreateSerializeObject();
|
||||||
}
|
}
|
||||||
|
|
||||||
//################################
|
//################################
|
||||||
|
@ -145,63 +146,71 @@ namespace Coffee.UIExtensions
|
||||||
{
|
{
|
||||||
base.OnEnable();
|
base.OnEnable();
|
||||||
|
|
||||||
m_Maskable = serializedObject.FindProperty("m_Maskable");
|
_maskable = serializedObject.FindProperty("m_Maskable");
|
||||||
m_Scale3D = serializedObject.FindProperty("m_Scale3D");
|
_scale3D = serializedObject.FindProperty("m_Scale3D");
|
||||||
m_AnimatableProperties = serializedObject.FindProperty("m_AnimatableProperties");
|
_animatableProperties = serializedObject.FindProperty("m_AnimatableProperties");
|
||||||
m_MeshSharing = serializedObject.FindProperty("m_MeshSharing");
|
_meshSharing = serializedObject.FindProperty("m_MeshSharing");
|
||||||
m_GroupId = serializedObject.FindProperty("m_GroupId");
|
_groupId = serializedObject.FindProperty("m_GroupId");
|
||||||
m_GroupMaxId = serializedObject.FindProperty("m_GroupMaxId");
|
_groupMaxId = serializedObject.FindProperty("m_GroupMaxId");
|
||||||
m_AbsoluteMode = serializedObject.FindProperty("m_AbsoluteMode");
|
_positionMode = serializedObject.FindProperty("m_PositionMode");
|
||||||
|
_autoScaling = serializedObject.FindProperty("m_AutoScaling");
|
||||||
|
|
||||||
var sp = serializedObject.FindProperty("m_Particles");
|
var sp = serializedObject.FindProperty("m_Particles");
|
||||||
_ro = new ReorderableList(sp.serializedObject, sp, true, true, true, true);
|
_ro = new ReorderableList(sp.serializedObject, sp, true, true, true, true)
|
||||||
_ro.elementHeight = (EditorGUIUtility.singleLineHeight * 3) + 4;
|
|
||||||
_ro.elementHeightCallback = _ => 3 * (EditorGUIUtility.singleLineHeight + 2);
|
|
||||||
_ro.drawElementCallback = (rect, index, _, __) =>
|
|
||||||
{
|
{
|
||||||
EditorGUI.BeginDisabledGroup(sp.hasMultipleDifferentValues);
|
elementHeight = EditorGUIUtility.singleLineHeight * 3 + 4,
|
||||||
rect.y += 1;
|
elementHeightCallback = _ => 3 * (EditorGUIUtility.singleLineHeight + 2),
|
||||||
rect.height = EditorGUIUtility.singleLineHeight;
|
drawElementCallback = (rect, index, _, __) =>
|
||||||
var p = sp.GetArrayElementAtIndex(index);
|
|
||||||
EditorGUI.ObjectField(rect, p, GUIContent.none);
|
|
||||||
rect.x += 15;
|
|
||||||
rect.width -= 15;
|
|
||||||
var ps = p.objectReferenceValue as ParticleSystem;
|
|
||||||
var materials = ps
|
|
||||||
? new SerializedObject(ps.GetComponent<ParticleSystemRenderer>()).FindProperty("m_Materials")
|
|
||||||
: null;
|
|
||||||
rect.y += rect.height + 1;
|
|
||||||
MaterialField(rect, s_ContentMaterial, materials, 0);
|
|
||||||
rect.y += rect.height + 1;
|
|
||||||
MaterialField(rect, s_ContentTrailMaterial, materials, 1);
|
|
||||||
EditorGUI.EndDisabledGroup();
|
|
||||||
if (materials != null && materials.serializedObject.hasModifiedProperties)
|
|
||||||
{
|
{
|
||||||
materials.serializedObject.ApplyModifiedProperties();
|
EditorGUI.BeginDisabledGroup(sp.hasMultipleDifferentValues);
|
||||||
}
|
rect.y += 1;
|
||||||
};
|
rect.height = EditorGUIUtility.singleLineHeight;
|
||||||
_ro.drawHeaderCallback = rect =>
|
var p = sp.GetArrayElementAtIndex(index);
|
||||||
{
|
EditorGUI.ObjectField(rect, p, GUIContent.none);
|
||||||
#if !UNITY_2019_3_OR_NEWER
|
rect.x += 15;
|
||||||
rect.y -= 1;
|
rect.width -= 15;
|
||||||
#endif
|
var ps = p.objectReferenceValue as ParticleSystem;
|
||||||
EditorGUI.LabelField(new Rect(rect.x, rect.y, 150, rect.height), s_ContentRenderingOrder);
|
var materials = ps
|
||||||
|
? new SerializedObject(ps.GetComponent<ParticleSystemRenderer>()).FindProperty("m_Materials")
|
||||||
if (GUI.Button(new Rect(rect.width - 35, rect.y, 60, rect.height), s_ContentRefresh, EditorStyles.miniButton))
|
: null;
|
||||||
{
|
rect.y += rect.height + 1;
|
||||||
foreach (UIParticle t in targets)
|
MaterialField(rect, s_ContentMaterial, materials, 0);
|
||||||
|
rect.y += rect.height + 1;
|
||||||
|
MaterialField(rect, s_ContentTrailMaterial, materials, 1);
|
||||||
|
EditorGUI.EndDisabledGroup();
|
||||||
|
if (materials != null && materials.serializedObject.hasModifiedProperties)
|
||||||
{
|
{
|
||||||
t.RefreshParticles();
|
materials.serializedObject.ApplyModifiedProperties();
|
||||||
EditorUtility.SetDirty(t);
|
}
|
||||||
|
},
|
||||||
|
drawHeaderCallback = rect =>
|
||||||
|
{
|
||||||
|
#if !UNITY_2019_3_OR_NEWER
|
||||||
|
rect.y -= 1;
|
||||||
|
#endif
|
||||||
|
var pos = new Rect(rect.x, rect.y, 150, rect.height);
|
||||||
|
EditorGUI.LabelField(pos, s_ContentRenderingOrder);
|
||||||
|
|
||||||
|
pos = new Rect(rect.width - 35, rect.y, 60, rect.height);
|
||||||
|
if (GUI.Button(pos, s_ContentRefresh, EditorStyles.miniButton))
|
||||||
|
{
|
||||||
|
foreach (var uip in targets.OfType<UIParticle>())
|
||||||
|
{
|
||||||
|
uip.RefreshParticles();
|
||||||
|
EditorUtility.SetDirty(uip);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// On select UIParticle, refresh particles.
|
// On select UIParticle, refresh particles.
|
||||||
foreach (UIParticle t in targets)
|
if (!Application.isPlaying)
|
||||||
{
|
{
|
||||||
if (Application.isPlaying || PrefabUtility.GetPrefabAssetType(t) != PrefabAssetType.NotAPrefab) continue;
|
foreach (var uip in targets.OfType<UIParticle>())
|
||||||
t.RefreshParticles(t.particles);
|
{
|
||||||
|
if (PrefabUtility.GetPrefabAssetType(uip) != PrefabAssetType.NotAPrefab) continue;
|
||||||
|
uip.RefreshParticles(uip.particles);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -230,11 +239,11 @@ namespace Coffee.UIExtensions
|
||||||
serializedObject.Update();
|
serializedObject.Update();
|
||||||
|
|
||||||
// Maskable
|
// Maskable
|
||||||
EditorGUILayout.PropertyField(m_Maskable);
|
EditorGUILayout.PropertyField(_maskable);
|
||||||
|
|
||||||
// Scale
|
// Scale
|
||||||
EditorGUI.BeginDisabledGroup(!m_MeshSharing.hasMultipleDifferentValues && m_MeshSharing.intValue == 4);
|
EditorGUI.BeginDisabledGroup(!_meshSharing.hasMultipleDifferentValues && _meshSharing.intValue == 4);
|
||||||
_xyzMode = DrawFloatOrVector3Field(m_Scale3D, _xyzMode);
|
s_XYZMode = DrawFloatOrVector3Field(_scale3D, s_XYZMode);
|
||||||
EditorGUI.EndDisabledGroup();
|
EditorGUI.EndDisabledGroup();
|
||||||
|
|
||||||
// AnimatableProperties
|
// AnimatableProperties
|
||||||
|
@ -244,12 +253,11 @@ namespace Coffee.UIExtensions
|
||||||
.Where(x => x)
|
.Where(x => x)
|
||||||
.ToArray();
|
.ToArray();
|
||||||
|
|
||||||
// Animated properties
|
AnimatablePropertyEditor.Draw(_animatableProperties, mats);
|
||||||
AnimatedPropertiesEditor.DrawAnimatableProperties(m_AnimatableProperties, mats);
|
|
||||||
|
|
||||||
// Mesh sharing
|
// Mesh sharing
|
||||||
EditorGUI.BeginChangeCheck();
|
EditorGUI.BeginChangeCheck();
|
||||||
_showMax = DrawMeshSharing(m_MeshSharing, m_GroupId, m_GroupMaxId, _showMax);
|
_showMax = DrawMeshSharing(_meshSharing, _groupId, _groupMaxId, _showMax);
|
||||||
if (EditorGUI.EndChangeCheck())
|
if (EditorGUI.EndChangeCheck())
|
||||||
{
|
{
|
||||||
serializedObject.ApplyModifiedProperties();
|
serializedObject.ApplyModifiedProperties();
|
||||||
|
@ -259,8 +267,11 @@ namespace Coffee.UIExtensions
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Absolute Mode
|
// Position Mode
|
||||||
EditorGUILayout.PropertyField(m_AbsoluteMode);
|
EditorGUILayout.PropertyField(_positionMode);
|
||||||
|
|
||||||
|
// Auto Scaling
|
||||||
|
DrawAutoScaling(_autoScaling, targets.OfType<UIParticle>());
|
||||||
|
|
||||||
// Target ParticleSystems.
|
// Target ParticleSystems.
|
||||||
EditorGUI.BeginChangeCheck();
|
EditorGUI.BeginChangeCheck();
|
||||||
|
@ -276,8 +287,22 @@ 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?
|
// Does the shader support UI masks?
|
||||||
if (current.maskable && current.GetComponentInParent<Mask>())
|
if (current.maskable && current.GetComponentInParent<Mask>(false))
|
||||||
{
|
{
|
||||||
foreach (var mat in current.materials)
|
foreach (var mat in current.materials)
|
||||||
{
|
{
|
||||||
|
@ -289,15 +314,20 @@ namespace Coffee.UIExtensions
|
||||||
{
|
{
|
||||||
if (mat.HasProperty(propName)) continue;
|
if (mat.HasProperty(propName)) continue;
|
||||||
|
|
||||||
EditorGUILayout.HelpBox(string.Format("Shader '{0}' doesn't have '{1}' property. This graphic cannot be masked.", shader.name, propName), MessageType.Warning);
|
EditorGUILayout.HelpBox(
|
||||||
|
$"Shader '{shader.name}' doesn't have '{propName}' property." +
|
||||||
|
"\nThis graphic cannot be masked.",
|
||||||
|
MessageType.Warning);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
s_Shaders.Clear();
|
s_Shaders.Clear();
|
||||||
|
|
||||||
// UIParticle for trail should be removed.
|
// UIParticle for trail should be removed.
|
||||||
if (FixButton(current.m_IsTrail, "This UIParticle component should be removed. The UIParticle for trails is no longer needed."))
|
var label = "This UIParticle component should be removed. The UIParticle for trails is no longer needed.";
|
||||||
|
if (FixButton(current.m_IsTrail, label))
|
||||||
{
|
{
|
||||||
DestroyUIParticle(current);
|
DestroyUIParticle(current);
|
||||||
}
|
}
|
||||||
|
@ -313,7 +343,9 @@ namespace Coffee.UIExtensions
|
||||||
{
|
{
|
||||||
var so = new SerializedObject(allPsRenderers);
|
var so = new SerializedObject(allPsRenderers);
|
||||||
var sp = so.FindProperty("m_ApplyActiveColorSpace");
|
var sp = so.FindProperty("m_ApplyActiveColorSpace");
|
||||||
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."))
|
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))
|
||||||
{
|
{
|
||||||
sp.boolValue = false;
|
sp.boolValue = false;
|
||||||
so.ApplyModifiedProperties();
|
so.ApplyModifiedProperties();
|
||||||
|
@ -328,12 +360,23 @@ namespace Coffee.UIExtensions
|
||||||
|
|
||||||
if (2 < s_Streams.Select(GetUsedComponentCount).Sum())
|
if (2 < s_Streams.Select(GetUsedComponentCount).Sum())
|
||||||
{
|
{
|
||||||
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);
|
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();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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)
|
private static int GetUsedComponentCount(ParticleSystemVertexStream s)
|
||||||
{
|
{
|
||||||
switch (s)
|
switch (s)
|
||||||
|
@ -389,10 +432,12 @@ namespace Coffee.UIExtensions
|
||||||
case ParticleSystemVertexStream.Custom2XYZW:
|
case ParticleSystemVertexStream.Custom2XYZW:
|
||||||
return 4;
|
return 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 3;
|
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 ||
|
showMax |= spGroupId.intValue != spGroupMaxId.intValue ||
|
||||||
spGroupId.hasMultipleDifferentValues ||
|
spGroupId.hasMultipleDifferentValues ||
|
||||||
|
@ -404,7 +449,10 @@ namespace Coffee.UIExtensions
|
||||||
EditorGUI.BeginChangeCheck();
|
EditorGUI.BeginChangeCheck();
|
||||||
showMax = GUILayout.Toggle(showMax, s_ContentRandom, EditorStyles.miniButton, GUILayout.Width(60));
|
showMax = GUILayout.Toggle(showMax, s_ContentRandom, EditorStyles.miniButton, GUILayout.Width(60));
|
||||||
if (EditorGUI.EndChangeCheck() && !showMax)
|
if (EditorGUI.EndChangeCheck() && !showMax)
|
||||||
|
{
|
||||||
spGroupMaxId.intValue = spGroupId.intValue;
|
spGroupMaxId.intValue = spGroupId.intValue;
|
||||||
|
}
|
||||||
|
|
||||||
EditorGUILayout.EndHorizontal();
|
EditorGUILayout.EndHorizontal();
|
||||||
|
|
||||||
EditorGUI.BeginDisabledGroup(spMeshSharing.intValue == 0);
|
EditorGUI.BeginDisabledGroup(spMeshSharing.intValue == 0);
|
||||||
|
@ -417,20 +465,41 @@ namespace Coffee.UIExtensions
|
||||||
else if (spMeshSharing.intValue == 1 || spMeshSharing.intValue == 4)
|
else if (spMeshSharing.intValue == 1 || spMeshSharing.intValue == 4)
|
||||||
{
|
{
|
||||||
EditorGUI.BeginDisabledGroup(true);
|
EditorGUI.BeginDisabledGroup(true);
|
||||||
EditorGUILayout.ObjectField("Primary", UIParticleUpdater.GetPrimary(spGroupId.intValue), typeof(UIParticle), false);
|
var obj = UIParticleUpdater.GetPrimary(spGroupId.intValue);
|
||||||
|
EditorGUILayout.ObjectField("Primary", obj, typeof(UIParticle), false);
|
||||||
EditorGUI.EndDisabledGroup();
|
EditorGUI.EndDisabledGroup();
|
||||||
}
|
}
|
||||||
|
|
||||||
EditorGUI.indentLevel--;
|
EditorGUI.indentLevel--;
|
||||||
EditorGUI.EndDisabledGroup();
|
EditorGUI.EndDisabledGroup();
|
||||||
|
|
||||||
return showMax;
|
return showMax;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void WindowFunction(UnityEngine.Object target, SceneView sceneView)
|
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)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
if (s_SerializedObject.targetObjects.OfType<UIParticle>().Any(x => !x || !x.canvas)) return;
|
if (s_SerializedObject == null || !s_SerializedObject.targetObject) return;
|
||||||
|
var uiParticles = s_SerializedObject.targetObjects.OfType<UIParticle>();
|
||||||
|
if (uiParticles.Any(x => !x || !x.canvas)) return;
|
||||||
|
|
||||||
s_SerializedObject.Update();
|
s_SerializedObject.Update();
|
||||||
using (new EditorGUILayout.VerticalScope(GUILayout.Width(220f)))
|
using (new EditorGUILayout.VerticalScope(GUILayout.Width(220f)))
|
||||||
|
@ -438,37 +507,36 @@ namespace Coffee.UIExtensions
|
||||||
var labelWidth = EditorGUIUtility.labelWidth;
|
var labelWidth = EditorGUIUtility.labelWidth;
|
||||||
EditorGUIUtility.labelWidth = 100;
|
EditorGUIUtility.labelWidth = 100;
|
||||||
EditorGUILayout.PropertyField(s_SerializedObject.FindProperty("m_Enabled"));
|
EditorGUILayout.PropertyField(s_SerializedObject.FindProperty("m_Enabled"));
|
||||||
_xyzMode = DrawFloatOrVector3Field(s_SerializedObject.FindProperty("m_Scale3D"), _xyzMode);
|
s_XYZMode = DrawFloatOrVector3Field(s_SerializedObject.FindProperty("m_Scale3D"), s_XYZMode);
|
||||||
EditorGUILayout.PropertyField(s_SerializedObject.FindProperty("m_AbsoluteMode"));
|
EditorGUILayout.PropertyField(s_SerializedObject.FindProperty("m_PositionMode"));
|
||||||
|
DrawAutoScaling(s_SerializedObject.FindProperty("m_AutoScaling"), uiParticles);
|
||||||
EditorGUIUtility.labelWidth = labelWidth;
|
EditorGUIUtility.labelWidth = labelWidth;
|
||||||
}
|
}
|
||||||
|
|
||||||
s_SerializedObject.ApplyModifiedProperties();
|
s_SerializedObject.ApplyModifiedProperties();
|
||||||
}
|
}
|
||||||
catch
|
catch
|
||||||
{
|
{
|
||||||
|
// ignored
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void DestroyUIParticle(UIParticle p, bool ignoreCurrent = false)
|
private void DestroyUIParticle(UIParticle p, bool ignoreCurrent = false)
|
||||||
{
|
{
|
||||||
if (!p || ignoreCurrent && target == p) return;
|
if (!p || (ignoreCurrent && target == p)) return;
|
||||||
|
|
||||||
var cr = p.canvasRenderer;
|
var cr = p.canvasRenderer;
|
||||||
DestroyImmediate(p);
|
DestroyImmediate(p);
|
||||||
DestroyImmediate(cr);
|
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
|
#if UNITY_2018_3_OR_NEWER
|
||||||
|
var stage = PrefabStageUtility.GetCurrentPrefabStage();
|
||||||
if (stage != null && stage.scene.isLoaded)
|
if (stage != null && stage.scene.isLoaded)
|
||||||
{
|
{
|
||||||
#if UNITY_2020_1_OR_NEWER
|
#if UNITY_2020_1_OR_NEWER
|
||||||
string prefabAssetPath = stage.assetPath;
|
string prefabAssetPath = stage.assetPath;
|
||||||
#else
|
#else
|
||||||
string prefabAssetPath = stage.prefabAssetPath;
|
var prefabAssetPath = stage.prefabAssetPath;
|
||||||
#endif
|
#endif
|
||||||
PrefabUtility.SaveAsPrefabAsset(stage.prefabContentsRoot, prefabAssetPath);
|
PrefabUtility.SaveAsPrefabAsset(stage.prefabContentsRoot, prefabAssetPath);
|
||||||
}
|
}
|
||||||
|
@ -517,7 +585,10 @@ namespace Coffee.UIExtensions
|
||||||
EditorGUI.BeginChangeCheck();
|
EditorGUI.BeginChangeCheck();
|
||||||
showXyz = GUILayout.Toggle(showXyz, s_Content3D, EditorStyles.miniButton, GUILayout.Width(30));
|
showXyz = GUILayout.Toggle(showXyz, s_Content3D, EditorStyles.miniButton, GUILayout.Width(30));
|
||||||
if (EditorGUI.EndChangeCheck() && !showXyz)
|
if (EditorGUI.EndChangeCheck() && !showXyz)
|
||||||
|
{
|
||||||
z.floatValue = y.floatValue = x.floatValue;
|
z.floatValue = y.floatValue = x.floatValue;
|
||||||
|
}
|
||||||
|
|
||||||
EditorGUILayout.EndHorizontal();
|
EditorGUILayout.EndHorizontal();
|
||||||
|
|
||||||
return showXyz;
|
return showXyz;
|
||||||
|
|
|
@ -34,10 +34,10 @@ namespace Coffee.UIExtensions
|
||||||
ps.transform.SetParent(uiParticle.transform, false);
|
ps.transform.SetParent(uiParticle.transform, false);
|
||||||
ps.transform.localPosition = Vector3.zero;
|
ps.transform.localPosition = Vector3.zero;
|
||||||
|
|
||||||
// Assign default material.
|
// Assign default material (UIAdditive).
|
||||||
var renderer = ps.GetComponent<ParticleSystemRenderer>();
|
var renderer = ps.GetComponent<ParticleSystemRenderer>();
|
||||||
var defaultMat = AssetDatabase.GetBuiltinExtraResource<Material>("Default-Particle.mat");
|
var path = AssetDatabase.GUIDToAssetPath("9944483a3e009401ba5dcc42f14d5c63");
|
||||||
renderer.material = defaultMat ? defaultMat : renderer.material;
|
renderer.material = AssetDatabase.LoadAssetAtPath<Material>(path);
|
||||||
|
|
||||||
// Refresh particles.
|
// Refresh particles.
|
||||||
uiParticle.RefreshParticles();
|
uiParticle.RefreshParticles();
|
||||||
|
|
|
@ -10,7 +10,7 @@ namespace Coffee.UIParticleExtensions
|
||||||
public static Material Add(Material baseMat, Texture texture, int id)
|
public static Material Add(Material baseMat, Texture texture, int id)
|
||||||
{
|
{
|
||||||
MatEntry e;
|
MatEntry e;
|
||||||
for (var i = 0; i < s_Entries.Count; ++i)
|
for (var i = 0; i < s_Entries.Count; i++)
|
||||||
{
|
{
|
||||||
e = s_Entries[i];
|
e = s_Entries[i];
|
||||||
if (e.baseMat != baseMat || e.texture != texture || e.id != id) continue;
|
if (e.baseMat != baseMat || e.texture != texture || e.id != id) continue;
|
||||||
|
@ -18,15 +18,19 @@ namespace Coffee.UIParticleExtensions
|
||||||
return e.customMat;
|
return e.customMat;
|
||||||
}
|
}
|
||||||
|
|
||||||
e = new MatEntry();
|
e = new MatEntry
|
||||||
e.count = 1;
|
{
|
||||||
e.baseMat = baseMat;
|
count = 1,
|
||||||
e.texture = texture;
|
baseMat = baseMat,
|
||||||
e.id = id;
|
texture = texture,
|
||||||
e.customMat = new Material(baseMat);
|
id = id,
|
||||||
e.customMat.hideFlags = HideFlags.HideAndDontSave;
|
customMat = new Material(baseMat)
|
||||||
if (texture)
|
{
|
||||||
e.customMat.mainTexture = texture;
|
name = $"{baseMat.name}_{id}",
|
||||||
|
hideFlags = HideFlags.HideAndDontSave,
|
||||||
|
mainTexture = texture ? texture : null
|
||||||
|
}
|
||||||
|
};
|
||||||
s_Entries.Add(e);
|
s_Entries.Add(e);
|
||||||
//Debug.LogFormat(">>>> ModifiedMaterial.Add -> count = count:{0}, mat:{1}, tex:{2}, id:{3}", s_Entries.Count, baseMat, texture, id);
|
//Debug.LogFormat(">>>> ModifiedMaterial.Add -> count = count:{0}, mat:{1}, tex:{2}, id:{3}", s_Entries.Count, baseMat, texture, id);
|
||||||
return e.customMat;
|
return e.customMat;
|
||||||
|
@ -43,7 +47,8 @@ namespace Coffee.UIParticleExtensions
|
||||||
if (--e.count == 0)
|
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);
|
//Debug.LogFormat(">>>> ModifiedMaterial.Remove -> count:{0}, mat:{1}, tex:{2}, id:{3}", s_Entries.Count - 1, e.customMat, e.texture, e.id);
|
||||||
DestroyImmediate(e.customMat);
|
Misc.DestroyImmediate(e.customMat);
|
||||||
|
e.customMat = null;
|
||||||
e.baseMat = null;
|
e.baseMat = null;
|
||||||
e.texture = null;
|
e.texture = null;
|
||||||
s_Entries.RemoveAt(i);
|
s_Entries.RemoveAt(i);
|
||||||
|
@ -53,22 +58,13 @@ 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
|
private class MatEntry
|
||||||
{
|
{
|
||||||
public Material baseMat;
|
public Material baseMat;
|
||||||
public Material customMat;
|
|
||||||
public int count;
|
public int count;
|
||||||
public Texture texture;
|
public Material customMat;
|
||||||
public int id;
|
public int id;
|
||||||
|
public Texture texture;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,11 +2,11 @@
|
||||||
#define SERIALIZE_FIELD_MASKABLE
|
#define SERIALIZE_FIELD_MASKABLE
|
||||||
#endif
|
#endif
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
|
||||||
using System.Runtime.CompilerServices;
|
using System.Runtime.CompilerServices;
|
||||||
using Coffee.UIParticleExtensions;
|
using Coffee.UIParticleExtensions;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
using UnityEngine.Rendering;
|
using UnityEngine.Rendering;
|
||||||
|
using UnityEngine.Serialization;
|
||||||
using UnityEngine.UI;
|
using UnityEngine.UI;
|
||||||
|
|
||||||
[assembly: InternalsVisibleTo("Coffee.UIParticle.Editor")]
|
[assembly: InternalsVisibleTo("Coffee.UIParticle.Editor")]
|
||||||
|
@ -19,7 +19,7 @@ namespace Coffee.UIExtensions
|
||||||
[ExecuteAlways]
|
[ExecuteAlways]
|
||||||
[RequireComponent(typeof(RectTransform))]
|
[RequireComponent(typeof(RectTransform))]
|
||||||
[RequireComponent(typeof(CanvasRenderer))]
|
[RequireComponent(typeof(CanvasRenderer))]
|
||||||
public class UIParticle : MaskableGraphic
|
public class UIParticle : MaskableGraphic, ISerializationCallbackReceiver
|
||||||
{
|
{
|
||||||
public enum MeshSharing
|
public enum MeshSharing
|
||||||
{
|
{
|
||||||
|
@ -27,16 +27,34 @@ namespace Coffee.UIExtensions
|
||||||
Auto,
|
Auto,
|
||||||
Primary,
|
Primary,
|
||||||
PrimarySimulator,
|
PrimarySimulator,
|
||||||
Replica,
|
Replica
|
||||||
}
|
}
|
||||||
|
|
||||||
[HideInInspector][SerializeField] internal bool m_IsTrail = false;
|
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;
|
||||||
|
|
||||||
[Tooltip("Particle effect scale")]
|
[Tooltip("Particle effect scale")]
|
||||||
[SerializeField]
|
[SerializeField]
|
||||||
private Vector3 m_Scale3D = new Vector3(10, 10, 10);
|
private Vector3 m_Scale3D = new Vector3(10, 10, 10);
|
||||||
|
|
||||||
[Tooltip("Animatable material properties. If you want to change the material properties of the ParticleSystem in Animation, enable it.")]
|
[Tooltip("Animatable material properties.\n" +
|
||||||
|
"If you want to change the material properties of the ParticleSystem in Animation, enable it.")]
|
||||||
[SerializeField]
|
[SerializeField]
|
||||||
internal AnimatableProperty[] m_AnimatableProperties = new AnimatableProperty[0];
|
internal AnimatableProperty[] m_AnimatableProperties = new AnimatableProperty[0];
|
||||||
|
|
||||||
|
@ -44,33 +62,44 @@ namespace Coffee.UIExtensions
|
||||||
[SerializeField]
|
[SerializeField]
|
||||||
private List<ParticleSystem> m_Particles = new List<ParticleSystem>();
|
private List<ParticleSystem> m_Particles = new List<ParticleSystem>();
|
||||||
|
|
||||||
[Tooltip("Mesh sharing.None: disable mesh sharing.\nAuto: automatically select Primary/Replica.\nPrimary: provides particle simulation results to the same group.\nPrimary Simulator: Primary, but do not render the particle (simulation only).\nReplica: render simulation results provided by the primary.")]
|
[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.")]
|
||||||
[SerializeField]
|
[SerializeField]
|
||||||
private MeshSharing m_MeshSharing = MeshSharing.None;
|
private MeshSharing m_MeshSharing = MeshSharing.None;
|
||||||
|
|
||||||
[Tooltip("Mesh sharing group ID. If non-zero is specified, particle simulation results are shared within the group.")]
|
[Tooltip("Mesh sharing group ID.\n" +
|
||||||
|
"If non-zero is specified, particle simulation results are shared within the group.")]
|
||||||
[SerializeField]
|
[SerializeField]
|
||||||
private int m_GroupId = 0;
|
private int m_GroupId;
|
||||||
|
|
||||||
[SerializeField]
|
[SerializeField]
|
||||||
private int m_GroupMaxId = 0;
|
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;
|
||||||
|
|
||||||
[SerializeField]
|
[SerializeField]
|
||||||
[Tooltip("The particles will be emitted at the ParticleSystem position.\nMove the UIParticle/ParticleSystem to move the particle.")]
|
[Tooltip("Transform.lossyScale (=world scale) is automatically set to (1, 1, 1), " +
|
||||||
private bool m_AbsoluteMode = false;
|
"to prevent the root-Canvas scale from affecting the hierarchy-scaled ParticleSystem.")]
|
||||||
|
private bool m_AutoScaling = true;
|
||||||
private List<UIParticleRenderer> m_Renderers = new List<UIParticleRenderer>();
|
|
||||||
|
|
||||||
#if !SERIALIZE_FIELD_MASKABLE
|
#if !SERIALIZE_FIELD_MASKABLE
|
||||||
[SerializeField] private bool m_Maskable = true;
|
[SerializeField]
|
||||||
|
private bool m_Maskable = true;
|
||||||
#endif
|
#endif
|
||||||
|
private readonly List<UIParticleRenderer> _renderers = new List<UIParticleRenderer>();
|
||||||
private DrivenRectTransformTracker _tracker;
|
|
||||||
private Camera _orthoCamera;
|
|
||||||
private int _groupId;
|
private int _groupId;
|
||||||
|
private Camera _orthoCamera;
|
||||||
|
private DrivenRectTransformTracker _tracker;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Should this graphic be considered a target for raycasting?
|
/// Should this graphic be considered a target for ray-casting?
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public override bool raycastTarget
|
public override bool raycastTarget
|
||||||
{
|
{
|
||||||
|
@ -79,7 +108,8 @@ namespace Coffee.UIExtensions
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Mesh sharing.None: disable mesh sharing.
|
/// Mesh sharing.
|
||||||
|
/// None: disable mesh sharing.
|
||||||
/// Auto: automatically select Primary/Replica.
|
/// Auto: automatically select Primary/Replica.
|
||||||
/// Primary: provides particle simulation results to the same group.
|
/// Primary: provides particle simulation results to the same group.
|
||||||
/// Primary Simulator: Primary, but do not render the particle (simulation only).
|
/// Primary Simulator: Primary, but do not render the particle (simulation only).
|
||||||
|
@ -92,7 +122,8 @@ namespace Coffee.UIExtensions
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <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>
|
/// </summary>
|
||||||
public int groupId
|
public int groupId
|
||||||
{
|
{
|
||||||
|
@ -102,7 +133,9 @@ namespace Coffee.UIExtensions
|
||||||
if (m_GroupId == value) return;
|
if (m_GroupId == value) return;
|
||||||
m_GroupId = value;
|
m_GroupId = value;
|
||||||
if (m_GroupId != m_GroupMaxId)
|
if (m_GroupId != m_GroupMaxId)
|
||||||
|
{
|
||||||
ResetGroupId();
|
ResetGroupId();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -118,14 +151,40 @@ namespace Coffee.UIExtensions
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Absolute particle position mode.
|
/// Particle position mode.
|
||||||
/// The particles will be emitted at the ParticleSystem position.
|
/// Relative: The particles will be emitted from the scaled position of the ParticleSystem.
|
||||||
/// Move the UIParticle/ParticleSystem to move the particle.
|
/// 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.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public bool absoluteMode
|
public bool absoluteMode
|
||||||
{
|
{
|
||||||
get { return m_AbsoluteMode; }
|
get { return m_PositionMode == PositionMode.Absolute; }
|
||||||
set { m_AbsoluteMode = value; }
|
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();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
internal bool useMeshSharing
|
internal bool useMeshSharing
|
||||||
|
@ -135,17 +194,33 @@ namespace Coffee.UIExtensions
|
||||||
|
|
||||||
internal bool isPrimary
|
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
|
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
|
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.Replica;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -178,12 +253,12 @@ namespace Coffee.UIExtensions
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
for (var i = 0; i < m_Renderers.Count; i++)
|
for (var i = 0; i < _renderers.Count; i++)
|
||||||
{
|
{
|
||||||
if (!m_Renderers[i] || !m_Renderers[i].material) continue;
|
var r = _renderers[i];
|
||||||
yield return m_Renderers[i].material;
|
if (!r || !r.material) continue;
|
||||||
|
yield return r.material;
|
||||||
}
|
}
|
||||||
yield break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -195,7 +270,78 @@ namespace Coffee.UIExtensions
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Paused.
|
/// Paused.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public bool isPaused { get; internal set; }
|
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()
|
||||||
|
{
|
||||||
|
m_IgnoreCanvasScaler = !m_AutoScaling;
|
||||||
|
m_AbsoluteMode = m_PositionMode == PositionMode.Absolute;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ISerializationCallbackReceiver.OnAfterDeserialize()
|
||||||
|
{
|
||||||
|
if (m_IgnoreCanvasScaler)
|
||||||
|
{
|
||||||
|
m_AutoScaling = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_AbsoluteMode)
|
||||||
|
{
|
||||||
|
m_PositionMode = PositionMode.Absolute;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public void Play()
|
public void Play()
|
||||||
{
|
{
|
||||||
|
@ -220,6 +366,24 @@ namespace Coffee.UIExtensions
|
||||||
isPaused = true;
|
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()
|
public void Clear()
|
||||||
{
|
{
|
||||||
particles.Exec(p => p.Clear());
|
particles.Exec(p => p.Clear());
|
||||||
|
@ -239,14 +403,10 @@ namespace Coffee.UIExtensions
|
||||||
{
|
{
|
||||||
var go = child.gameObject;
|
var go = child.gameObject;
|
||||||
go.SetActive(false);
|
go.SetActive(false);
|
||||||
if (!destroyOldParticles) continue;
|
if (destroyOldParticles)
|
||||||
|
{
|
||||||
#if UNITY_EDITOR
|
Misc.Destroy(go);
|
||||||
if (!Application.isPlaying)
|
}
|
||||||
DestroyImmediate(go);
|
|
||||||
else
|
|
||||||
#endif
|
|
||||||
Destroy(go);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var tr = instance.transform;
|
var tr = instance.transform;
|
||||||
|
@ -271,14 +431,17 @@ namespace Coffee.UIExtensions
|
||||||
private void RefreshParticles(GameObject root)
|
private void RefreshParticles(GameObject root)
|
||||||
{
|
{
|
||||||
if (!root) return;
|
if (!root) return;
|
||||||
root.GetComponentsInChildren(particles);
|
root.GetComponentsInChildren(true, particles);
|
||||||
particles.RemoveAll(x => x.GetComponentInParent<UIParticle>() != this);
|
particles.RemoveAll(x => x.GetComponentInParent<UIParticle>(true) != this);
|
||||||
|
|
||||||
foreach (var ps in particles)
|
for (var i = 0; i < particles.Count; i++)
|
||||||
{
|
{
|
||||||
|
var ps = particles[i];
|
||||||
var tsa = ps.textureSheetAnimation;
|
var tsa = ps.textureSheetAnimation;
|
||||||
if (tsa.mode == ParticleSystemAnimationMode.Sprites && tsa.uvChannelMask == 0)
|
if (tsa.mode == ParticleSystemAnimationMode.Sprites && tsa.uvChannelMask == 0)
|
||||||
|
{
|
||||||
tsa.uvChannelMask = UVChannelFlags.UV0;
|
tsa.uvChannelMask = UVChannelFlags.UV0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
RefreshParticles(particles);
|
RefreshParticles(particles);
|
||||||
|
@ -286,33 +449,42 @@ namespace Coffee.UIExtensions
|
||||||
|
|
||||||
public void RefreshParticles(List<ParticleSystem> particles)
|
public void RefreshParticles(List<ParticleSystem> particles)
|
||||||
{
|
{
|
||||||
GetComponentsInChildren(m_Renderers);
|
// #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);
|
||||||
|
}
|
||||||
|
|
||||||
var j = 0;
|
var j = 0;
|
||||||
for (var i = 0; i < particles.Count; i++)
|
for (var i = 0; i < particles.Count; i++)
|
||||||
{
|
{
|
||||||
if (!particles[i]) continue;
|
var ps = particles[i];
|
||||||
GetRenderer(j++).Set(this, particles[i], false);
|
if (!ps) continue;
|
||||||
if (particles[i].trails.enabled)
|
GetRenderer(j++).Set(this, ps, false);
|
||||||
|
if (ps.trails.enabled)
|
||||||
{
|
{
|
||||||
GetRenderer(j++).Set(this, particles[i], true);
|
GetRenderer(j++).Set(this, ps, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (; j < m_Renderers.Count; j++)
|
|
||||||
{
|
|
||||||
GetRenderer(j).Clear(j);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
internal void UpdateTransformScale()
|
internal void UpdateTransformScale()
|
||||||
{
|
{
|
||||||
//var newScale = Vector3.one;
|
parentScale = transform.parent.lossyScale;
|
||||||
//if (uiScaling)
|
if (!autoScaling) return;
|
||||||
//{
|
|
||||||
// newScale = transform.parent.lossyScale.Inverse();
|
var newScale = parentScale.Inverse();
|
||||||
//}
|
|
||||||
var newScale = transform.parent.lossyScale.Inverse();
|
|
||||||
if (transform.localScale != newScale)
|
if (transform.localScale != newScale)
|
||||||
{
|
{
|
||||||
transform.localScale = newScale;
|
transform.localScale = newScale;
|
||||||
|
@ -323,9 +495,10 @@ namespace Coffee.UIExtensions
|
||||||
{
|
{
|
||||||
if (!isActiveAndEnabled) return;
|
if (!isActiveAndEnabled) return;
|
||||||
|
|
||||||
foreach (var rend in m_Renderers)
|
for (var i = 0; i < _renderers.Count; i++)
|
||||||
{
|
{
|
||||||
if (!rend)
|
var r = _renderers[i];
|
||||||
|
if (!r)
|
||||||
{
|
{
|
||||||
RefreshParticles(particles);
|
RefreshParticles(particles);
|
||||||
break;
|
break;
|
||||||
|
@ -333,67 +506,29 @@ namespace Coffee.UIExtensions
|
||||||
}
|
}
|
||||||
|
|
||||||
var bakeCamera = GetBakeCamera();
|
var bakeCamera = GetBakeCamera();
|
||||||
for (var i = 0; i < m_Renderers.Count; i++)
|
for (var i = 0; i < _renderers.Count; i++)
|
||||||
{
|
{
|
||||||
if (!m_Renderers[i]) continue;
|
var r = _renderers[i];
|
||||||
m_Renderers[i].UpdateMesh(bakeCamera);
|
if (!r) continue;
|
||||||
|
r.UpdateMesh(bakeCamera);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
internal void UpdateParticleCount()
|
internal void UpdateParticleCount()
|
||||||
{
|
{
|
||||||
for (var i = 0; i < m_Renderers.Count; i++)
|
for (var i = 0; i < _renderers.Count; i++)
|
||||||
{
|
{
|
||||||
if (!m_Renderers[i]) continue;
|
var r = _renderers[i];
|
||||||
m_Renderers[i].UpdateParticleCount();
|
if (!r) continue;
|
||||||
|
r.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()
|
internal void ResetGroupId()
|
||||||
{
|
{
|
||||||
if (m_GroupId == m_GroupMaxId)
|
_groupId = m_GroupId == m_GroupMaxId
|
||||||
{
|
? m_GroupId
|
||||||
_groupId = m_GroupId;
|
: Random.Range(m_GroupId, m_GroupMaxId + 1);
|
||||||
}
|
|
||||||
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()
|
protected override void UpdateMaterial()
|
||||||
|
@ -407,43 +542,42 @@ namespace Coffee.UIExtensions
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Callback for when properties have been changed by animation.
|
|
||||||
/// </summary>
|
|
||||||
protected override void OnDidApplyAnimationProperties()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
private void UpdateRendererMaterial()
|
private void UpdateRendererMaterial()
|
||||||
{
|
{
|
||||||
for (var i = 0; i < m_Renderers.Count; i++)
|
for (var i = 0; i < _renderers.Count; i++)
|
||||||
{
|
{
|
||||||
if (!m_Renderers[i]) continue;
|
var r = _renderers[i];
|
||||||
m_Renderers[i].maskable = maskable;
|
if (!r) continue;
|
||||||
m_Renderers[i].SetMaterialDirty();
|
r.maskable = maskable;
|
||||||
|
r.SetMaterialDirty();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
internal UIParticleRenderer GetRenderer(int index)
|
internal UIParticleRenderer GetRenderer(int index)
|
||||||
{
|
{
|
||||||
if (m_Renderers.Count <= index)
|
if (_renderers.Count <= index)
|
||||||
{
|
{
|
||||||
m_Renderers.Add(UIParticleRenderer.AddRenderer(this, index));
|
_renderers.Add(UIParticleRenderer.AddRenderer(this, index));
|
||||||
}
|
}
|
||||||
if (!m_Renderers[index])
|
|
||||||
|
if (!_renderers[index])
|
||||||
{
|
{
|
||||||
m_Renderers[index] = UIParticleRenderer.AddRenderer(this, index);
|
_renderers[index] = UIParticleRenderer.AddRenderer(this, index);
|
||||||
}
|
}
|
||||||
return m_Renderers[index];
|
|
||||||
|
return _renderers[index];
|
||||||
}
|
}
|
||||||
|
|
||||||
private Camera GetBakeCamera()
|
private Camera GetBakeCamera()
|
||||||
{
|
{
|
||||||
if (!canvas) return Camera.main;
|
if (!canvas) return Camera.main;
|
||||||
|
|
||||||
// World camera.
|
// Render mode is not ScreenSpaceOverlay, use world camera.
|
||||||
var root = canvas.rootCanvas;
|
var root = canvas.rootCanvas;
|
||||||
if (root.renderMode != RenderMode.ScreenSpaceOverlay) return root.worldCamera ? root.worldCamera : Camera.main;
|
if (root.renderMode != RenderMode.ScreenSpaceOverlay)
|
||||||
|
{
|
||||||
|
return root.worldCamera ? root.worldCamera : Camera.main;
|
||||||
|
}
|
||||||
|
|
||||||
// Create ortho-camera.
|
// Create ortho-camera.
|
||||||
if (!_orthoCamera)
|
if (!_orthoCamera)
|
||||||
|
@ -451,10 +585,7 @@ namespace Coffee.UIExtensions
|
||||||
_orthoCamera = GetComponentInChildren<Camera>();
|
_orthoCamera = GetComponentInChildren<Camera>();
|
||||||
if (!_orthoCamera)
|
if (!_orthoCamera)
|
||||||
{
|
{
|
||||||
var go = new GameObject("UIParticleOverlayCamera")
|
var go = new GameObject("UIParticleOverlayCamera") { hideFlags = HideFlags.DontSave };
|
||||||
{
|
|
||||||
hideFlags = HideFlags.DontSave,
|
|
||||||
};
|
|
||||||
go.SetActive(false);
|
go.SetActive(false);
|
||||||
go.transform.SetParent(transform, false);
|
go.transform.SetParent(transform, false);
|
||||||
_orthoCamera = go.AddComponent<Camera>();
|
_orthoCamera = go.AddComponent<Camera>();
|
||||||
|
@ -462,7 +593,7 @@ namespace Coffee.UIExtensions
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
var size = ((RectTransform)root.transform).rect.size;
|
var size = ((RectTransform)root.transform).rect.size;
|
||||||
_orthoCamera.orthographicSize = Mathf.Max(size.x, size.y) * root.scaleFactor;
|
_orthoCamera.orthographicSize = Mathf.Max(size.x, size.y) * root.scaleFactor;
|
||||||
_orthoCamera.transform.SetPositionAndRotation(new Vector3(0, 0, -1000), Quaternion.identity);
|
_orthoCamera.transform.SetPositionAndRotation(new Vector3(0, 0, -1000), Quaternion.identity);
|
||||||
|
@ -471,5 +602,17 @@ namespace Coffee.UIExtensions
|
||||||
|
|
||||||
return _orthoCamera;
|
return _orthoCamera;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void UpdateTracker()
|
||||||
|
{
|
||||||
|
if (!enabled || !autoScaling)
|
||||||
|
{
|
||||||
|
_tracker.Clear();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_tracker.Add(this, rectTransform, DrivenTransformProperties.Scale);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
using UnityEngine;
|
using System;
|
||||||
using Coffee.UIParticleExtensions;
|
using Coffee.UIParticleExtensions;
|
||||||
|
using UnityEngine;
|
||||||
using UnityEngine.Events;
|
using UnityEngine.Events;
|
||||||
using System;
|
|
||||||
|
|
||||||
namespace Coffee.UIExtensions
|
namespace Coffee.UIExtensions
|
||||||
{
|
{
|
||||||
|
@ -12,7 +12,13 @@ namespace Coffee.UIExtensions
|
||||||
{
|
{
|
||||||
Linear,
|
Linear,
|
||||||
Smooth,
|
Smooth,
|
||||||
Sphere,
|
Sphere
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum UpdateMode
|
||||||
|
{
|
||||||
|
Normal,
|
||||||
|
UnscaledTime
|
||||||
}
|
}
|
||||||
|
|
||||||
[SerializeField]
|
[SerializeField]
|
||||||
|
@ -24,7 +30,7 @@ namespace Coffee.UIExtensions
|
||||||
|
|
||||||
[Range(0f, 0.95f)]
|
[Range(0f, 0.95f)]
|
||||||
[SerializeField]
|
[SerializeField]
|
||||||
private float m_DelayRate = 0;
|
private float m_DelayRate;
|
||||||
|
|
||||||
[Range(0.001f, 100f)]
|
[Range(0.001f, 100f)]
|
||||||
[SerializeField]
|
[SerializeField]
|
||||||
|
@ -33,73 +39,81 @@ namespace Coffee.UIExtensions
|
||||||
[SerializeField]
|
[SerializeField]
|
||||||
private Movement m_Movement;
|
private Movement m_Movement;
|
||||||
|
|
||||||
|
[SerializeField]
|
||||||
|
private UpdateMode m_UpdateMode;
|
||||||
|
|
||||||
[SerializeField]
|
[SerializeField]
|
||||||
private UnityEvent m_OnAttracted;
|
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
|
public float delay
|
||||||
{
|
{
|
||||||
get
|
get { return m_DelayRate; }
|
||||||
{
|
set { m_DelayRate = value; }
|
||||||
return m_DelayRate;
|
|
||||||
}
|
|
||||||
set
|
|
||||||
{
|
|
||||||
m_DelayRate = value;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public float maxSpeed
|
public float maxSpeed
|
||||||
{
|
{
|
||||||
get
|
get { return m_MaxSpeed; }
|
||||||
{
|
set { m_MaxSpeed = value; }
|
||||||
return m_MaxSpeed;
|
|
||||||
}
|
|
||||||
set
|
|
||||||
{
|
|
||||||
m_MaxSpeed = value;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public Movement movement
|
public Movement movement
|
||||||
{
|
{
|
||||||
get
|
get { return m_Movement; }
|
||||||
{
|
set { m_Movement = value; }
|
||||||
return m_Movement;
|
|
||||||
}
|
|
||||||
set
|
|
||||||
{
|
|
||||||
m_Movement = value;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public ParticleSystem particleSystem
|
public UpdateMode updateMode
|
||||||
{
|
{
|
||||||
get
|
get { return m_UpdateMode; }
|
||||||
{
|
set { m_UpdateMode = value; }
|
||||||
return m_ParticleSystem;
|
}
|
||||||
}
|
|
||||||
|
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
|
set
|
||||||
{
|
{
|
||||||
m_ParticleSystem = value;
|
m_ParticleSystem = value;
|
||||||
if (!ApplyParticleSystem()) return;
|
ApplyParticleSystem();
|
||||||
enabled = true;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private UIParticle _uiParticle;
|
|
||||||
|
|
||||||
private void OnEnable()
|
private void OnEnable()
|
||||||
{
|
{
|
||||||
if (!ApplyParticleSystem()) return;
|
ApplyParticleSystem();
|
||||||
UIParticleUpdater.Register(this);
|
UIParticleUpdater.Register(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnDisable()
|
private void OnDisable()
|
||||||
{
|
{
|
||||||
_uiParticle = null;
|
|
||||||
UIParticleUpdater.Unregister(this);
|
UIParticleUpdater.Unregister(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void OnDestroy()
|
||||||
|
{
|
||||||
|
_uiParticle = null;
|
||||||
|
m_ParticleSystem = null;
|
||||||
|
}
|
||||||
|
|
||||||
internal void Attract()
|
internal void Attract()
|
||||||
{
|
{
|
||||||
if (m_ParticleSystem == null) return;
|
if (m_ParticleSystem == null) return;
|
||||||
|
@ -131,6 +145,7 @@ namespace Coffee.UIExtensions
|
||||||
Debug.LogException(e);
|
Debug.LogException(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -157,36 +172,51 @@ namespace Coffee.UIExtensions
|
||||||
var psPos = m_ParticleSystem.transform.position;
|
var psPos = m_ParticleSystem.transform.position;
|
||||||
var attractorPos = transform.position;
|
var attractorPos = transform.position;
|
||||||
var dstPos = attractorPos;
|
var dstPos = attractorPos;
|
||||||
if (m_ParticleSystem.main.simulationSpace == ParticleSystemSimulationSpace.Local)
|
var isLocalSpace = m_ParticleSystem.IsLocalSpace();
|
||||||
|
|
||||||
|
if (isLocalSpace)
|
||||||
{
|
{
|
||||||
dstPos = m_ParticleSystem.transform.InverseTransformPoint(dstPos);
|
dstPos = m_ParticleSystem.transform.InverseTransformPoint(dstPos);
|
||||||
if (isUI)
|
|
||||||
{
|
|
||||||
dstPos = dstPos.GetScaled(_uiParticle.transform.localScale, _uiParticle.scale3D.Inverse());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
|
||||||
|
if (isUI)
|
||||||
{
|
{
|
||||||
#if UNITY_EDITOR
|
var inverseScale = _uiParticle.parentScale.Inverse();
|
||||||
if (!Application.isPlaying && isUI)
|
dstPos = dstPos.GetScaled(inverseScale, _uiParticle.scale3D.Inverse());
|
||||||
|
|
||||||
|
// Relative mode
|
||||||
|
if (_uiParticle.positionMode == UIParticle.PositionMode.Relative)
|
||||||
{
|
{
|
||||||
var diff = dstPos - psPos;
|
var diff = _uiParticle.transform.position - psPos;
|
||||||
diff = diff.GetScaled(_uiParticle.transform.localScale, _uiParticle.scale3D.Inverse());
|
diff.Scale(_uiParticle.scale3D - inverseScale);
|
||||||
return psPos + diff;
|
diff.Scale(_uiParticle.scale3D.Inverse());
|
||||||
|
dstPos += diff;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if UNITY_EDITOR
|
||||||
|
if (!Application.isPlaying && !isLocalSpace)
|
||||||
|
{
|
||||||
|
dstPos += psPos - psPos.GetScaled(inverseScale, _uiParticle.scale3D.Inverse());
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
if (isUI)
|
|
||||||
{
|
|
||||||
dstPos.Scale(_uiParticle.transform.localScale);
|
|
||||||
dstPos.Scale(_uiParticle.scale3D.Inverse());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return dstPos;
|
return dstPos;
|
||||||
}
|
}
|
||||||
|
|
||||||
private Vector3 GetAttractedPosition(Vector3 current, Vector3 target, float duration, float time)
|
private Vector3 GetAttractedPosition(Vector3 current, Vector3 target, float duration, float time)
|
||||||
{
|
{
|
||||||
var speed = m_MaxSpeed;
|
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)
|
switch (m_Movement)
|
||||||
{
|
{
|
||||||
case Movement.Linear:
|
case Movement.Linear:
|
||||||
|
@ -203,22 +233,26 @@ namespace Coffee.UIExtensions
|
||||||
return Vector3.MoveTowards(current, target, speed);
|
return Vector3.MoveTowards(current, target, speed);
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool ApplyParticleSystem()
|
private void ApplyParticleSystem()
|
||||||
{
|
{
|
||||||
|
_uiParticle = null;
|
||||||
if (m_ParticleSystem == null)
|
if (m_ParticleSystem == null)
|
||||||
{
|
{
|
||||||
Debug.LogError("No particle system attached to particle attractor script", this);
|
#if UNITY_EDITOR
|
||||||
enabled = false;
|
if (Application.isPlaying)
|
||||||
return false;
|
#endif
|
||||||
|
{
|
||||||
|
Debug.LogError("No particle system attached to particle attractor script", this);
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
_uiParticle = m_ParticleSystem.GetComponentInParent<UIParticle>();
|
_uiParticle = m_ParticleSystem.GetComponentInParent<UIParticle>(true);
|
||||||
if (_uiParticle && !_uiParticle.particles.Contains(m_ParticleSystem))
|
if (_uiParticle && !_uiParticle.particles.Contains(m_ParticleSystem))
|
||||||
{
|
{
|
||||||
_uiParticle = null;
|
_uiParticle = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,9 +1,10 @@
|
||||||
using UnityEngine;
|
using System;
|
||||||
using UnityEngine.UI;
|
using System.Collections.Generic;
|
||||||
using Coffee.UIParticleExtensions;
|
using Coffee.UIParticleExtensions;
|
||||||
|
using UnityEngine;
|
||||||
using UnityEngine.Profiling;
|
using UnityEngine.Profiling;
|
||||||
using UnityEngine.Rendering;
|
using UnityEngine.Rendering;
|
||||||
using System.Collections.Generic;
|
using UnityEngine.UI;
|
||||||
|
|
||||||
namespace Coffee.UIExtensions
|
namespace Coffee.UIExtensions
|
||||||
{
|
{
|
||||||
|
@ -13,43 +14,36 @@ namespace Coffee.UIExtensions
|
||||||
[AddComponentMenu("")]
|
[AddComponentMenu("")]
|
||||||
internal class UIParticleRenderer : MaskableGraphic
|
internal class UIParticleRenderer : MaskableGraphic
|
||||||
{
|
{
|
||||||
private static readonly CombineInstance[] s_CombineInstances = new CombineInstance[] { new CombineInstance() };
|
private static readonly CombineInstance[] s_CombineInstances = { new CombineInstance() };
|
||||||
private static readonly List<Material> s_Materials = new List<Material>(2);
|
private static readonly List<Material> s_Materials = new List<Material>(2);
|
||||||
private static MaterialPropertyBlock s_Mpb;
|
private static MaterialPropertyBlock s_Mpb;
|
||||||
private static readonly List<UIParticleRenderer> s_Renderers = new List<UIParticleRenderer>();
|
private static readonly List<UIParticleRenderer> s_Renderers = new List<UIParticleRenderer>();
|
||||||
private static readonly Vector3[] s_Corners = new Vector3[4];
|
private static readonly Vector3[] s_Corners = new Vector3[4];
|
||||||
|
private Material _currentMaterialForRendering;
|
||||||
private ParticleSystemRenderer _renderer;
|
private bool _delay;
|
||||||
private ParticleSystem _particleSystem;
|
|
||||||
private int _prevParticleCount = 0;
|
|
||||||
private UIParticle _parent;
|
|
||||||
private int _index;
|
private int _index;
|
||||||
private bool _isTrail;
|
private bool _isTrail;
|
||||||
private Material _modifiedMaterial;
|
|
||||||
private Vector3 _prevScale;
|
|
||||||
private Vector3 _prevPsPos;
|
|
||||||
private Vector2Int _prevScreenSize;
|
|
||||||
private bool _delay = false;
|
|
||||||
private bool _prewarm = false;
|
|
||||||
private Material _currentMaterialForRendering;
|
|
||||||
private Bounds _lastBounds;
|
private Bounds _lastBounds;
|
||||||
|
private Material _modifiedMaterial;
|
||||||
|
private UIParticle _parent;
|
||||||
|
private ParticleSystem _particleSystem;
|
||||||
|
private int _prevParticleCount;
|
||||||
|
private Vector3 _prevPsPos;
|
||||||
|
private Vector3 _prevScale;
|
||||||
|
private Vector2Int _prevScreenSize;
|
||||||
|
private bool _prewarm;
|
||||||
|
private ParticleSystemRenderer _renderer;
|
||||||
|
|
||||||
public override Texture mainTexture
|
public override Texture mainTexture
|
||||||
{
|
{
|
||||||
get
|
get { return _isTrail ? null : _particleSystem.GetTextureForSprite(); }
|
||||||
{
|
|
||||||
return _isTrail ? null : _particleSystem.GetTextureForSprite();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public override bool raycastTarget
|
public override bool raycastTarget
|
||||||
{
|
{
|
||||||
get
|
get { return false; }
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private Rect rootCanvasRect
|
private Rect rootCanvasRect
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
|
@ -62,32 +56,103 @@ namespace Coffee.UIExtensions
|
||||||
{
|
{
|
||||||
var worldToLocalMatrix = canvas.rootCanvas.transform.worldToLocalMatrix;
|
var worldToLocalMatrix = canvas.rootCanvas.transform.worldToLocalMatrix;
|
||||||
for (var i = 0; i < 4; ++i)
|
for (var i = 0; i < 4; ++i)
|
||||||
|
{
|
||||||
s_Corners[i] = worldToLocalMatrix.MultiplyPoint(s_Corners[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)
|
for (var i = 1; i < 4; ++i)
|
||||||
{
|
{
|
||||||
if (s_Corners[i].x < corner1.x)
|
if (s_Corners[i].x < corner1.x)
|
||||||
|
{
|
||||||
corner1.x = s_Corners[i].x;
|
corner1.x = s_Corners[i].x;
|
||||||
|
}
|
||||||
else if (s_Corners[i].x > corner2.x)
|
else if (s_Corners[i].x > corner2.x)
|
||||||
|
{
|
||||||
corner2.x = s_Corners[i].x;
|
corner2.x = s_Corners[i].x;
|
||||||
|
}
|
||||||
|
|
||||||
if (s_Corners[i].y < corner1.y)
|
if (s_Corners[i].y < corner1.y)
|
||||||
|
{
|
||||||
corner1.y = s_Corners[i].y;
|
corner1.y = s_Corners[i].y;
|
||||||
|
}
|
||||||
else if (s_Corners[i].y > corner2.y)
|
else if (s_Corners[i].y > corner2.y)
|
||||||
|
{
|
||||||
corner2.y = s_Corners[i].y;
|
corner2.y = s_Corners[i].y;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return new Rect(corner1, corner2 - corner1);
|
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)
|
public static UIParticleRenderer AddRenderer(UIParticle parent, int index)
|
||||||
{
|
{
|
||||||
// Create renderer object.
|
// Create renderer object.
|
||||||
var go = new GameObject("UIParticleRenderer", typeof(UIParticleRenderer))
|
var go = new GameObject("UIParticleRenderer", typeof(UIParticleRenderer))
|
||||||
{
|
{
|
||||||
hideFlags = HideFlags.DontSave,
|
hideFlags = HideFlags.DontSave,
|
||||||
layer = parent.gameObject.layer,
|
layer = parent.gameObject.layer
|
||||||
};
|
};
|
||||||
|
|
||||||
// Set parent.
|
// Set parent.
|
||||||
|
@ -112,11 +177,16 @@ namespace Coffee.UIExtensions
|
||||||
{
|
{
|
||||||
_currentMaterialForRendering = null;
|
_currentMaterialForRendering = null;
|
||||||
|
|
||||||
if (!IsActive()) return baseMaterial;
|
if (!IsActive() || !_parent)
|
||||||
|
{
|
||||||
|
ModifiedMaterial.Remove(_modifiedMaterial);
|
||||||
|
_modifiedMaterial = null;
|
||||||
|
return baseMaterial;
|
||||||
|
}
|
||||||
|
|
||||||
var modifiedMaterial = base.GetModifiedMaterial(baseMaterial);
|
var modifiedMaterial = base.GetModifiedMaterial(baseMaterial);
|
||||||
|
|
||||||
//
|
//
|
||||||
var texture = mainTexture;
|
var texture = mainTexture;
|
||||||
if (texture == null && _parent.m_AnimatableProperties.Length == 0)
|
if (texture == null && _parent.m_AnimatableProperties.Length == 0)
|
||||||
{
|
{
|
||||||
|
@ -134,50 +204,28 @@ namespace Coffee.UIExtensions
|
||||||
return modifiedMaterial;
|
return modifiedMaterial;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Clear(int index = -1)
|
public void Set(UIParticle parent, ParticleSystem ps, bool isTrail)
|
||||||
{
|
|
||||||
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;
|
_parent = parent;
|
||||||
maskable = parent.maskable;
|
maskable = parent.maskable;
|
||||||
|
|
||||||
gameObject.layer = parent.gameObject.layer;
|
gameObject.layer = parent.gameObject.layer;
|
||||||
|
|
||||||
_particleSystem = particleSystem;
|
_particleSystem = ps;
|
||||||
|
_prewarm = _particleSystem.main.prewarm;
|
||||||
|
|
||||||
#if UNITY_EDITOR
|
#if UNITY_EDITOR
|
||||||
if (Application.isPlaying)
|
if (Application.isPlaying)
|
||||||
#endif
|
#endif
|
||||||
if (_particleSystem.isPlaying)
|
|
||||||
{
|
{
|
||||||
_particleSystem.Clear();
|
if (_particleSystem.isPlaying || _prewarm)
|
||||||
_particleSystem.Pause();
|
{
|
||||||
|
_particleSystem.Clear();
|
||||||
|
_particleSystem.Pause();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
_prewarm = _particleSystem.main.prewarm;
|
|
||||||
|
|
||||||
_renderer = particleSystem.GetComponent<ParticleSystemRenderer>();
|
_renderer = ps.GetComponent<ParticleSystemRenderer>();
|
||||||
_renderer.enabled = false;
|
_renderer.enabled = false;
|
||||||
|
|
||||||
//_emitter = emitter;
|
//_emitter = emitter;
|
||||||
|
@ -188,9 +236,11 @@ namespace Coffee.UIExtensions
|
||||||
s_Materials.Clear();
|
s_Materials.Clear();
|
||||||
|
|
||||||
// Support sprite.
|
// Support sprite.
|
||||||
var tsa = particleSystem.textureSheetAnimation;
|
var tsa = ps.textureSheetAnimation;
|
||||||
if (tsa.mode == ParticleSystemAnimationMode.Sprites && tsa.uvChannelMask == 0)
|
if (tsa.mode == ParticleSystemAnimationMode.Sprites && tsa.uvChannelMask == 0)
|
||||||
|
{
|
||||||
tsa.uvChannelMask = UVChannelFlags.UV0;
|
tsa.uvChannelMask = UVChannelFlags.UV0;
|
||||||
|
}
|
||||||
|
|
||||||
_prevScale = GetWorldScale();
|
_prevScale = GetWorldScale();
|
||||||
_prevPsPos = _particleSystem.transform.position;
|
_prevPsPos = _particleSystem.transform.position;
|
||||||
|
@ -207,15 +257,17 @@ namespace Coffee.UIExtensions
|
||||||
{
|
{
|
||||||
// No particle to render: Clear mesh.
|
// No particle to render: Clear mesh.
|
||||||
if (
|
if (
|
||||||
!isActiveAndEnabled || !_particleSystem || !_parent || !canvasRenderer || !canvas || !bakeCamera
|
!isActiveAndEnabled || !_particleSystem || !_parent
|
||||||
|
|| !canvasRenderer || !canvas || !bakeCamera
|
||||||
|| _parent.meshSharing == UIParticle.MeshSharing.Replica
|
|| _parent.meshSharing == UIParticle.MeshSharing.Replica
|
||||||
|| !transform.lossyScale.GetScaled(_parent.scale3D).IsVisible() // Scale is not visible.
|
|| !transform.lossyScale.GetScaled(_parent.scale3D).IsVisible() // Scale is not visible.
|
||||||
|| (!_particleSystem.IsAlive() && !_particleSystem.isPlaying) // No particle.
|
|| (!_particleSystem.IsAlive() && !_particleSystem.isPlaying) // No particle.
|
||||||
|| (_isTrail && !_particleSystem.trails.enabled) // Trail, but it is not enabled.
|
|| (_isTrail && !_particleSystem.trails.enabled) // Trail, but it is not enabled.
|
||||||
#if UNITY_2018_3_OR_NEWER
|
#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
|
#endif
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
Profiler.BeginSample("[UIParticleRenderer] Clear Mesh");
|
Profiler.BeginSample("[UIParticleRenderer] Clear Mesh");
|
||||||
workerMesh.Clear();
|
workerMesh.Clear();
|
||||||
|
@ -251,20 +303,25 @@ namespace Coffee.UIExtensions
|
||||||
}
|
}
|
||||||
|
|
||||||
// When the ParticleSystem simulation is complete, stop it.
|
// 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);
|
_particleSystem.Stop(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_prevScale = scale;
|
_prevScale = scale;
|
||||||
_prevPsPos = psPos;
|
_prevPsPos = psPos;
|
||||||
_delay = false;
|
_delay = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
Profiler.EndSample();
|
Profiler.EndSample();
|
||||||
|
|
||||||
// Bake mesh.
|
// Bake mesh.
|
||||||
Profiler.BeginSample("[UIParticleRenderer] Bake Mesh");
|
Profiler.BeginSample("[UIParticleRenderer] Bake Mesh");
|
||||||
if (_isTrail && _parent.canSimulate)
|
if (_isTrail && _parent.canSimulate && 0 < s_CombineInstances[0].mesh.vertexCount)
|
||||||
{
|
{
|
||||||
_renderer.BakeTrailsMesh(s_CombineInstances[0].mesh, bakeCamera, true);
|
_renderer.BakeTrailsMesh(s_CombineInstances[0].mesh, bakeCamera, true);
|
||||||
}
|
}
|
||||||
|
@ -276,21 +333,41 @@ namespace Coffee.UIExtensions
|
||||||
{
|
{
|
||||||
s_CombineInstances[0].mesh.Clear(false);
|
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();
|
Profiler.EndSample();
|
||||||
|
|
||||||
// Combine mesh to transform. ([ParticleSystem local ->] world -> renderer local)
|
// Combine mesh to transform. ([ParticleSystem local ->] world -> renderer local)
|
||||||
Profiler.BeginSample("[UIParticleRenderer] Combine Mesh");
|
Profiler.BeginSample("[UIParticleRenderer] Combine Mesh");
|
||||||
if (_parent.canSimulate)
|
if (_parent.canSimulate)
|
||||||
{
|
{
|
||||||
if (_parent.absoluteMode)
|
if (_parent.positionMode == UIParticle.PositionMode.Absolute)
|
||||||
{
|
{
|
||||||
s_CombineInstances[0].transform = canvasRenderer.transform.worldToLocalMatrix * GetWorldMatrix(psPos, scale);
|
s_CombineInstances[0].transform =
|
||||||
|
canvasRenderer.transform.worldToLocalMatrix
|
||||||
|
* GetWorldMatrix(psPos, scale);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
var diff = _particleSystem.transform.position - _parent.transform.position;
|
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.CombineMeshes(s_CombineInstances, true, true);
|
||||||
|
|
||||||
workerMesh.RecalculateBounds();
|
workerMesh.RecalculateBounds();
|
||||||
|
@ -304,6 +381,7 @@ namespace Coffee.UIExtensions
|
||||||
workerMesh.bounds = bounds;
|
workerMesh.bounds = bounds;
|
||||||
_lastBounds = bounds;
|
_lastBounds = bounds;
|
||||||
}
|
}
|
||||||
|
|
||||||
Profiler.EndSample();
|
Profiler.EndSample();
|
||||||
|
|
||||||
|
|
||||||
|
@ -316,7 +394,7 @@ namespace Coffee.UIExtensions
|
||||||
|
|
||||||
// Set mesh to the CanvasRenderer.
|
// Set mesh to the CanvasRenderer.
|
||||||
Profiler.BeginSample("[UIParticleRenderer] Set Mesh");
|
Profiler.BeginSample("[UIParticleRenderer] Set Mesh");
|
||||||
for (int i = 0; i < s_Renderers.Count; i++)
|
for (var i = 0; i < s_Renderers.Count; i++)
|
||||||
{
|
{
|
||||||
if (s_Renderers[i] == this) continue;
|
if (s_Renderers[i] == this) continue;
|
||||||
s_Renderers[i].canvasRenderer.SetMesh(workerMesh);
|
s_Renderers[i].canvasRenderer.SetMesh(workerMesh);
|
||||||
|
@ -327,6 +405,7 @@ namespace Coffee.UIExtensions
|
||||||
{
|
{
|
||||||
workerMesh.Clear();
|
workerMesh.Clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
canvasRenderer.SetMesh(workerMesh);
|
canvasRenderer.SetMesh(workerMesh);
|
||||||
Profiler.EndSample();
|
Profiler.EndSample();
|
||||||
|
|
||||||
|
@ -339,7 +418,8 @@ namespace Coffee.UIExtensions
|
||||||
{
|
{
|
||||||
_currentMaterialForRendering = materialForRendering;
|
_currentMaterialForRendering = materialForRendering;
|
||||||
}
|
}
|
||||||
for (int i = 0; i < s_Renderers.Count; i++)
|
|
||||||
|
for (var i = 0; i < s_Renderers.Count; i++)
|
||||||
{
|
{
|
||||||
if (s_Renderers[i] == this) continue;
|
if (s_Renderers[i] == this) continue;
|
||||||
|
|
||||||
|
@ -347,6 +427,7 @@ namespace Coffee.UIExtensions
|
||||||
s_Renderers[i].canvasRenderer.SetMaterial(_currentMaterialForRendering, 0);
|
s_Renderers[i].canvasRenderer.SetMaterial(_currentMaterialForRendering, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Profiler.EndSample();
|
Profiler.EndSample();
|
||||||
|
|
||||||
s_Renderers.Clear();
|
s_Renderers.Clear();
|
||||||
|
@ -358,42 +439,20 @@ namespace Coffee.UIExtensions
|
||||||
_prevParticleCount = _particleSystem.particleCount;
|
_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>
|
/// <summary>
|
||||||
/// Call to update the geometry of the Graphic onto the CanvasRenderer.
|
/// Call to update the geometry of the Graphic onto the CanvasRenderer.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
protected override void UpdateGeometry()
|
protected override void UpdateGeometry()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void Cull(Rect clipRect, bool validRect)
|
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;
|
if (canvasRenderer.cull == cull) return;
|
||||||
|
|
||||||
canvasRenderer.cull = cull;
|
canvasRenderer.cull = cull;
|
||||||
UISystemProfilerApi.AddMarker("MaskableGraphic.cullingChanged", this);
|
UISystemProfilerApi.AddMarker("MaskableGraphic.cullingChanged", this);
|
||||||
onCullStateChanged.Invoke(cull);
|
onCullStateChanged.Invoke(cull);
|
||||||
|
@ -403,16 +462,7 @@ namespace Coffee.UIExtensions
|
||||||
private Vector3 GetWorldScale()
|
private Vector3 GetWorldScale()
|
||||||
{
|
{
|
||||||
Profiler.BeginSample("[UIParticleRenderer] GetWorldScale");
|
Profiler.BeginSample("[UIParticleRenderer] GetWorldScale");
|
||||||
var scale = _parent.scale3D;
|
var scale = _parent.scale3D.GetScaled(_parent.parentScale);
|
||||||
//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();
|
Profiler.EndSample();
|
||||||
return scale;
|
return scale;
|
||||||
}
|
}
|
||||||
|
@ -432,8 +482,8 @@ namespace Coffee.UIExtensions
|
||||||
{
|
{
|
||||||
case ParticleSystemSimulationSpace.World:
|
case ParticleSystemSimulationSpace.World:
|
||||||
return Matrix4x4.Translate(psPos)
|
return Matrix4x4.Translate(psPos)
|
||||||
* Matrix4x4.Scale(scale)
|
* Matrix4x4.Scale(scale)
|
||||||
* Matrix4x4.Translate(-psPos);
|
* Matrix4x4.Translate(-psPos);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -442,17 +492,17 @@ namespace Coffee.UIExtensions
|
||||||
{
|
{
|
||||||
case ParticleSystemSimulationSpace.Local:
|
case ParticleSystemSimulationSpace.Local:
|
||||||
return Matrix4x4.Translate(psPos)
|
return Matrix4x4.Translate(psPos)
|
||||||
* Matrix4x4.Scale(scale);
|
* Matrix4x4.Scale(scale);
|
||||||
case ParticleSystemSimulationSpace.World:
|
case ParticleSystemSimulationSpace.World:
|
||||||
return Matrix4x4.Scale(scale);
|
return Matrix4x4.Scale(scale);
|
||||||
case ParticleSystemSimulationSpace.Custom:
|
case ParticleSystemSimulationSpace.Custom:
|
||||||
return Matrix4x4.Translate(_particleSystem.main.customSimulationSpace.position.GetScaled(scale))
|
return Matrix4x4.Translate(_particleSystem.main.customSimulationSpace.position.GetScaled(scale))
|
||||||
//* Matrix4x4.Translate(wpos)
|
//* Matrix4x4.Translate(wpos)
|
||||||
* Matrix4x4.Scale(scale)
|
* Matrix4x4.Scale(scale)
|
||||||
//* Matrix4x4.Translate(-wpos)
|
//* Matrix4x4.Translate(-wpos)
|
||||||
;
|
;
|
||||||
default:
|
default:
|
||||||
throw new System.NotSupportedException();
|
throw new NotSupportedException();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -464,8 +514,9 @@ namespace Coffee.UIExtensions
|
||||||
private void ResolveResolutionChange(Vector3 psPos, Vector3 scale)
|
private void ResolveResolutionChange(Vector3 psPos, Vector3 scale)
|
||||||
{
|
{
|
||||||
var screenSize = new Vector2Int(Screen.width, Screen.height);
|
var screenSize = new Vector2Int(Screen.width, Screen.height);
|
||||||
//if ((_prevScreenSize != screenSize || _prevScale != scale) && _particleSystem.main.simulationSpace == ParticleSystemSimulationSpace.World && _parent.uiScaling)
|
var isWorldSpace = _particleSystem.IsWorldSpace();
|
||||||
if ((_prevScreenSize != screenSize || _prevScale != scale) && _particleSystem.main.simulationSpace == ParticleSystemSimulationSpace.World)
|
var resolutionChanged = _prevScreenSize != screenSize || _prevScale != scale;
|
||||||
|
if (resolutionChanged && isWorldSpace)
|
||||||
{
|
{
|
||||||
// Update particle array size and get particles.
|
// Update particle array size and get particles.
|
||||||
var size = _particleSystem.particleCount;
|
var size = _particleSystem.particleCount;
|
||||||
|
@ -474,13 +525,17 @@ namespace Coffee.UIExtensions
|
||||||
|
|
||||||
// Resolusion resolver:
|
// Resolusion resolver:
|
||||||
// (psPos / scale) / (prevPsPos / prevScale) -> psPos * scale.inv * prevPsPos.inv * prevScale
|
// (psPos / scale) / (prevPsPos / prevScale) -> psPos * scale.inv * prevPsPos.inv * prevScale
|
||||||
var modifier = psPos.GetScaled(scale.Inverse(), _prevPsPos.Inverse(), _prevScale);
|
var modifier = psPos.GetScaled(
|
||||||
|
scale.Inverse(),
|
||||||
|
_prevPsPos.Inverse(),
|
||||||
|
_prevScale);
|
||||||
for (var i = 0; i < size; i++)
|
for (var i = 0; i < size; i++)
|
||||||
{
|
{
|
||||||
var particle = particles[i];
|
var particle = particles[i];
|
||||||
particle.position = particle.position.GetScaled(modifier);
|
particle.position = particle.position.GetScaled(modifier);
|
||||||
particles[i] = particle;
|
particles[i] = particle;
|
||||||
}
|
}
|
||||||
|
|
||||||
_particleSystem.SetParticles(particles, size);
|
_particleSystem.SetParticles(particles, size);
|
||||||
|
|
||||||
// Delay: Do not progress in the frame where the resolution has been changed.
|
// Delay: Do not progress in the frame where the resolution has been changed.
|
||||||
|
@ -488,6 +543,7 @@ namespace Coffee.UIExtensions
|
||||||
_prevScale = scale;
|
_prevScale = scale;
|
||||||
_prevPsPos = psPos;
|
_prevPsPos = psPos;
|
||||||
}
|
}
|
||||||
|
|
||||||
_prevScreenSize = screenSize;
|
_prevScreenSize = screenSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -500,14 +556,16 @@ namespace Coffee.UIExtensions
|
||||||
? Time.unscaledDeltaTime
|
? Time.unscaledDeltaTime
|
||||||
: Time.deltaTime;
|
: Time.deltaTime;
|
||||||
|
|
||||||
// Prewarm:
|
// Prewarm:
|
||||||
if (0 < deltaTime && _prewarm)
|
if (0 < deltaTime && _prewarm)
|
||||||
{
|
{
|
||||||
deltaTime += main.duration;
|
deltaTime += main.duration;
|
||||||
_prewarm = false;
|
_prewarm = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Emitted particles found.
|
// (COMMENT OUT) #231: Sub Emitters option is not work in editor playing
|
||||||
|
/*
|
||||||
|
// Emitted particles found.
|
||||||
if (_prevParticleCount != _particleSystem.particleCount)
|
if (_prevParticleCount != _particleSystem.particleCount)
|
||||||
{
|
{
|
||||||
var size = _particleSystem.particleCount;
|
var size = _particleSystem.particleCount;
|
||||||
|
@ -522,24 +580,31 @@ namespace Coffee.UIExtensions
|
||||||
|
|
||||||
_particleSystem.SetParticles(particles, size);
|
_particleSystem.SetParticles(particles, size);
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
// get world position.
|
// get world position.
|
||||||
|
var isLocalSpace = _particleSystem.IsLocalSpace();
|
||||||
var psTransform = _particleSystem.transform;
|
var psTransform = _particleSystem.transform;
|
||||||
var originWorldPosition = psTransform.position;
|
var originWorldPosition = psTransform.position;
|
||||||
var originWorldRotation = psTransform.rotation;
|
var originWorldRotation = psTransform.rotation;
|
||||||
|
|
||||||
var emission = _particleSystem.emission;
|
var emission = _particleSystem.emission;
|
||||||
var rateOverDistance = emission.enabled && 0 < emission.rateOverDistance.constant && 0 < emission.rateOverDistanceMultiplier;
|
var rateOverDistance = emission.enabled
|
||||||
if (rateOverDistance)
|
&& 0 < emission.rateOverDistance.constant
|
||||||
|
&& 0 < emission.rateOverDistanceMultiplier;
|
||||||
|
if (rateOverDistance && !paused)
|
||||||
{
|
{
|
||||||
// (For rate-over-distance emission,) Move to previous scaled position, simulate (delta = 0).
|
// (For rate-over-distance emission,) Move to previous scaled position, simulate (delta = 0).
|
||||||
Vector3 prevScaledPos = _prevPsPos.GetScaled(_prevScale.Inverse());
|
var prevScaledPos = isLocalSpace
|
||||||
|
? _prevPsPos
|
||||||
|
: _prevPsPos.GetScaled(_prevScale.Inverse());
|
||||||
psTransform.SetPositionAndRotation(prevScaledPos, originWorldRotation);
|
psTransform.SetPositionAndRotation(prevScaledPos, originWorldRotation);
|
||||||
_particleSystem.Simulate(0, false, false, false);
|
_particleSystem.Simulate(0, false, false, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Move to scaled position, simulate, revert to origin position.
|
// Move to scaled position, simulate, revert to origin position.
|
||||||
var scaledPos = originWorldPosition.GetScaled(scale.Inverse());
|
var scaledPos = isLocalSpace
|
||||||
|
? originWorldPosition
|
||||||
|
: originWorldPosition.GetScaled(scale.Inverse());
|
||||||
psTransform.SetPositionAndRotation(scaledPos, originWorldRotation);
|
psTransform.SetPositionAndRotation(scaledPos, originWorldRotation);
|
||||||
_particleSystem.Simulate(deltaTime, false, false, false);
|
_particleSystem.Simulate(deltaTime, false, false, false);
|
||||||
psTransform.SetPositionAndRotation(originWorldPosition, originWorldRotation);
|
psTransform.SetPositionAndRotation(originWorldPosition, originWorldRotation);
|
||||||
|
@ -549,7 +614,8 @@ namespace Coffee.UIExtensions
|
||||||
private void SimulateForEditor(Vector3 diffPos, Vector3 scale)
|
private void SimulateForEditor(Vector3 diffPos, Vector3 scale)
|
||||||
{
|
{
|
||||||
// Extra world simulation.
|
// Extra world simulation.
|
||||||
if (_particleSystem.main.simulationSpace == ParticleSystemSimulationSpace.World && 0 < Vector3.SqrMagnitude(diffPos))
|
var isWorldSpace = _particleSystem.IsWorldSpace();
|
||||||
|
if (isWorldSpace && 0 < Vector3.SqrMagnitude(diffPos))
|
||||||
{
|
{
|
||||||
Profiler.BeginSample("[UIParticle] Bake Mesh > Extra world simulation");
|
Profiler.BeginSample("[UIParticle] Bake Mesh > Extra world simulation");
|
||||||
diffPos.x *= 1f - 1f / Mathf.Max(0.001f, scale.x);
|
diffPos.x *= 1f - 1f / Mathf.Max(0.001f, scale.x);
|
||||||
|
@ -577,7 +643,9 @@ namespace Coffee.UIExtensions
|
||||||
if (_parent.m_AnimatableProperties.Length == 0) return;
|
if (_parent.m_AnimatableProperties.Length == 0) return;
|
||||||
|
|
||||||
if (s_Mpb == null)
|
if (s_Mpb == null)
|
||||||
|
{
|
||||||
s_Mpb = new MaterialPropertyBlock();
|
s_Mpb = new MaterialPropertyBlock();
|
||||||
|
}
|
||||||
|
|
||||||
_renderer.GetPropertyBlock(s_Mpb);
|
_renderer.GetPropertyBlock(s_Mpb);
|
||||||
if (s_Mpb.isEmpty) return;
|
if (s_Mpb.isEmpty) return;
|
||||||
|
@ -585,12 +653,13 @@ namespace Coffee.UIExtensions
|
||||||
// #41: Copy the value from MaterialPropertyBlock to CanvasRenderer
|
// #41: Copy the value from MaterialPropertyBlock to CanvasRenderer
|
||||||
if (!_modifiedMaterial) return;
|
if (!_modifiedMaterial) return;
|
||||||
|
|
||||||
foreach (var ap in _parent.m_AnimatableProperties)
|
for (var i = 0; i < _parent.m_AnimatableProperties.Length; i++)
|
||||||
{
|
{
|
||||||
|
var ap = _parent.m_AnimatableProperties[i];
|
||||||
ap.UpdateMaterialProperties(_modifiedMaterial, s_Mpb);
|
ap.UpdateMaterialProperties(_modifiedMaterial, s_Mpb);
|
||||||
}
|
}
|
||||||
|
|
||||||
s_Mpb.Clear();
|
s_Mpb.Clear();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,21 +1,19 @@
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using UnityEditor;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
|
|
||||||
namespace Coffee.UIExtensions
|
namespace Coffee.UIExtensions
|
||||||
{
|
{
|
||||||
internal static class UIParticleUpdater
|
internal static class UIParticleUpdater
|
||||||
{
|
{
|
||||||
static readonly List<UIParticle> s_ActiveParticles = new List<UIParticle>();
|
private static readonly List<UIParticle> s_ActiveParticles = new List<UIParticle>();
|
||||||
static readonly List<UIParticleAttractor> s_ActiveAttractors = new List<UIParticleAttractor>();
|
private static readonly List<UIParticleAttractor> s_ActiveAttractors = new List<UIParticleAttractor>();
|
||||||
static readonly HashSet<int> s_UpdatedGroupIds = new HashSet<int>();
|
private static readonly HashSet<int> s_UpdatedGroupIds = new HashSet<int>();
|
||||||
private static int frameCount = 0;
|
private static int s_FrameCount;
|
||||||
|
|
||||||
public static int uiParticleCount
|
public static int uiParticleCount
|
||||||
{
|
{
|
||||||
get
|
get { return s_ActiveParticles.Count; }
|
||||||
{
|
|
||||||
return s_ActiveParticles.Count;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void Register(UIParticle particle)
|
public static void Register(UIParticle particle)
|
||||||
|
@ -43,7 +41,7 @@ namespace Coffee.UIExtensions
|
||||||
}
|
}
|
||||||
|
|
||||||
#if UNITY_EDITOR
|
#if UNITY_EDITOR
|
||||||
[UnityEditor.InitializeOnLoadMethod]
|
[InitializeOnLoadMethod]
|
||||||
#endif
|
#endif
|
||||||
[RuntimeInitializeOnLoadMethod]
|
[RuntimeInitializeOnLoadMethod]
|
||||||
private static void InitializeOnLoad()
|
private static void InitializeOnLoad()
|
||||||
|
@ -55,8 +53,8 @@ namespace Coffee.UIExtensions
|
||||||
private static void Refresh()
|
private static void Refresh()
|
||||||
{
|
{
|
||||||
// Do not allow it to be called in the same frame.
|
// Do not allow it to be called in the same frame.
|
||||||
if (frameCount == Time.frameCount) return;
|
if (s_FrameCount == Time.frameCount) return;
|
||||||
frameCount = Time.frameCount;
|
s_FrameCount = Time.frameCount;
|
||||||
|
|
||||||
// Simulate -> Primary
|
// Simulate -> Primary
|
||||||
for (var i = 0; i < s_ActiveParticles.Count; i++)
|
for (var i = 0; i < s_ActiveParticles.Count; i++)
|
||||||
|
@ -129,6 +127,7 @@ namespace Coffee.UIExtensions
|
||||||
if (uip.isPrimary) return uip;
|
if (uip.isPrimary) return uip;
|
||||||
if (!primary && uip.canSimulate) primary = uip;
|
if (!primary && uip.canSimulate) primary = uip;
|
||||||
}
|
}
|
||||||
|
|
||||||
return primary;
|
return primary;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
121
Scripts/Utils.cs
121
Scripts/Utils.cs
|
@ -46,11 +46,11 @@ namespace Coffee.UIParticleExtensions
|
||||||
internal static class SpriteExtensions
|
internal static class SpriteExtensions
|
||||||
{
|
{
|
||||||
#if UNITY_EDITOR
|
#if UNITY_EDITOR
|
||||||
private static Type tSpriteEditorExtension =
|
private static readonly Type s_SpriteEditorExtensionType =
|
||||||
Type.GetType("UnityEditor.Experimental.U2D.SpriteEditorExtension, UnityEditor")
|
Type.GetType("UnityEditor.Experimental.U2D.SpriteEditorExtension, UnityEditor")
|
||||||
?? Type.GetType("UnityEditor.U2D.SpriteEditorExtension, UnityEditor");
|
?? Type.GetType("UnityEditor.U2D.SpriteEditorExtension, UnityEditor");
|
||||||
|
|
||||||
private static MethodInfo miGetActiveAtlasTexture = tSpriteEditorExtension
|
private static readonly MethodInfo s_GetActiveAtlasTextureMethodInfo = s_SpriteEditorExtensionType
|
||||||
.GetMethod("GetActiveAtlasTexture", BindingFlags.Static | BindingFlags.NonPublic);
|
.GetMethod("GetActiveAtlasTexture", BindingFlags.Static | BindingFlags.NonPublic);
|
||||||
|
|
||||||
public static Texture2D GetActualTexture(this Sprite self)
|
public static Texture2D GetActualTexture(this Sprite self)
|
||||||
|
@ -58,8 +58,10 @@ namespace Coffee.UIParticleExtensions
|
||||||
if (!self) return null;
|
if (!self) return null;
|
||||||
|
|
||||||
if (Application.isPlaying) return self.texture;
|
if (Application.isPlaying) return self.texture;
|
||||||
var ret = miGetActiveAtlasTexture.Invoke(null, new[] { self }) as Texture2D;
|
var ret = s_GetActiveAtlasTextureMethodInfo.Invoke(null, new object[] { self }) as Texture2D;
|
||||||
return ret ? ret : self.texture;
|
return ret
|
||||||
|
? ret
|
||||||
|
: self.texture;
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
internal static Texture2D GetActualTexture(this Sprite self)
|
internal static Texture2D GetActualTexture(this Sprite self)
|
||||||
|
@ -77,12 +79,14 @@ namespace Coffee.UIParticleExtensions
|
||||||
{
|
{
|
||||||
if (s_TmpParticles.Length < size)
|
if (s_TmpParticles.Length < size)
|
||||||
{
|
{
|
||||||
while(s_TmpParticles.Length < size)
|
while (s_TmpParticles.Length < size)
|
||||||
{
|
{
|
||||||
size = Mathf.NextPowerOfTwo(size);
|
size = Mathf.NextPowerOfTwo(size);
|
||||||
}
|
}
|
||||||
|
|
||||||
s_TmpParticles = new ParticleSystem.Particle[size];
|
s_TmpParticles = new ParticleSystem.Particle[size];
|
||||||
}
|
}
|
||||||
|
|
||||||
return s_TmpParticles;
|
return s_TmpParticles;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -102,47 +106,69 @@ namespace Coffee.UIParticleExtensions
|
||||||
var main = self.main;
|
var main = self.main;
|
||||||
var space = main.simulationSpace;
|
var space = main.simulationSpace;
|
||||||
if (space == ParticleSystemSimulationSpace.Custom && !main.customSimulationSpace)
|
if (space == ParticleSystemSimulationSpace.Custom && !main.customSimulationSpace)
|
||||||
|
{
|
||||||
space = ParticleSystemSimulationSpace.Local;
|
space = ParticleSystemSimulationSpace.Local;
|
||||||
|
}
|
||||||
|
|
||||||
return space;
|
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)
|
public static void SortForRendering(this List<ParticleSystem> self, Transform transform, bool sortByMaterial)
|
||||||
{
|
{
|
||||||
self.Sort((a, b) =>
|
self.Sort((a, b) =>
|
||||||
{
|
{
|
||||||
var tr = transform;
|
|
||||||
var aRenderer = a.GetComponent<ParticleSystemRenderer>();
|
var aRenderer = a.GetComponent<ParticleSystemRenderer>();
|
||||||
var bRenderer = b.GetComponent<ParticleSystemRenderer>();
|
var bRenderer = b.GetComponent<ParticleSystemRenderer>();
|
||||||
|
|
||||||
// Render queue: ascending
|
// Render queue: ascending
|
||||||
var aMat = aRenderer.sharedMaterial ?? aRenderer.trailMaterial;
|
var aMat = aRenderer.sharedMaterial ? aRenderer.sharedMaterial : aRenderer.trailMaterial;
|
||||||
var bMat = bRenderer.sharedMaterial ?? bRenderer.trailMaterial;
|
var bMat = bRenderer.sharedMaterial ? bRenderer.sharedMaterial : bRenderer.trailMaterial;
|
||||||
if (!aMat && !bMat) return 0;
|
if (!aMat && !bMat) return 0;
|
||||||
if (!aMat) return -1;
|
if (!aMat) return -1;
|
||||||
if (!bMat) return 1;
|
if (!bMat) return 1;
|
||||||
|
|
||||||
if (sortByMaterial)
|
if (sortByMaterial)
|
||||||
|
{
|
||||||
return aMat.GetInstanceID() - bMat.GetInstanceID();
|
return aMat.GetInstanceID() - bMat.GetInstanceID();
|
||||||
|
}
|
||||||
|
|
||||||
if (aMat.renderQueue != bMat.renderQueue)
|
if (aMat.renderQueue != bMat.renderQueue)
|
||||||
|
{
|
||||||
return aMat.renderQueue - bMat.renderQueue;
|
return aMat.renderQueue - bMat.renderQueue;
|
||||||
|
}
|
||||||
|
|
||||||
// Sorting layer: ascending
|
// Sorting layer: ascending
|
||||||
if (aRenderer.sortingLayerID != bRenderer.sortingLayerID)
|
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
|
// Sorting order: ascending
|
||||||
if (aRenderer.sortingOrder != bRenderer.sortingOrder)
|
if (aRenderer.sortingOrder != bRenderer.sortingOrder)
|
||||||
|
{
|
||||||
return aRenderer.sortingOrder - bRenderer.sortingOrder;
|
return aRenderer.sortingOrder - bRenderer.sortingOrder;
|
||||||
|
}
|
||||||
|
|
||||||
// Z position & sortingFudge: descending
|
// Z position & sortingFudge: descending
|
||||||
var aTransform = a.transform;
|
var aTransform = a.transform;
|
||||||
var bTransform = b.transform;
|
var bTransform = b.transform;
|
||||||
var aPos = tr.InverseTransformPoint(aTransform.position).z + aRenderer.sortingFudge;
|
var aPos = transform.InverseTransformPoint(aTransform.position).z + aRenderer.sortingFudge;
|
||||||
var bPos = tr.InverseTransformPoint(bTransform.position).z + bRenderer.sortingFudge;
|
var bPos = transform.InverseTransformPoint(bTransform.position).z + bRenderer.sortingFudge;
|
||||||
if (!Mathf.Approximately(aPos, bPos))
|
if (!Mathf.Approximately(aPos, bPos))
|
||||||
|
{
|
||||||
return (int)Mathf.Sign(bPos - aPos);
|
return (int)Mathf.Sign(bPos - aPos);
|
||||||
|
}
|
||||||
|
|
||||||
return (int)Mathf.Sign(GetIndex(self, a) - GetIndex(self, b));
|
return (int)Mathf.Sign(GetIndex(self, a) - GetIndex(self, b));
|
||||||
});
|
});
|
||||||
|
@ -152,7 +178,10 @@ namespace Coffee.UIParticleExtensions
|
||||||
{
|
{
|
||||||
for (var i = 0; i < list.Count; i++)
|
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;
|
return 0;
|
||||||
|
@ -183,4 +212,72 @@ namespace Coffee.UIParticleExtensions
|
||||||
self.ForEach(action);
|
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_2020_3_OR_NEWER || UNITY_2021_1
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static T GetComponentInChildren<T>(this Component self, bool includeInactive) where T : Component
|
||||||
|
{
|
||||||
|
if (!self) return null;
|
||||||
|
if (!includeInactive) return self.GetComponentInChildren<T>();
|
||||||
|
|
||||||
|
var component = self.GetComponent<T>();
|
||||||
|
if (component) return component;
|
||||||
|
|
||||||
|
foreach (Transform child in self.transform)
|
||||||
|
{
|
||||||
|
component = child.GetComponentInChildren<T>(true);
|
||||||
|
if (component) return component;
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,85 @@
|
||||||
|
%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: []
|
|
@ -0,0 +1,8 @@
|
||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 9944483a3e009401ba5dcc42f14d5c63
|
||||||
|
NativeFormatImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
mainObjectFileID: 2100000
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
Loading…
Reference in New Issue