You've already forked ParticleEffectForUGUI
mirror of
https://github.com/mob-sakai/ParticleEffectForUGUI.git
synced 2026-05-14 20:20:06 +00:00
Compare commits
15 Commits
develop
...
4.6.0-prev
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ee780c4996 | ||
|
|
e840631fb3 | ||
|
|
a5fdfce554 | ||
|
|
8028b2a770 | ||
|
|
b45dc77312 | ||
|
|
5dab4f21c7 | ||
|
|
f17ecafae7 | ||
|
|
5892df1ce1 | ||
|
|
f0fb205212 | ||
|
|
70e917107d | ||
|
|
eaae94ce00 | ||
|
|
7430c39f52 | ||
|
|
5fc44b82bc | ||
|
|
128990acc6 | ||
|
|
4790db6b93 |
12
.github/FUNDING.yml
vendored
12
.github/FUNDING.yml
vendored
@@ -1,12 +0,0 @@
|
||||
# These are supported funding model platforms
|
||||
|
||||
github: mob-sakai # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2]
|
||||
patreon: mob_sakai # Replace with a single Patreon username
|
||||
open_collective: # Replace with a single Open Collective username
|
||||
ko_fi: # Replace with a single Ko-fi username
|
||||
tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel
|
||||
community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry
|
||||
liberapay: # Replace with a single Liberapay username
|
||||
issuehunt: # Replace with a single IssueHunt username
|
||||
otechie: # Replace with a single Otechie username
|
||||
custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2']
|
||||
48
.github/ISSUE_TEMPLATE/bug_report.md
vendored
48
.github/ISSUE_TEMPLATE/bug_report.md
vendored
@@ -1,48 +0,0 @@
|
||||
---
|
||||
name: Bug report
|
||||
about: Create a report to help us improve
|
||||
title: ''
|
||||
labels: bug
|
||||
assignees: mob-sakai
|
||||
|
||||
---
|
||||
|
||||
NOTE: Your issue may already be reported! Please search on the [issue tracker](../) before creating one.
|
||||
|
||||
**Describe the bug**
|
||||
|
||||
A clear and concise description of what the bug is.
|
||||
|
||||
**To Reproduce**
|
||||
|
||||
Steps to reproduce the behavior:
|
||||
|
||||
1. Go to '...'
|
||||
2. Click on '....'
|
||||
3. Scroll down to '....'
|
||||
4. See error
|
||||
|
||||
**Expected behavior**
|
||||
|
||||
A clear and concise description of what you expected to happen.
|
||||
|
||||
**Screenshots**
|
||||
|
||||
If applicable, add screenshots to help explain your problem.
|
||||
|
||||
**Environment (please complete the following)**
|
||||
|
||||
- Package version [e.g. 4.2.0, 3.3.14]
|
||||
- Platform: [e.g. Editor(Windows/Mac), Standalone(Windows/Mac), iOS, Android, WebGL]
|
||||
- Unity version: [e.g. 2021.3.7f1]
|
||||
- Project options: [e.g. Mono/IL2CPP, .Net Standard 2.1/.Net 4.x, URP/HDRP, GraphicAPIs]
|
||||
|
||||
**Additional context**
|
||||
|
||||
Please add any other context about the issue here.
|
||||
It will help us resolve the issue.
|
||||
|
||||
- Error messages and crash dump
|
||||
- Screenshots, gif animations and movie files
|
||||
- Reproducible minimal project
|
||||
- The entire project (zipped Assets, Packages, ProjectSettings) is preferred over `.unitypackage`
|
||||
26
.github/ISSUE_TEMPLATE/feature_request.md
vendored
26
.github/ISSUE_TEMPLATE/feature_request.md
vendored
@@ -1,26 +0,0 @@
|
||||
---
|
||||
name: Feature request
|
||||
about: Suggest an idea for this project
|
||||
title: ''
|
||||
labels: enhancement
|
||||
assignees: mob-sakai
|
||||
|
||||
---
|
||||
|
||||
NOTE: Your issue may already be reported! Please search on the [issue tracker](../) before creating one.
|
||||
|
||||
**Is your feature request related to a problem? Please describe.**
|
||||
|
||||
A clear and concise description of what the issue is. (e.g. I'm always frustrated when [...])
|
||||
|
||||
**Describe the solution you'd like**
|
||||
|
||||
A clear and concise description of what you want to happen.
|
||||
|
||||
**Describe alternatives you've considered**
|
||||
|
||||
A clear and concise description of any alternative solutions or features you've considered.
|
||||
|
||||
**Additional context**
|
||||
|
||||
Add any other context or screenshots about the feature request here.
|
||||
16
.github/ISSUE_TEMPLATE/question.md
vendored
16
.github/ISSUE_TEMPLATE/question.md
vendored
@@ -1,16 +0,0 @@
|
||||
---
|
||||
name: Question
|
||||
about: Ask a question about this project
|
||||
title: ''
|
||||
labels: question
|
||||
assignees: mob-sakai
|
||||
|
||||
---
|
||||
|
||||
NOTE: Your issue may already be reported! Please search on the [issue tracker](../) before creating one.
|
||||
|
||||
**Describe what help do you need**
|
||||
A description of the question.
|
||||
|
||||
**Additional context**
|
||||
Add any other context or screenshots about the question here.
|
||||
24
.github/workflows/release.yml
vendored
24
.github/workflows/release.yml
vendored
@@ -1,24 +0,0 @@
|
||||
name: release
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- preview
|
||||
- main
|
||||
- v*.x
|
||||
tags-ignore:
|
||||
- "**"
|
||||
|
||||
jobs:
|
||||
release:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
- uses: cycjimmy/semantic-release-action@v3
|
||||
with:
|
||||
extra_plugins: |
|
||||
@semantic-release/changelog
|
||||
@semantic-release/git
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ github.token }}
|
||||
69
.github/workflows/test.yml
vendored
69
.github/workflows/test.yml
vendored
@@ -1,69 +0,0 @@
|
||||
# Secrets
|
||||
# UNITY_LICENSE:
|
||||
name: test
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- develop
|
||||
tags:
|
||||
- "!*"
|
||||
pull_request:
|
||||
types:
|
||||
- opened
|
||||
- synchronize
|
||||
|
||||
jobs:
|
||||
setup:
|
||||
runs-on: ubuntu-latest
|
||||
outputs:
|
||||
versions: ${{ steps.setup.outputs.versions }}
|
||||
steps:
|
||||
- id: setup
|
||||
run: |
|
||||
VERSIONS=`npx unity-changeset list --versions --all --latest-patch --min 2018.3 --json`
|
||||
echo "==== Target Unity Versions ===="
|
||||
echo "${VERSIONS}"
|
||||
echo "::set-output name=versions::${VERSIONS}"
|
||||
|
||||
test:
|
||||
runs-on: ubuntu-latest
|
||||
needs: setup
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
version: ${{ fromJson(needs.setup.outputs.versions) }}
|
||||
|
||||
steps:
|
||||
# Checkout sandbox project
|
||||
- uses: actions/checkout@v3
|
||||
with:
|
||||
ref: sandbox
|
||||
submodules: true
|
||||
fetch-depth: 0
|
||||
|
||||
# Update package submodule
|
||||
- name: "Update package submodule"
|
||||
working-directory: Packages/dev
|
||||
run: git checkout ${{ github.sha }}
|
||||
|
||||
# Cache
|
||||
- uses: actions/cache@v3
|
||||
with:
|
||||
path: Library
|
||||
key: Library-${{ matrix.version }}-${{ github.sha }}
|
||||
restore-keys: |
|
||||
Library-${{ matrix.version }}-
|
||||
Library-
|
||||
|
||||
# Run tests
|
||||
- name: "Run tests"
|
||||
uses: game-ci/unity-test-runner@v2
|
||||
with:
|
||||
customImage: mobsakai/unity3d:${{ matrix.version }}
|
||||
customParameters: -nographics
|
||||
# unityVersion: ${{ matrix.version }}
|
||||
checkName: ${{ matrix.version }} Test Results
|
||||
githubToken: ${{ github.token }}
|
||||
env:
|
||||
UNITY_LICENSE: ${{ secrets.UNITY_LICENSE }}
|
||||
@@ -1,14 +1,11 @@
|
||||
{
|
||||
"branches": [
|
||||
"+([0-9])?(.{+([0-9]),x}).x",
|
||||
"master",
|
||||
"main",
|
||||
"release",
|
||||
{
|
||||
"name": "preview",
|
||||
"prerelease": true
|
||||
}
|
||||
],
|
||||
"tagFormat": "${version}",
|
||||
"plugins": [
|
||||
"@semantic-release/commit-analyzer",
|
||||
"@semantic-release/release-notes-generator",
|
||||
|
||||
17
CHANGELOG.md
17
CHANGELOG.md
@@ -1,3 +1,20 @@
|
||||
# [4.6.0-preview.1](https://github.com/mob-sakai/ParticleEffectForUGUI/compare/v4.5.2...v4.6.0-preview.1) (2024-01-24)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* fix abnormal mesh bounds error ([772bf50](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/772bf50d168982bd401c30e58172e0a60fbafe46)), closes [#213](https://github.com/mob-sakai/ParticleEffectForUGUI/issues/213)
|
||||
* fix warning ([93d3919](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/93d3919b6fb6ac186b3e99f8baaef9a044f583f2))
|
||||
* fix warning ([8a78ec1](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/8a78ec13ad2aad9138a22b67c332871e064a38cc))
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* "[generated]" GameObjects on the hierarchy is disturbing ([7c42421](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/7c4242150b591daf64390588afa27efa27368af3)), closes [#288](https://github.com/mob-sakai/ParticleEffectForUGUI/issues/288)
|
||||
* add explicit dependencies ([9a0187a](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/9a0187a72a35d378ff7be965bfcb7475f423fe0f))
|
||||
* add icon ([0c1022c](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/0c1022c6224394713f62b41e5e4ef0c289610ae1))
|
||||
* remove samples ([f53a7fa](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/f53a7faed3ee73ac22d745a778284e818624b510))
|
||||
|
||||
## [4.5.2](https://github.com/mob-sakai/ParticleEffectForUGUI/compare/4.5.1...4.5.2) (2024-01-18)
|
||||
|
||||
|
||||
|
||||
@@ -1,3 +1,11 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text.RegularExpressions;
|
||||
using UnityEditor;
|
||||
using UnityEditor.UI;
|
||||
using UnityEditorInternal;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
#if UNITY_2021_2_OR_NEWER
|
||||
using UnityEditor.Overlays;
|
||||
#else
|
||||
@@ -8,17 +16,6 @@ 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
|
||||
{
|
||||
@@ -29,9 +26,9 @@ namespace Coffee.UIExtensions
|
||||
#if UNITY_2021_2_OR_NEWER
|
||||
#if UNITY_2022_1_OR_NEWER
|
||||
[Overlay(typeof(SceneView), "Scene View/UI Particles", "UI Particles", true,
|
||||
defaultDockPosition = DockPosition.Bottom,
|
||||
defaultDockZone = DockZone.Floating,
|
||||
defaultLayout = Layout.Panel)]
|
||||
defaultDockPosition = DockPosition.Bottom,
|
||||
defaultDockZone = DockZone.Floating,
|
||||
defaultLayout = Layout.Panel)]
|
||||
#else
|
||||
[Overlay(typeof(SceneView), "Scene View/UI Particles", "UI Particles", true)]
|
||||
#endif
|
||||
@@ -43,7 +40,7 @@ namespace Coffee.UIExtensions
|
||||
{
|
||||
if (visible)
|
||||
{
|
||||
WindowFunction(null, null);
|
||||
WindowFunction();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -75,8 +72,9 @@ namespace Coffee.UIExtensions
|
||||
private bool _showMax;
|
||||
|
||||
private static readonly HashSet<Shader> s_Shaders = new HashSet<Shader>();
|
||||
#if UNITY_2018 || UNITY_2019
|
||||
private static readonly List<ParticleSystemVertexStream> s_Streams = new List<ParticleSystemVertexStream>();
|
||||
|
||||
#endif
|
||||
private static readonly List<string> s_MaskablePropertyNames = new List<string>
|
||||
{
|
||||
"_Stencil",
|
||||
@@ -128,6 +126,7 @@ namespace Coffee.UIExtensions
|
||||
.Concat(Selection.gameObjects.Select(x => x.GetComponent<UIParticle>())
|
||||
.Where(x => x && x.canvas))
|
||||
.Distinct()
|
||||
.OfType<Object>()
|
||||
.ToArray();
|
||||
return 0 < uiParticles.Length ? new SerializedObject(uiParticles) : null;
|
||||
}
|
||||
@@ -332,6 +331,8 @@ namespace Coffee.UIExtensions
|
||||
DestroyUIParticle(current);
|
||||
}
|
||||
|
||||
#if UNITY_2018 || UNITY_2019
|
||||
// (2018, 2019) Check to use 'TEXCOORD*.zw' components as custom vertex stream.
|
||||
var allPsRenderers = targets.OfType<UIParticle>()
|
||||
.SelectMany(x => x.particles)
|
||||
.Where(x => x)
|
||||
@@ -357,6 +358,7 @@ namespace Coffee.UIExtensions
|
||||
s_Streams.Clear();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
private bool IsBuiltInObject(Object obj)
|
||||
@@ -365,6 +367,7 @@ namespace Coffee.UIExtensions
|
||||
&& Regex.IsMatch(guid, "^0{16}.0{15}$", RegexOptions.Compiled);
|
||||
}
|
||||
|
||||
#if UNITY_2018 || UNITY_2019
|
||||
private static int GetUsedComponentCount(ParticleSystemVertexStream s)
|
||||
{
|
||||
switch (s)
|
||||
@@ -423,6 +426,7 @@ namespace Coffee.UIExtensions
|
||||
|
||||
return 3;
|
||||
}
|
||||
#endif
|
||||
|
||||
private static bool DrawMeshSharing(SerializedProperty spMeshSharing, SerializedProperty spGroupId,
|
||||
SerializedProperty spGroupMaxId, bool showMax)
|
||||
@@ -482,12 +486,16 @@ namespace Coffee.UIExtensions
|
||||
};
|
||||
}
|
||||
|
||||
private static void WindowFunction(Object target, SceneView sceneView)
|
||||
#if UNITY_2021_2_OR_NEWER
|
||||
private static void WindowFunction()
|
||||
#else
|
||||
private static void WindowFunction(Object _, SceneView __)
|
||||
#endif
|
||||
{
|
||||
try
|
||||
{
|
||||
if (s_SerializedObject == null || !s_SerializedObject.targetObject) return;
|
||||
var uiParticles = s_SerializedObject.targetObjects.OfType<UIParticle>();
|
||||
var uiParticles = s_SerializedObject.targetObjects.OfType<UIParticle>().ToArray();
|
||||
if (uiParticles.Any(x => !x || !x.canvas)) return;
|
||||
|
||||
s_SerializedObject.Update();
|
||||
@@ -523,7 +531,7 @@ namespace Coffee.UIExtensions
|
||||
if (stage != null && stage.scene.isLoaded)
|
||||
{
|
||||
#if UNITY_2020_1_OR_NEWER
|
||||
string prefabAssetPath = stage.assetPath;
|
||||
var prefabAssetPath = stage.assetPath;
|
||||
#else
|
||||
var prefabAssetPath = stage.prefabAssetPath;
|
||||
#endif
|
||||
@@ -1,5 +1,5 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 15e5409f0334e479e91e672ae14567d3
|
||||
guid: 7a55e246f37df405bac88eac692e3a86
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
BIN
Icons/UIParticleIcon.png
Normal file
BIN
Icons/UIParticleIcon.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 418 B |
@@ -1,9 +1,9 @@
|
||||
fileFormatVersion: 2
|
||||
guid: fc4e1d816001842709cf8a393c69dd14
|
||||
guid: 5f0675613942149309588d556e33d990
|
||||
TextureImporter:
|
||||
fileIDToRecycleName: {}
|
||||
internalIDToNameTable: []
|
||||
externalObjects: {}
|
||||
serializedVersion: 9
|
||||
serializedVersion: 12
|
||||
mipmaps:
|
||||
mipMapMode: 0
|
||||
enableMipMap: 0
|
||||
@@ -20,27 +20,30 @@ TextureImporter:
|
||||
externalNormalMap: 0
|
||||
heightScale: 0.25
|
||||
normalMapFilter: 0
|
||||
flipGreenChannel: 0
|
||||
isReadable: 0
|
||||
streamingMipmaps: 0
|
||||
streamingMipmapsPriority: 0
|
||||
vTOnly: 0
|
||||
ignoreMipmapLimit: 0
|
||||
grayScaleToAlpha: 0
|
||||
generateCubemap: 6
|
||||
cubemapConvolution: 0
|
||||
seamlessCubemap: 0
|
||||
textureFormat: -1
|
||||
textureFormat: 1
|
||||
maxTextureSize: 2048
|
||||
textureSettings:
|
||||
serializedVersion: 2
|
||||
filterMode: -1
|
||||
aniso: -1
|
||||
mipBias: -100
|
||||
filterMode: 1
|
||||
aniso: 1
|
||||
mipBias: 0
|
||||
wrapU: 1
|
||||
wrapV: 1
|
||||
wrapW: 1
|
||||
wrapW: 0
|
||||
nPOTScale: 0
|
||||
lightmap: 0
|
||||
compressionQuality: 50
|
||||
spriteMode: 1
|
||||
spriteMode: 0
|
||||
spriteExtrude: 1
|
||||
spriteMeshType: 1
|
||||
alignment: 0
|
||||
@@ -51,16 +54,22 @@ TextureImporter:
|
||||
alphaUsage: 1
|
||||
alphaIsTransparency: 1
|
||||
spriteTessellationDetail: -1
|
||||
textureType: 8
|
||||
textureType: 2
|
||||
textureShape: 1
|
||||
singleChannelComponent: 0
|
||||
flipbookRows: 1
|
||||
flipbookColumns: 1
|
||||
maxTextureSizeSet: 0
|
||||
compressionQualitySet: 0
|
||||
textureFormatSet: 0
|
||||
ignorePngGamma: 0
|
||||
applyGammaDecoding: 0
|
||||
swizzle: 50462976
|
||||
cookieLightType: 0
|
||||
platformSettings:
|
||||
- serializedVersion: 2
|
||||
- serializedVersion: 3
|
||||
buildTarget: DefaultTexturePlatform
|
||||
maxTextureSize: 2048
|
||||
maxTextureSize: 64
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
@@ -68,8 +77,10 @@ TextureImporter:
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
ignorePlatformSupport: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
- serializedVersion: 2
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
- serializedVersion: 3
|
||||
buildTarget: Standalone
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
@@ -79,31 +90,11 @@ TextureImporter:
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
ignorePlatformSupport: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
- serializedVersion: 2
|
||||
buildTarget: iPhone
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
- serializedVersion: 2
|
||||
buildTarget: Android
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
- serializedVersion: 2
|
||||
buildTarget: WebGL
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
- serializedVersion: 3
|
||||
buildTarget: Server
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
@@ -112,21 +103,25 @@ TextureImporter:
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
ignorePlatformSupport: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
spriteSheet:
|
||||
serializedVersion: 2
|
||||
sprites: []
|
||||
outline: []
|
||||
physicsShape: []
|
||||
bones: []
|
||||
spriteID: de8a1691f8aae4be18d66008040aa1a7
|
||||
spriteID:
|
||||
internalID: 0
|
||||
vertices: []
|
||||
indices:
|
||||
edges: []
|
||||
weights: []
|
||||
spritePackingTag:
|
||||
secondaryTextures: []
|
||||
nameFileIdTable: {}
|
||||
mipmapLimitGroupName:
|
||||
pSDRemoveMatte: 0
|
||||
pSDShowRemoveMatteOption: 0
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
454
README.md
454
README.md
@@ -1,210 +1,176 @@
|
||||
Particle Effect For UGUI (UI Particle)
|
||||
===
|
||||
# Particle Effect For UGUI (UI Particle)
|
||||
|
||||
This plugin provide a component to render particle effect for uGUI in Unity 2018.2 or later.
|
||||
The particle rendering is maskable and sortable, without Camera, RenderTexture or Canvas.
|
||||
This package provides a component to render particle effects for uGUI in Unity 2018.2 or later.
|
||||
The particle rendering is maskable and sortable, without the need for an extra Camera, RenderTexture, or Canvas.
|
||||
|
||||

|
||||
[](https://openupm.com/packages/com.coffee.ui-particle/)
|
||||
[](https://github.com/mob-sakai/ParticleEffectForUGUI/releases)
|
||||
[)](https://github.com/mob-sakai/ParticleEffectForUGUI/releases)
|
||||
[](https://github.com/mob-sakai/ParticleEffectForUGUI/releases) [](https://github.com/mob-sakai/ParticleEffectForUGUI/blob/master/LICENSE.txt)
|
||||
[](https://github.com/mob-sakai/ParticleEffectForUGUI/releases)
|
||||
[](https://github.com/mob-sakai/ParticleEffectForUGUI/blob/main/LICENSE.txt)
|
||||

|
||||

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

|
||||
|
||||
This plugin uses new APIs `MeshBake/MashTrailBake` (added with Unity 2018.2) to render particles by CanvasRenderer.
|
||||
You can mask and sort particles for uGUI without Camera, RenderTexture, Canvas.
|
||||
This package utilizes the new APIs `MeshBake/MashTrailBake` (introduced with Unity 2018.2) to render particles through
|
||||
CanvasRenderer.
|
||||
You can render, mask, and sort your ParticleSystems for UI without the necessity of an additional Camera, RenderTexture,
|
||||
or Canvas.
|
||||
|
||||
Compares this "Baking mesh" approach with the conventional approach:
|
||||
[Performance test results](https://github.com/mob-sakai/ParticleEffectForUGUI/issues/193#issuecomment-1160028374)
|
||||
### Features
|
||||
|
||||
|Approach|Good|Bad|Screenshot|
|
||||
|-|-|-|-|
|
||||
|Baking mesh<br>**\(UIParticle\)**|Rendered as is.<br>Maskable.<br>Sortable.<br>Less objects.|[Not support `TEXCOORD*.zw` components for custom vertex stream](https://github.com/mob-sakai/ParticleEffectForUGUI/issues/191#issuecomment-1043409186)|<img src="https://user-images.githubusercontent.com/12690315/41765089-0302b9a2-763e-11e8-88b3-b6ffa306bbb0.gif" width="500px">|
|
||||
|Do nothing|Rendered as is.|**Looks like a glitch.**<br>Not maskable.<br>Not sortable.|<img src="https://user-images.githubusercontent.com/12690315/41765090-0329828a-763e-11e8-8d8a-f1d269ea3bc7.gif" width="500px">|
|
||||
|Convert particle to UIVertex<br>[\(UIParticleSystem\)](https://forum.unity.com/threads/free-script-particle-systems-in-ui-screen-space-overlay.406862/)|Maskable.<br>Sortable.<br>Less objects.|**Adjustment is difficult.**<br>Requires UI shaders.<br>Difficult to adjust scale.<br>Force hierarchy scalling.<br>Simulation results are incorrect.<br>Trail, rotation of transform, time scaling are not supported.<br>Generate heavy GC every frame.|<img src="https://user-images.githubusercontent.com/12690315/41765088-02deb9c6-763e-11e8-98d0-9e0c1766ef39.gif" width="500px">|
|
||||
|Use Canvas to sort|Rendered as is.<br>Sortable.|**You must to manage sorting orders.**<br>Not maskable.<br>More batches.|<img src="https://user-images.githubusercontent.com/12690315/41765087-02b866ea-763e-11e8-8c33-081c9ad852f8.gif" width="500px">|
|
||||
|Use RenderTexture|Maskable.<br>Sortable.|**Requires Camera and RenderTexture.**<br>Difficult to adjust position and size.<br>Quality depends on the RenderTexture's setting.|<img src="https://user-images.githubusercontent.com/12690315/41765085-0291b3e2-763e-11e8-827b-72e5ee9bc556.gif" width="500px">|
|
||||
* Easy to use: The package is ready to use out of the box.
|
||||
* Sort particle effects and other UI by sibling index.
|
||||
* No extra Camera, RenderTexture, or Canvas required.
|
||||
* Masking options for Mask or RectMask2D.
|
||||
* Support for the Trail module.
|
||||
* Support for CanvasGroup alpha.
|
||||
* No allocations needed to render particles.
|
||||
* Compatibility with overlay, camera space, and world space.
|
||||
* Support for Universal Render Pipeline (URP) and High Definition Render Pipeline (HDRP).
|
||||
* Support for disabling `Enter Play Mode Options > Reload Domain`.
|
||||
* Support for changing material property with AnimationClip (AnimatableProperty).
|
||||
![AnimatableProperty.gif][AnimatableProperty.gif]
|
||||
* [4.0.0+] Support for 8+ materials.
|
||||
* [4.0.0+] Correct world space particle position adjustment when changing window size for standalone platforms (Windows,
|
||||
MacOSX, and Linux).
|
||||
* [4.0.0+] Adaptive scaling for UI.
|
||||
* [4.0.0+] Mesh sharing group to improve performance.
|
||||
![MeshSharing.gif][MeshSharing.gif]
|
||||
* [4.0.0+] Particle attractor component.
|
||||
![ParticleAttractor.gif][ParticleAttractor.gif]
|
||||
* [4.1.0+] Relative/Absolute particle position mode.
|
||||
![AbsolutePosition.gif][AbsolutePosition.gif]
|
||||
|
||||
|Approach|FPS on Editor|FPS on iPhone6|FPS on Xperia XZ|
|
||||
|--|--|--|--|
|
||||
|Particle System|43|57|22|
|
||||
|UIParticleSystem|4|3|0 (unmeasurable)|
|
||||
|Sorting By Canvas|43|44|18|
|
||||
|UIParticle|17|12|4|
|
||||
|UIParticle with MeshSharing|44|45|30|
|
||||
[AnimatableProperty.gif]: https://user-images.githubusercontent.com/12690315/53286323-2d94a980-37b0-11e9-8afb-c4a207805ff2.gif
|
||||
|
||||
[MeshSharing.gif]: https://user-images.githubusercontent.com/12690315/174311048-c882df81-6c34-4eba-b0aa-5645457692f1.gif
|
||||
|
||||
[ParticleAttractor.gif]: https://user-images.githubusercontent.com/12690315/174311027-462929a4-13f0-4ec4-86ea-9c832f2eecf1.gif
|
||||
|
||||
[AbsolutePosition.gif]: https://user-images.githubusercontent.com/12690315/175751579-5a2357e8-2ecf-4afd-83c8-66e9771bde39.gif
|
||||
|
||||
<br><br>
|
||||
|
||||
#### Features
|
||||
## 🎮 Demo
|
||||
|
||||
* Easy to use: the package is out-of-the-box
|
||||
* Sort particle effects and UI by sibling index
|
||||
* No Camera, RenderTexture or Canvas are required
|
||||
* Masking by Mask or RectMask2D
|
||||
* Support Trail module
|
||||
* Support CanvasGroup alpha
|
||||
* No allocations
|
||||
* Support overlay, camera space and world space
|
||||
* Support Universal Render Pipeline (URP) and High Definition Render Pipeline (HDRP)
|
||||
* Support disabling `Enter Play Mode Options > Reload Domain`
|
||||
* Support changing material property with AnimationClip (AnimatableProperty)
|
||||

|
||||
* [4.0.0+] Support 8+ materials
|
||||
* [4.0.0+] Correct world space particle position when changing window size for standalone platforms (Windows, MacOSX and Linux)
|
||||
* [4.0.0+] Adaptive scaling for UI
|
||||
* [4.0.0+] Mesh sharing group to improve performance
|
||||

|
||||
* [4.0.0+] Particle attractor component
|
||||

|
||||
* [4.1.0+] Relative/Absolute particle position mode
|
||||

|
||||
* [WebGL Demo](https://mob-sakai.github.io/demos/UIParticle_Demo/index.html)
|
||||
|
||||
|
||||
<br><br><br><br>
|
||||
|
||||
## Demo
|
||||
|
||||
* [WebGL Demo](https://mob-sakai.github.io/demos/UIParticle_Demo/index.html)
|
||||
> 
|
||||
|
||||
* [WebGL Demo (Cartoon FX & War FX)](https://mob-sakai.github.io/Demos/ParticleEffectForUGUI_CFX)
|
||||
* [Cartoon FX Free][CFX] & [War FX][WFX] (by [Jean Moreno (JMO)][JMO]) with UIParticle
|
||||
* [Cartoon FX Free][CFX] & [War FX][WFX] (by [Jean Moreno (JMO)][JMO]) with UIParticle
|
||||
|
||||
> 
|
||||
|
||||
[CFX]: https://assetstore.unity.com/packages/vfx/particles/cartoon-fx-free-109565
|
||||
|
||||
[WFX]: https://assetstore.unity.com/packages/vfx/particles/war-fx-5669
|
||||
|
||||
[JMO]: https://assetstore.unity.com/publishers/1669
|
||||
|
||||
|
||||
<br><br><br><br>
|
||||
<br><br>
|
||||
|
||||
## Installation
|
||||
## ⚙ Installation
|
||||
|
||||
### Requirement
|
||||
_This package requires Unity 2018.3 or later._
|
||||
|
||||
Unity 2018.2 or later
|
||||
#### Install via OpenUPM
|
||||
|
||||
### Install via OpenUPM
|
||||
This package is available on [OpenUPM](https://openupm.com) package registry.
|
||||
This is the preferred method of installation, as you can easily receive updates as they're released.
|
||||
|
||||
This package is available on [OpenUPM](https://openupm.com).
|
||||
It's recommended to install it via [openupm-cli](https://github.com/openupm/openupm-cli).
|
||||
```
|
||||
If you have [openupm-cli](https://github.com/openupm/openupm-cli) installed, then run the following command in your
|
||||
project's directory:
|
||||
|
||||
```sh
|
||||
openupm add com.coffee.ui-particle
|
||||
```
|
||||
|
||||
### Install via Package Manager Window (using Git URL)
|
||||
#### Install via UPM (using Git URL)
|
||||
|
||||
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`
|
||||

|
||||
Navigate to your project's Packages folder and open the `manifest.json` file. Then add this package somewhere in
|
||||
the `dependencies` block:
|
||||
|
||||
```json
|
||||
{
|
||||
"dependencies": {
|
||||
"com.coffee.ui-particle": "https://github.com/mob-sakai/ParticleEffectForUGUI.git",
|
||||
...
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
To update the package, change suffix `#{version}` to the target version.
|
||||
|
||||
* e.g. `"com.coffee.ui-particle": "https://github.com/mob-sakai/ParticleEffectForUGUI.git#4.6.0",`
|
||||
|
||||
Or, use [UpmGitExtension](https://github.com/mob-sakai/UpmGitExtension) to install and update the package.
|
||||
|
||||
### Install via manifest.json (using Git URL)
|
||||
<br><br>
|
||||
|
||||
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",`
|
||||
## 🚀 Usage
|
||||
|
||||
### Install as an embed package
|
||||
### UIParticle Component
|
||||
|
||||
1. Download a source code zip file from [Releases](https://github.com/mob-sakai/ParticleEffectForUGUI/releases) page
|
||||
2. Extract it and place it under `Packages` directory in your project.
|
||||

|
||||
|
||||
|
||||
<br><br><br><br>
|
||||
|
||||
## How to play demo
|
||||
|
||||
### For Unity 2019.1 or later
|
||||
|
||||
1. Open `Package Manager` window
|
||||
2. Select `UI Particle` package in package list
|
||||
3. Click `Import Sample` button
|
||||

|
||||
4. The demo project is imported into `Assets/Samples/UI Particle/{version}/Demo`
|
||||
5. Open `UIParticle_Demo` scene and play it
|
||||
|
||||
### For Unity 2018.4 or earlier
|
||||
|
||||
1. Select `Assets/Samples/UI Particle Demo` from menu
|
||||
2. The demo project is imported into `Assets/Samples/UI Particle/{version}/Demo`
|
||||
3. Open `UIParticle_Demo` scene and play it
|
||||
|
||||
### About `Cartoon FX & War Fx Demo`
|
||||
|
||||
* It requires free assets ([Cartoon FX Free][CFX] & [War FX][WFX])
|
||||
* by [Jean Moreno (JMO)][JMO]
|
||||
|
||||
|
||||
|
||||
<br><br><br><br>
|
||||
|
||||
## Usage
|
||||
|
||||
### UIParticle component
|
||||
|
||||
`UIParticle` controls the ParticleSystems that is attached to its own game objects and child game objects.
|
||||
`UIParticle` controls the ParticleSystems that are attached to its own game objects and child game objects.
|
||||
|
||||

|
||||
|
||||
| Properties | Description |
|
||||
| -- | -- |
|
||||
| Maskable | Does this graphic allow masking. |
|
||||
| Scale | Scale the rendering.<br>When the `3D` toggle is enabled, 3D scale (x,y,z) is supported. |
|
||||
| Animatable Properties | If you want update material properties (e.g. `_MainTex_ST`, `_Color`) in AnimationClip, use this to mark the changes. |
|
||||
| Mesh Sharing | Particle simulation results are shared within the same group.<br>A large number of the same effects can be displayed with a small load.<br>When the `Random` toggle is enabled, it will be grouped randomaly. |
|
||||
| Position Mode | **Absolute:** Emit from the world position of the `ParticleSystem`.<br>**Relative:** Emit from the scaled position of the `ParticleSystem`. |
|
||||
| Auto Scaling | Transform.lossyScale (=world scale) will be set to `(1, 1, 1)` on update.<br>It prevents the root-Canvas scale from affecting the hierarchy-scaled `ParticleSystem`. |
|
||||
| Rendering Order | The ParticleSystem list to be rendered.<br>You can change the order and the materials. |
|
||||
- **Maskable**: Does this graphic allow masking.
|
||||
- **Scale**: Scale the rendering. When the `3D` toggle is enabled, 3D scale (x, y, z) is supported.
|
||||
- **Animatable Properties**: If you want to update material properties (e.g., `_MainTex_ST`, `_Color`) in AnimationClip,
|
||||
use this to mark the changes.
|
||||
- **Mesh Sharing**: Particle simulation results are shared within the same group. A large number of the same effects can
|
||||
be displayed with a small load. When the `Random` toggle is enabled, it will be grouped randomly.
|
||||
- **Position Mode**: Emission position mode.
|
||||
- **Absolute:** Emit from the world position of the `ParticleSystem`.
|
||||
- **Relative:** Emit from the scaled position of the `ParticleSystem`.
|
||||
- **Auto Scaling**: `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`.
|
||||
- **Rendering Order**: The ParticleSystem list to be rendered. 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 the `Refresh` button to reconstruct the rendering order based on children ParticleSystem's sorting order
|
||||
and z-position.
|
||||
|
||||
<br><br>
|
||||
|
||||
### Basically usage
|
||||
#### Basic Usage
|
||||
|
||||
1. Select `Game Object/UI/ParticleSystem` to create UIParticle with a ParticleSystem.
|
||||

|
||||
2. Adjust the ParticleSystem as you like.
|
||||

|
||||
1. Select `GameObject/UI/ParticleSystem` to create UIParticle with a ParticleSystem.
|
||||

|
||||
2. Adjust the ParticleSystem as you like.
|
||||

|
||||
|
||||
<br><br>
|
||||
<br>
|
||||
|
||||
### With your existing ParticleSystem prefab
|
||||
#### With Your Existing ParticleSystem Prefab
|
||||
|
||||
1. Select `Game Object/UI/ParticleSystem (Empty)` to create UIParticle.
|
||||

|
||||
2. Drag & drop your ParticleSystem prefab on UIParticle.
|
||||

|
||||
1. Select `GameObject/UI/ParticleSystem (Empty)` to create UIParticle.
|
||||

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

|
||||
|
||||
<br><br>
|
||||
<br>
|
||||
|
||||
### With `Mask` or `RectMask2D` component
|
||||
#### With `Mask` or `RectMask2D` Component
|
||||
|
||||
If you want to mask particles, set a stencil supported shader (such as `UI/UIAdditive`) to material for ParticleSystem.
|
||||
If you use some custom shaders, see [How to make a custom shader to support Mask/RectMask2D component](#how-to-make-a-custom-shader-to-support-maskrectmask2d-component) section.
|
||||
If you want to mask particles, set a stencil-supported shader (such as `UI/UIAdditive`) to the material for
|
||||
ParticleSystem.
|
||||
If you use some custom shaders, see
|
||||
the [How to Make a Custom Shader to Support Mask/RectMask2D Component](#how-to-make-a-custom-shader-to-support-maskrectmask2d-component)
|
||||
section.
|
||||
|
||||

|
||||
|
||||
|
||||
<br><br>
|
||||
|
||||
### Script usage
|
||||
@@ -232,43 +198,108 @@ uiParticle.Stop();
|
||||

|
||||

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

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

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

|
||||
- :+1: Maskable.
|
||||
- :+1: Sortable.
|
||||
- :-1: Adjustment is difficult.
|
||||
- :-1: Requires UI shaders.
|
||||
- :-1: Difficult to adjust scale.
|
||||
- :-1: Force hierarchy scalling.
|
||||
- :-1: Simulation results are incorrect.
|
||||
- :-1: Trail, rotation of transform, time scaling are not supported.
|
||||
- :-1: Generate heavy GC every frame.
|
||||
|
||||
- **Use Canvas to sort (Sorting By Canvas )**
|
||||

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

|
||||
- :+1: Maskable.
|
||||
- :+1: Sortable.
|
||||
- :-1: Requires Camera and RenderTexture.
|
||||
- :-1: Difficult to adjust position and size.
|
||||
- :-1: Quality depends on the RenderTexture's setting.
|
||||
|
||||
[UIParticleSystem]: https://forum.unity.com/threads/free-script-particle-systems-in-ui-screen-space-overlay.406862/
|
||||
|
||||
#### [Performance test results](https://github.com/mob-sakai/ParticleEffectForUGUI/issues/193#issuecomment-1160028374)
|
||||
|
||||
| Approach | FPS on Editor | FPS on iPhone6 | FPS on Xperia XZ |
|
||||
|-----------------------------|---------------|----------------|------------------|
|
||||
| Particle System | 43 | 57 | 22 |
|
||||
| UIParticleSystem | 4 | 3 | 0 (unmeasurable) |
|
||||
| Sorting By Canvas | 43 | 44 | 18 |
|
||||
| UIParticle | 17 | 12 | 4 |
|
||||
| UIParticle with MeshSharing | 44 | 45 | 30 |
|
||||
|
||||
### 🔍 FAQ: Why Are My UIParticles Not Displayed Correctly?
|
||||
|
||||
If `ParticleSystem` alone displays particles correctly but `UIParticle` does not, please check the following points:
|
||||
|
||||
* [Shader Limitation](https://github.com/mob-sakai/ParticleEffectForUGUI#shader-limitation)
|
||||
* Most cases can be solved by using `UI/Additive` or `UI/Default`.
|
||||
* Particles are masked
|
||||
* `UIParticle` is maskable.
|
||||
* Set `Mask` or `RectMask2D` component properly.
|
||||
* Particles are too small
|
||||
* If particles are small enough, they will not appear on the screen.
|
||||
* Increase the `Scale` value.
|
||||
* If you don't want to change the apparent size depending on the resolution, try `Auto Scaling` option.
|
||||
* Particles are too many
|
||||
* No more than 65535 vertices can be displayed (for mesh combination limitations).
|
||||
* Please set `Emission` module and `Max Particles` of ParticleSystem properly.
|
||||
* Particles are emitted off-screen.
|
||||
* When `Position Mode = Relative`, particles are emitted from scaled position of the ParticleSystem, not from the screen point of the ParticleSystem.
|
||||
* Place the ParticleSystem in the proper position or try `Position Mode = Absolute`.
|
||||
* Attaching `UIParticle` to the same object as `ParticleSystem`
|
||||
* `Transform.localScale` will be overridden by `Auto Scaling` option.
|
||||
* It is recommended to place `ParticleSystem` under `UIParticle`.
|
||||
|
||||
- [Shader Limitation](#shader-limitation)
|
||||
- `UIParticle` does not support all built-in shaders except for `UI/Default`.
|
||||
- Most cases can be solved by using `UI/Additive` or `UI/Default`.
|
||||
- Particles are not masked
|
||||
- `UIParticle` is maskable.
|
||||
- Set `Mask` or `RectMask2D` component properly.
|
||||
- [Use maskable/clipable shader](#how-to-make-a-custom-shader-to-support-maskrectmask2d-component) (such
|
||||
as `UI/Additive` or `UI/Default`)
|
||||
- Particles are too small
|
||||
- If particles are small enough, they will not appear on the screen.
|
||||
- Increase the `Scale` value.
|
||||
- If you don't want to change the apparent size depending on the resolution, try the `Auto Scaling` option.
|
||||
- Particles are too many
|
||||
- No more than 65535 vertices can be displayed (for mesh combination limitations).
|
||||
- Please set `Emission` module and `Max Particles` of ParticleSystem properly.
|
||||
- Particles are emitted off-screen.
|
||||
- When `Position Mode = Relative`, particles are emitted from the scaled position of the ParticleSystem, not from
|
||||
the screen point of the ParticleSystem.
|
||||
- Place the ParticleSystem in the proper position or try `Position Mode = Absolute`.
|
||||
- Attaching `UIParticle` to the same object as `ParticleSystem`
|
||||
- `Transform.localScale` will be overridden by the `Auto Scaling` option.
|
||||
- It is recommended to place `ParticleSystem` under `UIParticle`.
|
||||
- If `Transform.localScale` contains 0, rendering will be skipped.
|
||||
- Displayed particles are in the correct position but too large/too small
|
||||
- Adjust `ParticleSystem.renderer.Min/MaxParticleSize`.
|
||||
|
||||
<br>
|
||||
|
||||
@@ -282,35 +313,37 @@ The use of UI shaders is recommended.
|
||||
|
||||
#### Built-in shaders are not supported
|
||||
|
||||
UIParticle does not support all built-in shaders except for `UI/Default`.
|
||||
`UIParticle` does not support all built-in shaders except for `UI/Default`.
|
||||
If their use is detected, an error is displayed in the inspector.
|
||||
Use UI shaders instead.
|
||||
|
||||
#### (2019.4 or earlier) UV.zw components will be discarded
|
||||
#### (Unity 2018 or 2019) UV.zw components will be discarded
|
||||
|
||||
UIParticleRenderer renders the particles based on UIVertex.
|
||||
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.
|
||||
Therefore, only the xy components are available for each UV in the shader. (zw components will be discarded).
|
||||
So unfortunately, UIParticles will not work well with some shaders.
|
||||
|
||||
#### (2019.4 or earlier) Custom vertex streams
|
||||
#### (Unity 2018 or 2019) Custom vertex streams
|
||||
|
||||
When using custom vertex streams, you can fill zw components with "unnecessary" data.
|
||||
https://github.com/mob-sakai/ParticleEffectForUGUI/issues/191
|
||||
|
||||
Refer to [this issue](https://github.com/mob-sakai/ParticleEffectForUGUI/issues/191) for more information.
|
||||
|
||||
<br>
|
||||
|
||||
### Overheads
|
||||
|
||||
UIParticle has some overheads and the batching depends on uGUI.
|
||||
UIParticle has some overheads, and the batching depends on uGUI.
|
||||
When improving performance, keep the following in mind:
|
||||
- If you are displaying a large number of the same effect, consider `Mesh Sharing` feature in [UIParticle Component](#uiparticle-component).
|
||||
- If you don't like the uniform output, consider `Random Group` feature.
|
||||

|
||||
- If you are using multiple materials, you will have more draw calls.
|
||||
- Consider single material, atlasing the sprites, and using `Sprite` mode in the `Texture Sheet Animation` module in ParticleSystem.
|
||||
|
||||
### How to make a custom shader to support Mask/RectMask2D component
|
||||
- If you are displaying a large number of the same effect, consider the `Mesh Sharing` feature in
|
||||
the [UIParticle Component](#uiparticle-component).
|
||||
- If you don't like the uniform output, consider the `Random Group` feature.
|
||||

|
||||
- If you are using multiple materials, you will have more draw calls.
|
||||
- Consider a single material, atlasing the sprites, and using `Sprite` mode in the `Texture Sheet Animation` module
|
||||
in the ParticleSystem.
|
||||
|
||||
### How to Make a Custom Shader to Support Mask/RectMask2D Component
|
||||
|
||||
<details>
|
||||
<summary>Shader tips</summary>
|
||||
@@ -402,54 +435,49 @@ Shader "Your/Custom/Shader"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
<br><br>
|
||||
|
||||
<br><br><br><br>
|
||||
|
||||
## Contributing
|
||||
## 🤝 Contributing
|
||||
|
||||
### Issues
|
||||
|
||||
Issues are very valuable to this project.
|
||||
Issues are incredibly valuable to this project:
|
||||
|
||||
- Ideas are a valuable source of contributions others can make
|
||||
- Problems show where this project is lacking
|
||||
- With a question you show where contributors can improve the user experience
|
||||
- Ideas provide a valuable source of contributions that others can make.
|
||||
- Problems help identify areas where this project needs improvement.
|
||||
- Questions indicate where contributors can enhance the user experience.
|
||||
|
||||
### Pull Requests
|
||||
|
||||
Pull requests are, a great way to get your ideas into this repository.
|
||||
See [CONTRIBUTING.md](/../../blob/develop/CONTRIBUTING.md).
|
||||
Pull requests offer a fantastic way to contribute your ideas to this repository.
|
||||
Please refer to [CONTRIBUTING.md](https://github.com/mob-sakai/ParticleEffectForUGUI/blob/main/CONTRIBUTING.md)
|
||||
and [develop branch](https://github.com/mob-sakai/ParticleEffectForUGUI/tree/develop) for guidelines.
|
||||
|
||||
### Support
|
||||
|
||||
This is an open source project that I am developing in my spare time.
|
||||
If you like it, please support me.
|
||||
With your support, I can spend more time on development. :)
|
||||
This is an open-source project developed during my spare time.
|
||||
If you appreciate it, consider supporting me.
|
||||
Your support allows me to dedicate more time to development. 😊
|
||||
|
||||
[](https://www.patreon.com/join/mob_sakai?)
|
||||
[](https://www.patreon.com/join/2343451?)
|
||||
[](https://github.com/users/mob-sakai/sponsorship)
|
||||
|
||||
|
||||
|
||||
<br><br><br><br>
|
||||
<br><br>
|
||||
|
||||
## License
|
||||
|
||||
* MIT
|
||||
|
||||
|
||||
|
||||
## Author
|
||||
|
||||
*  [mob-sakai](https://github.com/mob-sakai) [](https://twitter.com/intent/follow?screen_name=mob_sakai) 
|
||||
|
||||
|
||||
|
||||
## See Also
|
||||
|
||||
* GitHub page : https://github.com/mob-sakai/ParticleEffectForUGUI
|
||||
* Releases : https://github.com/mob-sakai/ParticleEffectForUGUI/releases
|
||||
* Issue tracker : https://github.com/mob-sakai/ParticleEffectForUGUI/issues
|
||||
* Change log : https://github.com/mob-sakai/ParticleEffectForUGUI/blob/upm/CHANGELOG.md
|
||||
* Change log : https://github.com/mob-sakai/ParticleEffectForUGUI/blob/main/CHANGELOG.md
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
using System;
|
||||
using System;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Coffee.UIExtensions
|
||||
@@ -19,10 +19,7 @@ namespace Coffee.UIExtensions
|
||||
[SerializeField] private ShaderPropertyType m_Type = ShaderPropertyType.Vector;
|
||||
public int id { get; private set; }
|
||||
|
||||
public ShaderPropertyType type
|
||||
{
|
||||
get { return m_Type; }
|
||||
}
|
||||
public ShaderPropertyType type => m_Type;
|
||||
|
||||
void ISerializationCallbackReceiver.OnBeforeSerialize()
|
||||
{
|
||||
@@ -1,4 +1,4 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Coffee.UIParticleExtensions
|
||||
@@ -28,7 +28,7 @@ namespace Coffee.UIParticleExtensions
|
||||
customMat = new Material(baseMat)
|
||||
{
|
||||
name = $"{baseMat.name}_{id}",
|
||||
hideFlags = HideFlags.HideAndDontSave,
|
||||
hideFlags = HideFlags.DontSave | HideFlags.NotEditable,
|
||||
mainTexture = texture ? texture : null
|
||||
}
|
||||
};
|
||||
@@ -21,6 +21,13 @@ namespace Coffee.UIExtensions
|
||||
[RequireComponent(typeof(CanvasRenderer))]
|
||||
public class UIParticle : MaskableGraphic, ISerializationCallbackReceiver
|
||||
{
|
||||
public enum AutoScalingMode
|
||||
{
|
||||
None,
|
||||
UIParticle,
|
||||
Transform
|
||||
}
|
||||
|
||||
public enum MeshSharing
|
||||
{
|
||||
None,
|
||||
@@ -36,13 +43,6 @@ namespace Coffee.UIExtensions
|
||||
Absolute
|
||||
}
|
||||
|
||||
public enum AutoScalingMode
|
||||
{
|
||||
None,
|
||||
UIParticle,
|
||||
Transform
|
||||
}
|
||||
|
||||
[HideInInspector]
|
||||
[SerializeField]
|
||||
internal bool m_IsTrail;
|
||||
@@ -113,7 +113,7 @@ namespace Coffee.UIExtensions
|
||||
/// </summary>
|
||||
public override bool raycastTarget
|
||||
{
|
||||
get { return false; }
|
||||
get => false;
|
||||
set { }
|
||||
}
|
||||
|
||||
@@ -127,8 +127,8 @@ namespace Coffee.UIExtensions
|
||||
/// </summary>
|
||||
public MeshSharing meshSharing
|
||||
{
|
||||
get { return m_MeshSharing; }
|
||||
set { m_MeshSharing = value; }
|
||||
get => m_MeshSharing;
|
||||
set => m_MeshSharing = value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -137,7 +137,7 @@ namespace Coffee.UIExtensions
|
||||
/// </summary>
|
||||
public int groupId
|
||||
{
|
||||
get { return _groupId; }
|
||||
get => _groupId;
|
||||
set
|
||||
{
|
||||
if (m_GroupId == value) return;
|
||||
@@ -151,7 +151,7 @@ namespace Coffee.UIExtensions
|
||||
|
||||
public int groupMaxId
|
||||
{
|
||||
get { return m_GroupMaxId; }
|
||||
get => m_GroupMaxId;
|
||||
set
|
||||
{
|
||||
if (m_GroupMaxId == value) return;
|
||||
@@ -167,8 +167,8 @@ namespace Coffee.UIExtensions
|
||||
/// </summary>
|
||||
public PositionMode positionMode
|
||||
{
|
||||
get { return m_PositionMode; }
|
||||
set { m_PositionMode = value; }
|
||||
get => m_PositionMode;
|
||||
set => m_PositionMode = value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -178,8 +178,8 @@ namespace Coffee.UIExtensions
|
||||
/// </summary>
|
||||
public bool absoluteMode
|
||||
{
|
||||
get { return m_PositionMode == PositionMode.Absolute; }
|
||||
set { positionMode = value ? PositionMode.Absolute : PositionMode.Relative; }
|
||||
get => m_PositionMode == PositionMode.Absolute;
|
||||
set => positionMode = value ? PositionMode.Absolute : PositionMode.Relative;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -188,11 +188,8 @@ namespace Coffee.UIExtensions
|
||||
[Obsolete("The autoScaling is now obsolete. Please use the autoScalingMode instead.", false)]
|
||||
public bool autoScaling
|
||||
{
|
||||
get { return m_AutoScalingMode != AutoScalingMode.None; }
|
||||
set
|
||||
{
|
||||
autoScalingMode = value ? AutoScalingMode.Transform : AutoScalingMode.None;
|
||||
}
|
||||
get => m_AutoScalingMode != AutoScalingMode.None;
|
||||
set => autoScalingMode = value ? AutoScalingMode.Transform : AutoScalingMode.None;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -202,7 +199,7 @@ namespace Coffee.UIExtensions
|
||||
/// </summary>
|
||||
public AutoScalingMode autoScalingMode
|
||||
{
|
||||
get { return m_AutoScalingMode; }
|
||||
get => m_AutoScalingMode;
|
||||
set
|
||||
{
|
||||
if (m_AutoScalingMode == value) return;
|
||||
@@ -211,49 +208,31 @@ namespace Coffee.UIExtensions
|
||||
}
|
||||
}
|
||||
|
||||
internal bool useMeshSharing
|
||||
{
|
||||
get { return m_MeshSharing != MeshSharing.None; }
|
||||
}
|
||||
internal bool useMeshSharing => m_MeshSharing != MeshSharing.None;
|
||||
|
||||
internal bool isPrimary
|
||||
{
|
||||
get
|
||||
{
|
||||
return m_MeshSharing == MeshSharing.Primary
|
||||
|| m_MeshSharing == MeshSharing.PrimarySimulator;
|
||||
}
|
||||
}
|
||||
internal bool isPrimary =>
|
||||
m_MeshSharing == MeshSharing.Primary
|
||||
|| m_MeshSharing == MeshSharing.PrimarySimulator;
|
||||
|
||||
internal bool canSimulate
|
||||
{
|
||||
get
|
||||
{
|
||||
return m_MeshSharing == MeshSharing.None
|
||||
|| m_MeshSharing == MeshSharing.Auto
|
||||
|| m_MeshSharing == MeshSharing.Primary
|
||||
|| m_MeshSharing == MeshSharing.PrimarySimulator;
|
||||
}
|
||||
}
|
||||
internal bool canSimulate =>
|
||||
m_MeshSharing == MeshSharing.None
|
||||
|| m_MeshSharing == MeshSharing.Auto
|
||||
|| m_MeshSharing == MeshSharing.Primary
|
||||
|| m_MeshSharing == MeshSharing.PrimarySimulator;
|
||||
|
||||
internal bool canRender
|
||||
{
|
||||
get
|
||||
{
|
||||
return m_MeshSharing == MeshSharing.None
|
||||
|| m_MeshSharing == MeshSharing.Auto
|
||||
|| m_MeshSharing == MeshSharing.Primary
|
||||
|| m_MeshSharing == MeshSharing.Replica;
|
||||
}
|
||||
}
|
||||
internal bool canRender =>
|
||||
m_MeshSharing == MeshSharing.None
|
||||
|| m_MeshSharing == MeshSharing.Auto
|
||||
|| m_MeshSharing == MeshSharing.Primary
|
||||
|| m_MeshSharing == MeshSharing.Replica;
|
||||
|
||||
/// <summary>
|
||||
/// Particle effect scale.
|
||||
/// </summary>
|
||||
public float scale
|
||||
{
|
||||
get { return m_Scale3D.x; }
|
||||
set { m_Scale3D = new Vector3(value, value, value); }
|
||||
get => m_Scale3D.x;
|
||||
set => m_Scale3D = new Vector3(value, value, value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -261,22 +240,18 @@ namespace Coffee.UIExtensions
|
||||
/// </summary>
|
||||
public Vector3 scale3D
|
||||
{
|
||||
get { return m_Scale3D; }
|
||||
set { m_Scale3D = value; }
|
||||
get => m_Scale3D;
|
||||
set => m_Scale3D = value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Particle effect scale.
|
||||
/// </summary>
|
||||
public Vector3 scale3DForCalc
|
||||
{
|
||||
get { return autoScalingMode == AutoScalingMode.UIParticle ? m_Scale3D.GetScaled(canvasScale) : m_Scale3D; }
|
||||
}
|
||||
public Vector3 scale3DForCalc => autoScalingMode == AutoScalingMode.UIParticle
|
||||
? m_Scale3D.GetScaled(canvasScale)
|
||||
: m_Scale3D;
|
||||
|
||||
public List<ParticleSystem> particles
|
||||
{
|
||||
get { return m_Particles; }
|
||||
}
|
||||
public List<ParticleSystem> particles => m_Particles;
|
||||
|
||||
/// <summary>
|
||||
/// Get all base materials to render.
|
||||
@@ -294,10 +269,7 @@ namespace Coffee.UIExtensions
|
||||
}
|
||||
}
|
||||
|
||||
public override Material materialForRendering
|
||||
{
|
||||
get { return null; }
|
||||
}
|
||||
public override Material materialForRendering => null;
|
||||
|
||||
/// <summary>
|
||||
/// Paused.
|
||||
@@ -565,16 +537,6 @@ namespace Coffee.UIExtensions
|
||||
}
|
||||
}
|
||||
|
||||
internal void UpdateParticleCount()
|
||||
{
|
||||
for (var i = 0; i < _renderers.Count; i++)
|
||||
{
|
||||
var r = _renderers[i];
|
||||
if (!r) continue;
|
||||
r.UpdateParticleCount();
|
||||
}
|
||||
}
|
||||
|
||||
internal void ResetGroupId()
|
||||
{
|
||||
_groupId = m_GroupId == m_GroupMaxId
|
||||
@@ -647,7 +609,10 @@ namespace Coffee.UIExtensions
|
||||
// Create ortho-camera.
|
||||
if (!_orthoCamera)
|
||||
{
|
||||
var go = new GameObject("[generated] UIParticleOverlayCamera") { hideFlags = HideFlags.DontSave | HideFlags.NotEditable };
|
||||
var go = new GameObject("[generated] UIParticleOverlayCamera")
|
||||
{
|
||||
hideFlags = HideFlags.HideAndDontSave
|
||||
};
|
||||
go.SetActive(false);
|
||||
go.transform.SetParent(transform, false);
|
||||
_orthoCamera = go.AddComponent<Camera>();
|
||||
@@ -5,7 +5,7 @@ MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
icon: {fileID: 2800000, guid: 5f0675613942149309588d556e33d990, type: 3}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,4 +1,4 @@
|
||||
using System;
|
||||
using System;
|
||||
using Coffee.UIParticleExtensions;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Events;
|
||||
@@ -49,47 +49,46 @@ namespace Coffee.UIExtensions
|
||||
|
||||
public float destinationRadius
|
||||
{
|
||||
get { return m_DestinationRadius; }
|
||||
set { m_DestinationRadius = Mathf.Clamp(value, 0.1f, 10f); }
|
||||
get => m_DestinationRadius;
|
||||
set => m_DestinationRadius = Mathf.Clamp(value, 0.1f, 10f);
|
||||
}
|
||||
|
||||
public float delay
|
||||
{
|
||||
get { return m_DelayRate; }
|
||||
set { m_DelayRate = value; }
|
||||
get => m_DelayRate;
|
||||
set => m_DelayRate = value;
|
||||
}
|
||||
|
||||
public float maxSpeed
|
||||
{
|
||||
get { return m_MaxSpeed; }
|
||||
set { m_MaxSpeed = value; }
|
||||
get => m_MaxSpeed;
|
||||
set => m_MaxSpeed = value;
|
||||
}
|
||||
|
||||
public Movement movement
|
||||
{
|
||||
get { return m_Movement; }
|
||||
set { m_Movement = value; }
|
||||
get => m_Movement;
|
||||
set => m_Movement = value;
|
||||
}
|
||||
|
||||
public UpdateMode updateMode
|
||||
{
|
||||
get { return m_UpdateMode; }
|
||||
set { m_UpdateMode = value; }
|
||||
get => m_UpdateMode;
|
||||
set => m_UpdateMode = value;
|
||||
}
|
||||
|
||||
public UnityEvent onAttracted
|
||||
{
|
||||
get { return m_OnAttracted; }
|
||||
set { m_OnAttracted = value; }
|
||||
get => m_OnAttracted;
|
||||
set => m_OnAttracted = value;
|
||||
}
|
||||
|
||||
#if UNITY_EDITOR
|
||||
/// <summary>
|
||||
/// The target ParticleSystem to attract.
|
||||
/// </summary>
|
||||
public new ParticleSystem particleSystem
|
||||
#else
|
||||
public ParticleSystem particleSystem
|
||||
#endif
|
||||
{
|
||||
get { return m_ParticleSystem; }
|
||||
get => m_ParticleSystem;
|
||||
set
|
||||
{
|
||||
m_ParticleSystem = value;
|
||||
@@ -1,4 +1,10 @@
|
||||
using System;
|
||||
#if UNITY_2022_3_0 || UNITY_2022_3_1 || UNITY_2022_3_2 || UNITY_2022_3_3 || UNITY_2022_3_4 || UNITY_2022_3_5 || UNITY_2022_3_6 || UNITY_2022_3_7 || UNITY_2022_3_8 || UNITY_2022_3_9 || UNITY_2022_3_10
|
||||
#elif UNITY_2023_1_0 || UNITY_2023_1_1 || UNITY_2023_1_2 || UNITY_2023_1_3 || UNITY_2023_1_4 || UNITY_2023_1_5 || UNITY_2023_1_6 || UNITY_2023_1_7 || UNITY_2023_1_8 || UNITY_2023_1_9
|
||||
#elif UNITY_2023_1_10 || UNITY_2023_1_11 || UNITY_2023_1_12 || UNITY_2023_1_13 || UNITY_2023_1_14 || UNITY_2023_1_15 || UNITY_2023_1_16
|
||||
#elif UNITY_2022_3_OR_NEWER
|
||||
#define PS_BAKE_API_V2
|
||||
#endif
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Coffee.UIParticleExtensions;
|
||||
using UnityEditor;
|
||||
@@ -30,23 +36,16 @@ namespace Coffee.UIExtensions
|
||||
private Material _modifiedMaterial;
|
||||
private UIParticle _parent;
|
||||
private ParticleSystem _particleSystem;
|
||||
private int _prevParticleCount;
|
||||
private float _prevCanvasScale;
|
||||
private Vector3 _prevPsPos;
|
||||
private Vector3 _prevScale;
|
||||
private Vector2Int _prevScreenSize;
|
||||
private float _prevCanvasScale;
|
||||
private bool _prewarm;
|
||||
private ParticleSystemRenderer _renderer;
|
||||
|
||||
public override Texture mainTexture
|
||||
{
|
||||
get { return _isTrail ? null : _particleSystem.GetTextureForSprite(); }
|
||||
}
|
||||
public override Texture mainTexture => _isTrail ? null : _particleSystem.GetTextureForSprite();
|
||||
|
||||
public override bool raycastTarget
|
||||
{
|
||||
get { return false; }
|
||||
}
|
||||
public override bool raycastTarget => false;
|
||||
|
||||
private Rect rootCanvasRect
|
||||
{
|
||||
@@ -102,7 +101,6 @@ namespace Coffee.UIExtensions
|
||||
_parent = null;
|
||||
_particleSystem = null;
|
||||
_renderer = null;
|
||||
_prevParticleCount = 0;
|
||||
if (0 <= index)
|
||||
{
|
||||
_index = index;
|
||||
@@ -155,7 +153,7 @@ namespace Coffee.UIExtensions
|
||||
// Create renderer object.
|
||||
var go = new GameObject("[generated] UIParticleRenderer", typeof(UIParticleRenderer))
|
||||
{
|
||||
hideFlags = HideFlags.DontSave | HideFlags.NotEditable,
|
||||
hideFlags = HideFlags.HideAndDontSave,
|
||||
layer = parent.gameObject.layer
|
||||
};
|
||||
|
||||
@@ -256,7 +254,6 @@ namespace Coffee.UIExtensions
|
||||
_prevScreenSize = new Vector2Int(Screen.width, Screen.height);
|
||||
_prevCanvasScale = canvas ? canvas.scaleFactor : 1f;
|
||||
_delay = true;
|
||||
_prevParticleCount = 0;
|
||||
|
||||
canvasRenderer.SetTexture(null);
|
||||
|
||||
@@ -333,11 +330,22 @@ namespace Coffee.UIExtensions
|
||||
Profiler.BeginSample("[UIParticleRenderer] Bake Mesh");
|
||||
if (_isTrail && _parent.canSimulate && 0 < s_CombineInstances[0].mesh.vertexCount)
|
||||
{
|
||||
#if PS_BAKE_API_V2
|
||||
_renderer.BakeTrailsMesh(s_CombineInstances[0].mesh, bakeCamera,
|
||||
ParticleSystemBakeMeshOptions.BakeRotationAndScale);
|
||||
#else
|
||||
_renderer.BakeTrailsMesh(s_CombineInstances[0].mesh, bakeCamera, true);
|
||||
#endif
|
||||
}
|
||||
else if (_renderer.CanBakeMesh())
|
||||
{
|
||||
_particleSystem.ValidateShape();
|
||||
#if PS_BAKE_API_V2
|
||||
_renderer.BakeMesh(s_CombineInstances[0].mesh, bakeCamera,
|
||||
ParticleSystemBakeMeshOptions.BakeRotationAndScale);
|
||||
#else
|
||||
_renderer.BakeMesh(s_CombineInstances[0].mesh, bakeCamera, true);
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -405,6 +413,7 @@ namespace Coffee.UIExtensions
|
||||
c.b = c.b.LinearToGamma();
|
||||
s_Colors[i] = c;
|
||||
}
|
||||
|
||||
workerMesh.SetColors(s_Colors);
|
||||
Profiler.EndSample();
|
||||
}
|
||||
@@ -459,7 +468,7 @@ namespace Coffee.UIExtensions
|
||||
SetMaterialDirty();
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
UpdateMaterialProperties();
|
||||
if (_parent.useMeshSharing)
|
||||
{
|
||||
@@ -482,12 +491,6 @@ namespace Coffee.UIExtensions
|
||||
s_Renderers.Clear();
|
||||
}
|
||||
|
||||
internal void UpdateParticleCount()
|
||||
{
|
||||
if (!_particleSystem) return;
|
||||
_prevParticleCount = _particleSystem.particleCount;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Call to update the geometry of the Graphic onto the CanvasRenderer.
|
||||
/// </summary>
|
||||
@@ -614,25 +617,6 @@ namespace Coffee.UIExtensions
|
||||
_prewarm = false;
|
||||
}
|
||||
|
||||
// (COMMENT OUT) #231: Sub Emitters option is not work in editor playing
|
||||
/*
|
||||
// Emitted particles found.
|
||||
if (_prevParticleCount != _particleSystem.particleCount)
|
||||
{
|
||||
var size = _particleSystem.particleCount;
|
||||
var particles = ParticleSystemExtensions.GetParticleArray(size);
|
||||
_particleSystem.GetParticles(particles, size);
|
||||
for (var i = _prevParticleCount; i < size; i++)
|
||||
{
|
||||
var p = particles[i];
|
||||
p.position = p.position.GetScaled(scale.Inverse());
|
||||
particles[i] = p;
|
||||
}
|
||||
|
||||
_particleSystem.SetParticles(particles, size);
|
||||
}
|
||||
*/
|
||||
|
||||
// get world position.
|
||||
var isLocalSpace = _particleSystem.IsLocalSpace();
|
||||
var psTransform = _particleSystem.transform;
|
||||
@@ -11,10 +11,7 @@ namespace Coffee.UIExtensions
|
||||
private static readonly HashSet<int> s_UpdatedGroupIds = new HashSet<int>();
|
||||
private static int s_FrameCount;
|
||||
|
||||
public static int uiParticleCount
|
||||
{
|
||||
get { return s_ActiveParticles.Count; }
|
||||
}
|
||||
public static int uiParticleCount => s_ActiveParticles.Count;
|
||||
|
||||
public static void Register(UIParticle particle)
|
||||
{
|
||||
@@ -93,15 +90,6 @@ namespace Coffee.UIExtensions
|
||||
{
|
||||
s_ActiveAttractors[i].Attract();
|
||||
}
|
||||
|
||||
// UpdateParticleCount.
|
||||
for (var i = 0; i < s_ActiveParticles.Count; i++)
|
||||
{
|
||||
var uip = s_ActiveParticles[i];
|
||||
if (!uip || !uip.canvas) continue;
|
||||
|
||||
uip.UpdateParticleCount();
|
||||
}
|
||||
}
|
||||
|
||||
public static void GetGroupedRenderers(int groupId, int index, List<UIParticleRenderer> results)
|
||||
@@ -1,4 +1,4 @@
|
||||
using System;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Reflection;
|
||||
using UnityEngine;
|
||||
@@ -109,6 +109,29 @@ namespace Coffee.UIParticleExtensions
|
||||
return s_TmpParticles;
|
||||
}
|
||||
|
||||
public static void ValidateShape(this ParticleSystem self)
|
||||
{
|
||||
var shape = self.shape;
|
||||
if (shape.enabled && shape.alignToDirection)
|
||||
{
|
||||
if (Mathf.Approximately(shape.scale.x * shape.scale.y * shape.scale.z, 0))
|
||||
{
|
||||
if (Mathf.Approximately(shape.scale.x, 0))
|
||||
{
|
||||
shape.scale.Set(0.0001f, shape.scale.y, shape.scale.z);
|
||||
}
|
||||
else if (Mathf.Approximately(shape.scale.y, 0))
|
||||
{
|
||||
shape.scale.Set(shape.scale.x, 0.0001f, shape.scale.z);
|
||||
}
|
||||
else if (Mathf.Approximately(shape.scale.z, 0))
|
||||
{
|
||||
shape.scale.Set(shape.scale.x, shape.scale.y, 0.0001f);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static bool CanBakeMesh(this ParticleSystemRenderer self)
|
||||
{
|
||||
// #69: Editor crashes when mesh is set to null when `ParticleSystem.RenderMode = Mesh`
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,4 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 064daa6b97d6846ec9334e98d642f081
|
||||
DefaultImporter:
|
||||
userData:
|
||||
@@ -1,14 +0,0 @@
|
||||
{
|
||||
"name": "Coffee.CFX_Demo_With_UIParticle",
|
||||
"references": [
|
||||
"Coffee.UIParticle"
|
||||
],
|
||||
"optionalUnityReferences": [],
|
||||
"includePlatforms": [],
|
||||
"excludePlatforms": [],
|
||||
"allowUnsafeCode": false,
|
||||
"overrideReferences": false,
|
||||
"precompiledReferences": [],
|
||||
"autoReferenced": true,
|
||||
"defineConstraints": []
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 67b89587ad4f645e18aa12053a6cc9b7
|
||||
AssemblyDefinitionImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,87 +0,0 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using UnityEngine;
|
||||
using UnityEngine.SceneManagement;
|
||||
using UnityEngine.UI;
|
||||
using Object = UnityEngine.Object;
|
||||
|
||||
namespace Coffee.UIExtensions.Demo
|
||||
{
|
||||
public class CFX_Demo_With_UIParticle : MonoBehaviour
|
||||
{
|
||||
private MonoBehaviour _demo;
|
||||
private Toggle _spawnOnUI;
|
||||
private UIParticle _uiParticle;
|
||||
|
||||
// Start is called before the first frame update
|
||||
private void Start()
|
||||
{
|
||||
_uiParticle = GetComponentInChildren<UIParticle>();
|
||||
_spawnOnUI = GetComponentInChildren<Toggle>();
|
||||
_demo = FindObjectOfType("CFX_Demo_New") as MonoBehaviour
|
||||
?? FindObjectOfType("WFX_Demo_New") as MonoBehaviour;
|
||||
|
||||
SetCanvasWidth(800);
|
||||
SetCanvasRenderOverlay(true);
|
||||
}
|
||||
|
||||
// Update is called once per frame
|
||||
private void Update()
|
||||
{
|
||||
if (!_spawnOnUI.isOn || !_demo || !Input.GetMouseButtonDown(0)) return;
|
||||
|
||||
foreach (Transform child in _uiParticle.transform)
|
||||
{
|
||||
Destroy(child.gameObject);
|
||||
}
|
||||
|
||||
var particle = _demo.GetType()
|
||||
.GetMethod("spawnParticle", BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public)
|
||||
?.Invoke(_demo, Array.Empty<object>()) as GameObject;
|
||||
if (!particle) return;
|
||||
|
||||
particle.transform.localScale = Vector3.one;
|
||||
_uiParticle.SetParticleSystemInstance(particle);
|
||||
}
|
||||
|
||||
private static Object FindObjectOfType(string typeName)
|
||||
{
|
||||
var type = AppDomain.CurrentDomain.GetAssemblies()
|
||||
.SelectMany(x => x.GetTypes())
|
||||
.FirstOrDefault(x => x.Name == typeName);
|
||||
|
||||
return type == null ? null : FindObjectOfType(type);
|
||||
}
|
||||
|
||||
public void SetCanvasWidth(int width)
|
||||
{
|
||||
var scaler = GetComponentInParent<CanvasScaler>();
|
||||
scaler.screenMatchMode = CanvasScaler.ScreenMatchMode.MatchWidthOrHeight;
|
||||
scaler.matchWidthOrHeight = 0;
|
||||
var resolution = scaler.referenceResolution;
|
||||
resolution.x = width;
|
||||
scaler.referenceResolution = resolution;
|
||||
}
|
||||
|
||||
public void SetCanvasRenderOverlay(bool enable)
|
||||
{
|
||||
var canvas = GetComponentInParent<Canvas>();
|
||||
if (enable)
|
||||
{
|
||||
canvas.renderMode = RenderMode.ScreenSpaceOverlay;
|
||||
}
|
||||
else
|
||||
{
|
||||
canvas.worldCamera = Camera.main;
|
||||
canvas.renderMode = RenderMode.ScreenSpaceCamera;
|
||||
canvas.planeDistance = 5;
|
||||
}
|
||||
}
|
||||
|
||||
public void LoadScene(string scene)
|
||||
{
|
||||
SceneManager.LoadScene(scene);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: a845100b226da488ab9037ad254b5860
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,7 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 3432d66abba624d4fad1150154199656
|
||||
PrefabImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,4 +0,0 @@
|
||||
Cartoon FX & War FX Demo
|
||||
===
|
||||
|
||||
Please import assets "Cartoon FX Free" and/or "War FX Free" from Unity asset store.
|
||||
@@ -1,7 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 8f3407e8e4c3c4cf0a8717c25bc1c790
|
||||
TextScriptImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,4 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: a81f9cd434f104e1fad7ffa20eb7a3d4
|
||||
DefaultImporter:
|
||||
userData:
|
||||
@@ -1,4 +1,4 @@
|
||||
using UnityEngine;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Serialization;
|
||||
|
||||
namespace Coffee.UIExtensions.Demo
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
using System;
|
||||
using System;
|
||||
using UnityEngine;
|
||||
using UnityEngine.EventSystems;
|
||||
using UnityEngine.Serialization;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
using UnityEngine;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Serialization;
|
||||
using UnityEngine.UI;
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
using UnityEngine;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Serialization;
|
||||
|
||||
namespace Coffee.UIExtensions.Demo
|
||||
|
||||
@@ -1,8 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: ca0fd7c7ead2c49b1ae139b7963de126
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,8 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 839afb79f79094e6c942050ec5413ebf
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,88 +0,0 @@
|
||||
%YAML 1.1
|
||||
%TAG !u! tag:unity3d.com,2011:
|
||||
--- !u!21 &2100000
|
||||
Material:
|
||||
serializedVersion: 6
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_Name: UIParticle_PerformanceDemo_Fire
|
||||
m_Shader: {fileID: 4800000, guid: ecfa8f5732b504ef98fba10aa18d0326, type: 3}
|
||||
m_ShaderKeywords:
|
||||
m_LightmapFlags: 4
|
||||
m_EnableInstancingVariants: 0
|
||||
m_DoubleSidedGI: 0
|
||||
m_CustomRenderQueue: -1
|
||||
stringTagMap: {}
|
||||
disabledShaderPasses: []
|
||||
m_SavedProperties:
|
||||
serializedVersion: 3
|
||||
m_TexEnvs:
|
||||
- _BumpMap:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- _DetailAlbedoMap:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- _DetailMask:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- _DetailNormalMap:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- _EmissionMap:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- _MainTex:
|
||||
m_Texture: {fileID: 2800000, guid: 294c5667b05cc4edcac3885a5899cc65, type: 3}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- _MetallicGlossMap:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- _OcclusionMap:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- _ParallaxMap:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
m_Floats:
|
||||
- _BumpScale: 1
|
||||
- _ColorMask: 15
|
||||
- _Cutoff: 0.5
|
||||
- _DetailNormalMapScale: 1
|
||||
- _DstBlend: 0
|
||||
- _GlossMapScale: 1
|
||||
- _Glossiness: 0.5
|
||||
- _GlossyReflections: 1
|
||||
- _Glow: 1
|
||||
- _InvFade: 1
|
||||
- _Metallic: 0
|
||||
- _Mode: 0
|
||||
- _OcclusionStrength: 1
|
||||
- _Parallax: 0.02
|
||||
- _SmoothnessTextureChannel: 0
|
||||
- _SpecularHighlights: 1
|
||||
- _SrcBlend: 1
|
||||
- _Stencil: 0
|
||||
- _StencilComp: 8
|
||||
- _StencilOp: 0
|
||||
- _StencilReadMask: 255
|
||||
- _StencilWriteMask: 255
|
||||
- _UVSec: 0
|
||||
- _UseUIAlphaClip: 0
|
||||
- _ZWrite: 1
|
||||
m_Colors:
|
||||
- _ClipRect: {r: -32767, g: -32767, b: 32767, a: 32767}
|
||||
- _Color: {r: 1, g: 1, b: 1, a: 1}
|
||||
- _EmissionColor: {r: 0, g: 0, b: 0, a: 1}
|
||||
- _TintColor: {r: 1, g: 1, b: 1, a: 1}
|
||||
@@ -1,8 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 3dc66b79cada243e59bcaf09f804373d
|
||||
NativeFormatImporter:
|
||||
externalObjects: {}
|
||||
mainObjectFileID: 2100000
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 585 KiB |
@@ -1,121 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 294c5667b05cc4edcac3885a5899cc65
|
||||
TextureImporter:
|
||||
fileIDToRecycleName: {}
|
||||
externalObjects: {}
|
||||
serializedVersion: 9
|
||||
mipmaps:
|
||||
mipMapMode: 0
|
||||
enableMipMap: 1
|
||||
sRGBTexture: 1
|
||||
linearTexture: 0
|
||||
fadeOut: 0
|
||||
borderMipMap: 0
|
||||
mipMapsPreserveCoverage: 0
|
||||
alphaTestReferenceValue: 0.5
|
||||
mipMapFadeDistanceStart: 1
|
||||
mipMapFadeDistanceEnd: 3
|
||||
bumpmap:
|
||||
convertToNormalMap: 0
|
||||
externalNormalMap: 0
|
||||
heightScale: 0.25
|
||||
normalMapFilter: 0
|
||||
isReadable: 0
|
||||
streamingMipmaps: 0
|
||||
streamingMipmapsPriority: 0
|
||||
grayScaleToAlpha: 0
|
||||
generateCubemap: 6
|
||||
cubemapConvolution: 0
|
||||
seamlessCubemap: 0
|
||||
textureFormat: 1
|
||||
maxTextureSize: 2048
|
||||
textureSettings:
|
||||
serializedVersion: 2
|
||||
filterMode: 2
|
||||
aniso: 16
|
||||
mipBias: -100
|
||||
wrapU: -1
|
||||
wrapV: -1
|
||||
wrapW: -1
|
||||
nPOTScale: 1
|
||||
lightmap: 0
|
||||
compressionQuality: 50
|
||||
spriteMode: 0
|
||||
spriteExtrude: 1
|
||||
spriteMeshType: 1
|
||||
alignment: 0
|
||||
spritePivot: {x: 0.5, y: 0.5}
|
||||
spritePixelsToUnits: 100
|
||||
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
|
||||
spriteGenerateFallbackPhysicsShape: 1
|
||||
alphaUsage: 1
|
||||
alphaIsTransparency: 0
|
||||
spriteTessellationDetail: -1
|
||||
textureType: 0
|
||||
textureShape: 1
|
||||
singleChannelComponent: 0
|
||||
maxTextureSizeSet: 0
|
||||
compressionQualitySet: 0
|
||||
textureFormatSet: 0
|
||||
platformSettings:
|
||||
- serializedVersion: 2
|
||||
buildTarget: DefaultTexturePlatform
|
||||
maxTextureSize: 4096
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 2
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
- serializedVersion: 2
|
||||
buildTarget: Standalone
|
||||
maxTextureSize: 4096
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 2
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
- serializedVersion: 2
|
||||
buildTarget: Android
|
||||
maxTextureSize: 4096
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 2
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
- serializedVersion: 2
|
||||
buildTarget: WebGL
|
||||
maxTextureSize: 4096
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 2
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
spriteSheet:
|
||||
serializedVersion: 2
|
||||
sprites: []
|
||||
outline: []
|
||||
physicsShape: []
|
||||
bones: []
|
||||
spriteID:
|
||||
vertices: []
|
||||
indices:
|
||||
edges: []
|
||||
weights: []
|
||||
spritePackingTag:
|
||||
pSDRemoveMatte: 0
|
||||
pSDShowRemoveMatteOption: 0
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,88 +0,0 @@
|
||||
%YAML 1.1
|
||||
%TAG !u! tag:unity3d.com,2011:
|
||||
--- !u!21 &2100000
|
||||
Material:
|
||||
serializedVersion: 6
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_Name: UIParticle_PerformanceDemo_Spread
|
||||
m_Shader: {fileID: 4800000, guid: ecfa8f5732b504ef98fba10aa18d0326, type: 3}
|
||||
m_ShaderKeywords:
|
||||
m_LightmapFlags: 4
|
||||
m_EnableInstancingVariants: 0
|
||||
m_DoubleSidedGI: 0
|
||||
m_CustomRenderQueue: -1
|
||||
stringTagMap: {}
|
||||
disabledShaderPasses: []
|
||||
m_SavedProperties:
|
||||
serializedVersion: 3
|
||||
m_TexEnvs:
|
||||
- _BumpMap:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- _DetailAlbedoMap:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- _DetailMask:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- _DetailNormalMap:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- _EmissionMap:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- _MainTex:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- _MetallicGlossMap:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- _OcclusionMap:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- _ParallaxMap:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
m_Floats:
|
||||
- _BumpScale: 1
|
||||
- _ColorMask: 15
|
||||
- _Cutoff: 0.5
|
||||
- _DetailNormalMapScale: 1
|
||||
- _DstBlend: 0
|
||||
- _GlossMapScale: 1
|
||||
- _Glossiness: 0.5
|
||||
- _GlossyReflections: 1
|
||||
- _Glow: 1
|
||||
- _InvFade: 1
|
||||
- _Metallic: 0
|
||||
- _Mode: 0
|
||||
- _OcclusionStrength: 1
|
||||
- _Parallax: 0.02
|
||||
- _SmoothnessTextureChannel: 0
|
||||
- _SpecularHighlights: 1
|
||||
- _SrcBlend: 1
|
||||
- _Stencil: 0
|
||||
- _StencilComp: 8
|
||||
- _StencilOp: 0
|
||||
- _StencilReadMask: 255
|
||||
- _StencilWriteMask: 255
|
||||
- _UVSec: 0
|
||||
- _UseUIAlphaClip: 0
|
||||
- _ZWrite: 1
|
||||
m_Colors:
|
||||
- _ClipRect: {r: -32767, g: -32767, b: 32767, a: 32767}
|
||||
- _Color: {r: 1, g: 1, b: 1, a: 1}
|
||||
- _EmissionColor: {r: 0, g: 0, b: 0, a: 1}
|
||||
- _TintColor: {r: 1, g: 1, b: 1, a: 1}
|
||||
@@ -1,8 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b7ac7640c2f1047c887aa52ff1ce9fcc
|
||||
NativeFormatImporter:
|
||||
externalObjects: {}
|
||||
mainObjectFileID: 2100000
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,8 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c5a6b37697e71473cb1ecc90047622d0
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,8 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b888c253a15224f1fa518bed74028211
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
Binary file not shown.
@@ -1,22 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: d07e6c2670f164cf7939ab011061a9bf
|
||||
TrueTypeFontImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 4
|
||||
fontSize: 26
|
||||
forceTextureCase: 0
|
||||
characterSpacing: 0
|
||||
characterPadding: 1
|
||||
includeFontData: 1
|
||||
fontName: Share Tech Mono
|
||||
fontNames:
|
||||
- Share Tech Mono
|
||||
fallbackFontReferences: []
|
||||
customCharacters:
|
||||
fontRenderingMode: 1
|
||||
ascentCalculationMode: 1
|
||||
useLegacyBoundsCalculation: 0
|
||||
shouldRoundAdvanceValue: 1
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,8 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: fa6e3b593bf274861b2eab47082d9b1e
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,7 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 784696794bc6345bc80bf49623581c2e
|
||||
PrefabImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,8 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f0b370726e57248da97c1c2f3bfd8bdf
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,12 +0,0 @@
|
||||
{
|
||||
"name": "Coffee.NanoMonitor",
|
||||
"references": [],
|
||||
"optionalUnityReferences": [],
|
||||
"includePlatforms": [],
|
||||
"excludePlatforms": [],
|
||||
"allowUnsafeCode": false,
|
||||
"overrideReferences": false,
|
||||
"precompiledReferences": [],
|
||||
"autoReferenced": false,
|
||||
"defineConstraints": []
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 3d6cc132218a845708ce317bd33e5500
|
||||
AssemblyDefinitionImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,296 +0,0 @@
|
||||
using System;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Profiling;
|
||||
using UnityEngine.Serialization;
|
||||
using UnityEngine.UI;
|
||||
#if UNITY_EDITOR
|
||||
using UnityEditor;
|
||||
using UnityEditorInternal;
|
||||
#endif
|
||||
|
||||
namespace Coffee.NanoMonitor
|
||||
{
|
||||
#if UNITY_EDITOR
|
||||
[CustomEditor(typeof(NanoMonitor))]
|
||||
internal class NanoMonitorEditor : Editor
|
||||
{
|
||||
private ReorderableList _monitorItemList;
|
||||
|
||||
private void OnEnable()
|
||||
{
|
||||
var items = serializedObject.FindProperty("m_CustomMonitorItems");
|
||||
_monitorItemList = new ReorderableList(serializedObject, items)
|
||||
{
|
||||
draggable = false,
|
||||
drawHeaderCallback = r =>
|
||||
{
|
||||
EditorGUI.LabelField(r, new GUIContent("Custom Monitor Items"));
|
||||
},
|
||||
drawElementCallback = (r, i, _, __) =>
|
||||
{
|
||||
EditorGUI.LabelField(new Rect(r.x, r.y, r.width, r.height - 2), GUIContent.none,
|
||||
EditorStyles.textArea);
|
||||
var labelWidth = EditorGUIUtility.labelWidth;
|
||||
EditorGUIUtility.labelWidth = 80;
|
||||
EditorGUI.PropertyField(new Rect(r.x + 2, r.y + 3, r.width - 4, r.height - 4),
|
||||
items.GetArrayElementAtIndex(i), true);
|
||||
EditorGUIUtility.labelWidth = labelWidth;
|
||||
},
|
||||
elementHeightCallback = i => EditorGUI.GetPropertyHeight(items.GetArrayElementAtIndex(i)) + 6
|
||||
};
|
||||
}
|
||||
|
||||
public override void OnInspectorGUI()
|
||||
{
|
||||
base.OnInspectorGUI();
|
||||
|
||||
_monitorItemList.DoLayoutList();
|
||||
serializedObject.ApplyModifiedProperties();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
[DisallowMultipleComponent]
|
||||
public sealed class NanoMonitor : MonoBehaviour
|
||||
{
|
||||
//################################
|
||||
// Serialize Members.
|
||||
//################################
|
||||
// Settings
|
||||
[Header("Settings")]
|
||||
[SerializeField]
|
||||
[Range(0.01f, 2f)]
|
||||
private float m_Interval = 1f;
|
||||
|
||||
[SerializeField]
|
||||
[Range(0, 3)]
|
||||
private int m_Precision = 2;
|
||||
|
||||
[SerializeField]
|
||||
private Font m_Font;
|
||||
|
||||
// Foldout
|
||||
[Header("Foldout")]
|
||||
[SerializeField]
|
||||
private bool m_Opened;
|
||||
|
||||
[FormerlySerializedAs("m_Collapse")]
|
||||
[SerializeField]
|
||||
private GameObject m_FoldoutObject;
|
||||
|
||||
[SerializeField]
|
||||
private Button m_OpenButton;
|
||||
|
||||
[SerializeField]
|
||||
private Button m_CloseButton;
|
||||
|
||||
// View
|
||||
[Header("View")]
|
||||
[SerializeField]
|
||||
private MonitorUI m_Fps;
|
||||
|
||||
[SerializeField]
|
||||
private MonitorUI m_Gc;
|
||||
|
||||
[SerializeField]
|
||||
private MonitorUI m_MonoUsage;
|
||||
|
||||
[SerializeField]
|
||||
private MonitorUI m_UnityUsage;
|
||||
|
||||
[HideInInspector]
|
||||
[SerializeField]
|
||||
private CustomMonitorItem[] m_CustomMonitorItems = new CustomMonitorItem[0];
|
||||
|
||||
|
||||
//################################
|
||||
// Private Members.
|
||||
//################################
|
||||
private double _elapsed;
|
||||
private double _fpsElapsed;
|
||||
private int _frames;
|
||||
|
||||
private void Update()
|
||||
{
|
||||
_frames++;
|
||||
_elapsed += Time.unscaledDeltaTime;
|
||||
_fpsElapsed += Time.unscaledDeltaTime;
|
||||
if (_elapsed < m_Interval) return;
|
||||
|
||||
if (m_Fps)
|
||||
{
|
||||
m_Fps.SetText("FPS: {0}", (int)(_frames / _fpsElapsed));
|
||||
}
|
||||
|
||||
if (m_Gc)
|
||||
{
|
||||
m_Gc.SetText("GC: {0}", GC.CollectionCount(0));
|
||||
}
|
||||
|
||||
if (m_MonoUsage)
|
||||
{
|
||||
var monoUsed = (Profiler.GetMonoUsedSizeLong() >> 10) / 1024f;
|
||||
var monoTotal = (Profiler.GetMonoHeapSizeLong() >> 10) / 1024f;
|
||||
if (m_Precision == 3)
|
||||
{
|
||||
m_MonoUsage.SetText("Mono: {0:N3}/{1:N3}MB", monoUsed, monoTotal);
|
||||
}
|
||||
else if (m_Precision == 2)
|
||||
{
|
||||
m_MonoUsage.SetText("Mono: {0:N2}/{1:N2}MB", monoUsed, monoTotal);
|
||||
}
|
||||
else if (m_Precision == 1)
|
||||
{
|
||||
m_MonoUsage.SetText("Mono: {0:N1}/{1:N1}MB", monoUsed, monoTotal);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_MonoUsage.SetText("Mono: {0:N0}/{1:N0}MB", monoUsed, monoTotal);
|
||||
}
|
||||
}
|
||||
|
||||
if (m_UnityUsage)
|
||||
{
|
||||
var unityUsed = (Profiler.GetTotalAllocatedMemoryLong() >> 10) / 1024f;
|
||||
var unityTotal = (Profiler.GetTotalReservedMemoryLong() >> 10) / 1024f;
|
||||
if (m_Precision == 3)
|
||||
{
|
||||
m_UnityUsage.SetText("Unity: {0:N3}/{1:N3}MB", unityUsed, unityTotal);
|
||||
}
|
||||
else if (m_Precision == 2)
|
||||
{
|
||||
m_UnityUsage.SetText("Unity: {0:N2}/{1:N2}MB", unityUsed, unityTotal);
|
||||
}
|
||||
else if (m_Precision == 1)
|
||||
{
|
||||
m_UnityUsage.SetText("Unity: {0:N1}/{1:N1}MB", unityUsed, unityTotal);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_UnityUsage.SetText("Unity: {0:N0}/{1:N0}MB", unityUsed, unityTotal);
|
||||
}
|
||||
}
|
||||
|
||||
foreach (var item in m_CustomMonitorItems)
|
||||
{
|
||||
item.UpdateText();
|
||||
}
|
||||
|
||||
_frames = 0;
|
||||
_elapsed %= m_Interval;
|
||||
_fpsElapsed = 0;
|
||||
}
|
||||
|
||||
|
||||
//################################
|
||||
// Unity Callbacks.
|
||||
//################################
|
||||
private void OnEnable()
|
||||
{
|
||||
if (m_OpenButton)
|
||||
{
|
||||
m_OpenButton.onClick.AddListener(Open);
|
||||
}
|
||||
|
||||
if (m_CloseButton)
|
||||
{
|
||||
m_CloseButton.onClick.AddListener(Close);
|
||||
}
|
||||
|
||||
if (m_Opened)
|
||||
{
|
||||
Open();
|
||||
}
|
||||
else
|
||||
{
|
||||
Close();
|
||||
}
|
||||
}
|
||||
|
||||
private void OnDisable()
|
||||
{
|
||||
if (m_OpenButton)
|
||||
{
|
||||
m_OpenButton.onClick.RemoveListener(Open);
|
||||
}
|
||||
|
||||
if (m_CloseButton)
|
||||
{
|
||||
m_CloseButton.onClick.RemoveListener(Close);
|
||||
}
|
||||
}
|
||||
|
||||
#if UNITY_EDITOR
|
||||
private void OnValidate()
|
||||
{
|
||||
if (m_Font)
|
||||
{
|
||||
foreach (var ui in GetComponentsInChildren<MonitorUI>(true))
|
||||
{
|
||||
ui.font = m_Font;
|
||||
}
|
||||
}
|
||||
|
||||
if (m_Opened)
|
||||
{
|
||||
Open();
|
||||
}
|
||||
else
|
||||
{
|
||||
Close();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
//################################
|
||||
// Public Members.
|
||||
//################################
|
||||
public void Clean()
|
||||
{
|
||||
Resources.UnloadUnusedAssets();
|
||||
GC.Collect();
|
||||
}
|
||||
|
||||
private void Open()
|
||||
{
|
||||
_frames = 0;
|
||||
_elapsed = m_Interval;
|
||||
_fpsElapsed = 0;
|
||||
|
||||
if (m_FoldoutObject)
|
||||
{
|
||||
m_FoldoutObject.SetActive(true);
|
||||
}
|
||||
|
||||
if (m_CloseButton)
|
||||
{
|
||||
m_CloseButton.gameObject.SetActive(true);
|
||||
}
|
||||
|
||||
if (m_OpenButton)
|
||||
{
|
||||
m_OpenButton.gameObject.SetActive(false);
|
||||
}
|
||||
}
|
||||
|
||||
private void Close()
|
||||
{
|
||||
if (m_FoldoutObject)
|
||||
{
|
||||
m_FoldoutObject.SetActive(false);
|
||||
}
|
||||
|
||||
if (m_CloseButton)
|
||||
{
|
||||
m_CloseButton.gameObject.SetActive(false);
|
||||
}
|
||||
|
||||
if (m_OpenButton)
|
||||
{
|
||||
m_OpenButton.gameObject.SetActive(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 19e83f45e7d5648f2bd10122dc7fed14
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,8 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: affee221821a14cfb842a0b0e8514a4e
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,160 +0,0 @@
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
|
||||
namespace Coffee.NanoMonitor
|
||||
{
|
||||
public class FixedFont
|
||||
{
|
||||
private const string k_Characters =
|
||||
"_!\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~";
|
||||
|
||||
private static readonly Dictionary<Font, FixedFont> s_Fonts = new Dictionary<Font, FixedFont>();
|
||||
private static readonly TextGenerator s_TextGenerator = new TextGenerator(100);
|
||||
|
||||
private static TextGenerationSettings s_Settings = new TextGenerationSettings
|
||||
{
|
||||
scaleFactor = 1,
|
||||
horizontalOverflow = HorizontalWrapMode.Overflow,
|
||||
verticalOverflow = VerticalWrapMode.Overflow,
|
||||
alignByGeometry = true,
|
||||
textAnchor = TextAnchor.MiddleCenter,
|
||||
color = Color.white
|
||||
};
|
||||
|
||||
private readonly Font _font;
|
||||
private readonly UIVertex[] _tmpVerts = new UIVertex[4];
|
||||
private UICharInfo[] _charInfos;
|
||||
|
||||
private int _resolution;
|
||||
private UIVertex[] _verts;
|
||||
|
||||
private FixedFont(Font font)
|
||||
{
|
||||
_font = font;
|
||||
}
|
||||
|
||||
public int fontSize
|
||||
{
|
||||
get
|
||||
{
|
||||
return _font.dynamic ? 32 : _font.fontSize;
|
||||
}
|
||||
}
|
||||
|
||||
public static FixedFont GetOrCreate(Font font)
|
||||
{
|
||||
if (font == null) return null;
|
||||
if (s_Fonts.TryGetValue(font, out var data)) return data;
|
||||
|
||||
data = new FixedFont(font);
|
||||
s_Fonts.Add(font, data);
|
||||
return data;
|
||||
}
|
||||
|
||||
public void Invalidate()
|
||||
{
|
||||
_resolution = 0;
|
||||
}
|
||||
|
||||
public void UpdateFont()
|
||||
{
|
||||
if (!_font) return;
|
||||
|
||||
var mat = _font.material;
|
||||
if (!mat) return;
|
||||
|
||||
var tex = mat.mainTexture;
|
||||
if (!tex) return;
|
||||
|
||||
var currentResolution = tex.width * tex.height;
|
||||
|
||||
if (_resolution == currentResolution) return;
|
||||
_resolution = currentResolution;
|
||||
|
||||
s_Settings.font = _font;
|
||||
s_TextGenerator.Invalidate();
|
||||
s_TextGenerator.Populate(k_Characters, s_Settings);
|
||||
|
||||
_verts = s_TextGenerator.GetVerticesArray();
|
||||
_charInfos = s_TextGenerator.GetCharactersArray();
|
||||
|
||||
float offsetX = 0;
|
||||
for (var i = 0; i < _verts.Length; i++)
|
||||
{
|
||||
if ((i & 3) == 0)
|
||||
{
|
||||
offsetX = _verts[i].position.x;
|
||||
}
|
||||
|
||||
var v = _verts[i];
|
||||
v.position -= new Vector3(offsetX, 0);
|
||||
_verts[i] = v;
|
||||
}
|
||||
}
|
||||
|
||||
public float Layout(char c, float offset, float scale)
|
||||
{
|
||||
if (_charInfos == null) return offset;
|
||||
if (c < 0x20 || 0x7e < c) return offset;
|
||||
var ci = c - 0x20;
|
||||
|
||||
return offset + _charInfos[ci].charWidth * scale;
|
||||
}
|
||||
|
||||
public float Append(VertexHelper toFill, char c, float offset, float scale, Color color)
|
||||
{
|
||||
if (_verts == null || _charInfos == null) return offset;
|
||||
if (c < 0x20 || 0x7e < c) return offset;
|
||||
var ci = c - 0x20;
|
||||
|
||||
for (var i = 0; i < 4; i++)
|
||||
{
|
||||
_tmpVerts[i] = _verts[ci * 4 + i];
|
||||
_tmpVerts[i].position = _tmpVerts[i].position * scale + new Vector3(offset, 0);
|
||||
_tmpVerts[i].color = ci == 0 ? Color.clear : color;
|
||||
}
|
||||
|
||||
toFill.AddUIVertexQuad(_tmpVerts);
|
||||
return offset + _charInfos[ci].charWidth * scale;
|
||||
}
|
||||
|
||||
public void Fill(VertexHelper toFill, Color color, RectTransform tr)
|
||||
{
|
||||
if (_verts == null || _charInfos == null) return;
|
||||
const int ci = '*' - 0x20;
|
||||
var uv = (_verts[ci * 4].uv0 + _verts[ci * 4 + 2].uv0) / 2;
|
||||
|
||||
var rect = tr.rect;
|
||||
var size = rect.size / 2;
|
||||
var offset = (new Vector2(0.5f, 0.5f) - tr.pivot) * rect.size;
|
||||
|
||||
for (var i = 0; i < 4; i++)
|
||||
{
|
||||
_tmpVerts[i] = new UIVertex
|
||||
{
|
||||
uv0 = uv,
|
||||
color = color
|
||||
};
|
||||
|
||||
switch (i)
|
||||
{
|
||||
case 0:
|
||||
_tmpVerts[i].position = new Vector2(-size.x, -size.y) + offset;
|
||||
break;
|
||||
case 1:
|
||||
_tmpVerts[i].position = new Vector2(-size.x, size.y) + offset;
|
||||
break;
|
||||
case 2:
|
||||
_tmpVerts[i].position = new Vector2(size.x, size.y) + offset;
|
||||
break;
|
||||
case 3:
|
||||
_tmpVerts[i].position = new Vector2(size.x, -size.y) + offset;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
toFill.AddUIVertexQuad(_tmpVerts);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,12 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 9a8c5c555d4bf4361ab3435c318c0699
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences:
|
||||
- m_Material: {fileID: 2100000, guid: 4da4639f724144ddead57bffca64e71f, type: 3}
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,239 +0,0 @@
|
||||
using System.Text;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
|
||||
namespace Coffee.NanoMonitor
|
||||
{
|
||||
#if UNITY_EDITOR
|
||||
[CustomEditor(typeof(MonitorUI))]
|
||||
public class MonitorTextEditor : Editor
|
||||
{
|
||||
private SerializedProperty _color;
|
||||
private SerializedProperty _font;
|
||||
private SerializedProperty _fontSize;
|
||||
private SerializedProperty _mode;
|
||||
private SerializedProperty _text;
|
||||
private SerializedProperty _textAnchor;
|
||||
|
||||
private void OnEnable()
|
||||
{
|
||||
_mode = serializedObject.FindProperty("m_Mode");
|
||||
_text = serializedObject.FindProperty("m_Text");
|
||||
_color = serializedObject.FindProperty("m_Color");
|
||||
var fontData = serializedObject.FindProperty("m_FontData");
|
||||
_fontSize = fontData.FindPropertyRelative("m_FontSize");
|
||||
_font = fontData.FindPropertyRelative("m_Font");
|
||||
_textAnchor = serializedObject.FindProperty("m_TextAnchor");
|
||||
}
|
||||
|
||||
public override void OnInspectorGUI()
|
||||
{
|
||||
serializedObject.Update();
|
||||
|
||||
EditorGUILayout.PropertyField(_mode);
|
||||
if ((MonitorUI.Mode)_mode.intValue == MonitorUI.Mode.Text)
|
||||
{
|
||||
EditorGUILayout.PropertyField(_text);
|
||||
EditorGUILayout.PropertyField(_fontSize);
|
||||
EditorGUILayout.PropertyField(_textAnchor);
|
||||
EditorGUILayout.PropertyField(_font);
|
||||
}
|
||||
|
||||
EditorGUILayout.PropertyField(_color);
|
||||
|
||||
serializedObject.ApplyModifiedProperties();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
public class MonitorUI : Text
|
||||
{
|
||||
public enum Mode
|
||||
{
|
||||
Text,
|
||||
Fill
|
||||
}
|
||||
|
||||
public enum TextAnchor
|
||||
{
|
||||
Left,
|
||||
Center,
|
||||
Right
|
||||
}
|
||||
|
||||
|
||||
//################################
|
||||
// Serialize Members.
|
||||
//################################
|
||||
[SerializeField] private Mode m_Mode = Mode.Text;
|
||||
[SerializeField] private TextAnchor m_TextAnchor;
|
||||
|
||||
|
||||
//################################
|
||||
// Private Members.
|
||||
//################################
|
||||
private readonly StringBuilder _sb = new StringBuilder(64);
|
||||
|
||||
|
||||
//################################
|
||||
// Public Members.
|
||||
//################################
|
||||
public override string text
|
||||
{
|
||||
get
|
||||
{
|
||||
return _sb.ToString();
|
||||
}
|
||||
set
|
||||
{
|
||||
m_Text = value;
|
||||
if (_sb.IsEqual(m_Text)) return;
|
||||
|
||||
_sb.Length = 0;
|
||||
_sb.Append(m_Text);
|
||||
SetVerticesDirty();
|
||||
}
|
||||
}
|
||||
|
||||
public TextAnchor textAnchor
|
||||
{
|
||||
get
|
||||
{
|
||||
return m_TextAnchor;
|
||||
}
|
||||
set
|
||||
{
|
||||
if (m_TextAnchor == value) return;
|
||||
|
||||
m_TextAnchor = value;
|
||||
SetVerticesDirty();
|
||||
}
|
||||
}
|
||||
|
||||
public override bool raycastTarget
|
||||
{
|
||||
get
|
||||
{
|
||||
return m_Mode == Mode.Fill;
|
||||
}
|
||||
set { }
|
||||
}
|
||||
|
||||
|
||||
//################################
|
||||
// Unity Callbacks.
|
||||
//################################
|
||||
protected override void OnEnable()
|
||||
{
|
||||
RegisterDirtyMaterialCallback(UpdateFont);
|
||||
|
||||
base.OnEnable();
|
||||
raycastTarget = false;
|
||||
maskable = false;
|
||||
_sb.Length = 0;
|
||||
_sb.Append(m_Text);
|
||||
}
|
||||
|
||||
protected override void OnDisable()
|
||||
{
|
||||
UnregisterDirtyMaterialCallback(UpdateFont);
|
||||
|
||||
base.OnDisable();
|
||||
}
|
||||
|
||||
#if UNITY_EDITOR
|
||||
protected override void OnValidate()
|
||||
{
|
||||
base.OnValidate();
|
||||
|
||||
if (!_sb.IsEqual(m_Text))
|
||||
{
|
||||
_sb.Length = 0;
|
||||
_sb.Append(m_Text);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
public void SetText(string format, double arg0 = 0, double arg1 = 0, double arg2 = 0, double arg3 = 0)
|
||||
{
|
||||
_sb.Length = 0;
|
||||
_sb.AppendFormatNoAlloc(format, arg0, arg1, arg2, arg3);
|
||||
SetVerticesDirty();
|
||||
}
|
||||
|
||||
public void SetText(StringBuilder builder)
|
||||
{
|
||||
_sb.Length = 0;
|
||||
_sb.Append(builder);
|
||||
SetVerticesDirty();
|
||||
}
|
||||
|
||||
private void UpdateFont()
|
||||
{
|
||||
var fontData = FixedFont.GetOrCreate(font);
|
||||
if (fontData != null)
|
||||
{
|
||||
fontData.Invalidate();
|
||||
fontData.UpdateFont();
|
||||
}
|
||||
}
|
||||
|
||||
protected override void OnPopulateMesh(VertexHelper toFill)
|
||||
{
|
||||
toFill.Clear();
|
||||
|
||||
var fontData = FixedFont.GetOrCreate(font);
|
||||
if (fontData == null) return;
|
||||
|
||||
fontData.UpdateFont();
|
||||
|
||||
if (m_Mode == Mode.Fill)
|
||||
{
|
||||
fontData.Fill(toFill, color, rectTransform);
|
||||
return;
|
||||
}
|
||||
|
||||
var scale = (float)fontSize / fontData.fontSize;
|
||||
float offset = 0;
|
||||
switch (textAnchor)
|
||||
{
|
||||
case TextAnchor.Left:
|
||||
offset = rectTransform.rect.xMin;
|
||||
break;
|
||||
case TextAnchor.Center:
|
||||
for (var i = 0; i < _sb.Length; i++)
|
||||
{
|
||||
offset = fontData.Layout(_sb[i], offset, scale);
|
||||
}
|
||||
|
||||
offset = -offset / 2;
|
||||
break;
|
||||
case TextAnchor.Right:
|
||||
for (var i = 0; i < _sb.Length; i++)
|
||||
{
|
||||
offset = fontData.Layout(_sb[i], offset, scale);
|
||||
}
|
||||
|
||||
offset = rectTransform.rect.xMax - offset;
|
||||
break;
|
||||
}
|
||||
|
||||
for (var i = 0; i < _sb.Length; i++)
|
||||
{
|
||||
offset = fontData.Append(toFill, _sb[i], offset, scale, color);
|
||||
}
|
||||
}
|
||||
|
||||
protected override void UpdateMaterial()
|
||||
{
|
||||
base.UpdateMaterial();
|
||||
|
||||
var fontData = FixedFont.GetOrCreate(font);
|
||||
if (fontData != null)
|
||||
{
|
||||
fontData.UpdateFont();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,12 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b0e08c6080a2e4d8186f97c60518830f
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences:
|
||||
- m_Material: {fileID: 2100000, guid: 4da4639f724144ddead57bffca64e71f, type: 3}
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,8 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 1051ed7e3f1474ed59ca41b33b00029b
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,55 +0,0 @@
|
||||
using System;
|
||||
using UnityEngine;
|
||||
#if UNITY_EDITOR
|
||||
using UnityEditor;
|
||||
#endif
|
||||
|
||||
namespace Coffee.NanoMonitor
|
||||
{
|
||||
#if UNITY_EDITOR
|
||||
[CustomPropertyDrawer(typeof(CustomMonitorItem))]
|
||||
internal sealed class CustomMonitorItemDrawer : PropertyDrawer
|
||||
{
|
||||
public override void OnGUI(Rect p, SerializedProperty property, GUIContent label)
|
||||
{
|
||||
var pos = new Rect(p.x, p.y + 18 * 0, p.width, 16);
|
||||
EditorGUI.PropertyField(pos, property.FindPropertyRelative("m_Text"));
|
||||
pos.y += 18;
|
||||
EditorGUI.PropertyField(pos, property.FindPropertyRelative("m_Format"));
|
||||
pos.y += 18;
|
||||
EditorGUI.indentLevel++;
|
||||
EditorGUI.PropertyField(pos, property.FindPropertyRelative("m_Arg0"));
|
||||
pos.y += 18;
|
||||
EditorGUI.PropertyField(pos, property.FindPropertyRelative("m_Arg1"));
|
||||
pos.y += 18;
|
||||
EditorGUI.PropertyField(pos, property.FindPropertyRelative("m_Arg2"));
|
||||
EditorGUI.indentLevel--;
|
||||
|
||||
property.serializedObject.ApplyModifiedProperties();
|
||||
}
|
||||
|
||||
public override float GetPropertyHeight(SerializedProperty property, GUIContent label)
|
||||
{
|
||||
return (EditorGUIUtility.singleLineHeight + 2) * 5;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
[Serializable]
|
||||
public class CustomMonitorItem
|
||||
{
|
||||
[SerializeField] private MonitorUI m_Text;
|
||||
[SerializeField] private string m_Format = "";
|
||||
[SerializeField] private NumericProperty m_Arg0;
|
||||
[SerializeField] private NumericProperty m_Arg1;
|
||||
[SerializeField] private NumericProperty m_Arg2;
|
||||
|
||||
public void UpdateText()
|
||||
{
|
||||
if (m_Text)
|
||||
{
|
||||
m_Text.SetText(m_Format, m_Arg0.Get(), m_Arg1.Get(), m_Arg2.Get());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 5c50c6434f4ad4488bfc5b0928dbb4c4
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,236 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Coffee.NanoMonitor
|
||||
{
|
||||
#if UNITY_EDITOR
|
||||
[CustomPropertyDrawer(typeof(NumericProperty))]
|
||||
internal sealed class NumericPropertyDrawer : PropertyDrawer
|
||||
{
|
||||
private static Action<PropertyInfo> s_OnMenuSelected;
|
||||
private static GenericMenu s_PropertyMenu;
|
||||
|
||||
private static readonly Dictionary<Type, string> s_SupportedTypes = new Dictionary<Type, string>
|
||||
{
|
||||
{ typeof(bool), "bool" },
|
||||
{ typeof(sbyte), "sbyte" },
|
||||
{ typeof(short), "short" },
|
||||
{ typeof(int), "int" },
|
||||
{ typeof(long), "long" },
|
||||
{ typeof(byte), "byte" },
|
||||
{ typeof(ushort), "ushort" },
|
||||
{ typeof(uint), "uint" },
|
||||
{ typeof(ulong), "ulong" },
|
||||
{ typeof(float), "float" },
|
||||
{ typeof(double), "double" },
|
||||
{ typeof(decimal), "decimal" }
|
||||
};
|
||||
|
||||
private static void Init()
|
||||
{
|
||||
if (s_PropertyMenu != null) return;
|
||||
|
||||
const BindingFlags bindingFlags = BindingFlags.Public
|
||||
| BindingFlags.NonPublic
|
||||
| BindingFlags.Static
|
||||
| BindingFlags.GetProperty;
|
||||
var properties = AppDomain.CurrentDomain.GetAssemblies()
|
||||
.SelectMany(assembly => assembly.GetTypes())
|
||||
.SelectMany(type => type.GetProperties(bindingFlags))
|
||||
.Where(pi => pi.GetMethod != null && s_SupportedTypes.ContainsKey(pi.PropertyType))
|
||||
.OrderBy(pi => ConvertToMenuItem(pi, false))
|
||||
.ToArray();
|
||||
|
||||
s_PropertyMenu = new GenericMenu();
|
||||
s_PropertyMenu.AddItem(new GUIContent("No Property"), false,
|
||||
arg => s_OnMenuSelected?.Invoke(arg as PropertyInfo), null);
|
||||
s_PropertyMenu.AddItem(new GUIContent("(Non Public Properties)/"), false, () => { });
|
||||
s_PropertyMenu.AddSeparator("");
|
||||
|
||||
foreach (var pi in properties)
|
||||
{
|
||||
s_PropertyMenu.AddItem(new GUIContent(ConvertToMenuItem(pi, true)), false,
|
||||
arg => s_OnMenuSelected?.Invoke(arg as PropertyInfo), pi);
|
||||
}
|
||||
}
|
||||
|
||||
private static string ConvertToMenuItem(PropertyInfo p, bool propertyType)
|
||||
{
|
||||
var type = p.DeclaringType;
|
||||
if (type == null) return "";
|
||||
|
||||
var category = p.GetMethod.IsPublic && type.IsPublic
|
||||
? ""
|
||||
: "(Non Public Properties)/";
|
||||
var typeName = type.FullName;
|
||||
var asmName = type.Assembly.GetName().Name;
|
||||
if (asmName == "UnityEngine.CoreModule")
|
||||
{
|
||||
asmName = "UnityEngine";
|
||||
}
|
||||
|
||||
return propertyType
|
||||
? $"{category}{asmName}/{typeName}/{s_SupportedTypes[p.PropertyType]} {p.Name}"
|
||||
: $"{category}{asmName}/{typeName}/{p.Name}";
|
||||
}
|
||||
|
||||
public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
|
||||
{
|
||||
Init();
|
||||
label = EditorGUI.BeginProperty(position, label, property);
|
||||
|
||||
var path = property.FindPropertyRelative("m_Path");
|
||||
var split = path.stringValue.Split(';', ' ', ',');
|
||||
var name = split.Length == 4 ? $"{split[0]}.{split[3]}" : "No Property";
|
||||
|
||||
position = EditorGUI.PrefixLabel(position, label);
|
||||
if (GUI.Button(position, name, EditorStyles.popup))
|
||||
{
|
||||
s_OnMenuSelected = p =>
|
||||
{
|
||||
path.stringValue = p == null
|
||||
? ""
|
||||
: $"{p.DeclaringType?.FullName}, {p.DeclaringType?.Assembly.GetName().Name};{p.Name}";
|
||||
property.serializedObject.ApplyModifiedProperties();
|
||||
};
|
||||
s_PropertyMenu.DropDown(position);
|
||||
}
|
||||
|
||||
EditorGUI.EndProperty();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
[Serializable]
|
||||
public class NumericProperty : ISerializationCallbackReceiver
|
||||
{
|
||||
//################################
|
||||
// Serialized Members.
|
||||
//################################
|
||||
[SerializeField] private string m_Path = "";
|
||||
|
||||
|
||||
//################################
|
||||
// Private Members.
|
||||
//################################
|
||||
private Func<double> _get;
|
||||
|
||||
void ISerializationCallbackReceiver.OnBeforeSerialize()
|
||||
{
|
||||
}
|
||||
|
||||
void ISerializationCallbackReceiver.OnAfterDeserialize()
|
||||
{
|
||||
var pInfo = GetPropertyInfo(m_Path);
|
||||
_get = CreateFunc(pInfo?.GetMethod);
|
||||
}
|
||||
|
||||
|
||||
//################################
|
||||
// Public Members.
|
||||
//################################
|
||||
public double Get()
|
||||
{
|
||||
return _get?.Invoke() ?? -1;
|
||||
}
|
||||
|
||||
private static PropertyInfo GetPropertyInfo(string path)
|
||||
{
|
||||
var p = path.Split(';');
|
||||
if (p.Length != 2) return null;
|
||||
|
||||
var type = Type.GetType(p[0]);
|
||||
if (type == null)
|
||||
{
|
||||
Debug.LogException(new Exception($"Type '{p[0]}' is not found"));
|
||||
return null;
|
||||
}
|
||||
|
||||
var pInfo = type.GetProperty(p[1], BindingFlags.GetProperty | BindingFlags.Public | BindingFlags.Static);
|
||||
if (pInfo == null)
|
||||
{
|
||||
Debug.LogException(new Exception($"Member '{p[1]}' is not found in type '{type}'"));
|
||||
}
|
||||
|
||||
return pInfo;
|
||||
}
|
||||
|
||||
private static Func<double> CreateFunc(MethodInfo mInfo)
|
||||
{
|
||||
if (mInfo == null) return null;
|
||||
switch (Type.GetTypeCode(mInfo.ReturnType))
|
||||
{
|
||||
case TypeCode.Boolean:
|
||||
{
|
||||
var func = (Func<bool>)mInfo.CreateDelegate(typeof(Func<bool>));
|
||||
return () => func() ? 1 : 0;
|
||||
}
|
||||
case TypeCode.Byte:
|
||||
{
|
||||
var func = (Func<byte>)mInfo.CreateDelegate(typeof(Func<byte>));
|
||||
return () => func();
|
||||
}
|
||||
case TypeCode.SByte:
|
||||
{
|
||||
var func = (Func<sbyte>)mInfo.CreateDelegate(typeof(Func<sbyte>));
|
||||
return () => func();
|
||||
}
|
||||
case TypeCode.UInt16:
|
||||
{
|
||||
var func = (Func<ushort>)mInfo.CreateDelegate(typeof(Func<ushort>));
|
||||
return () => func();
|
||||
}
|
||||
case TypeCode.UInt32:
|
||||
{
|
||||
var func = (Func<uint>)mInfo.CreateDelegate(typeof(Func<uint>));
|
||||
return () => func();
|
||||
}
|
||||
case TypeCode.UInt64:
|
||||
{
|
||||
var func = (Func<ulong>)mInfo.CreateDelegate(typeof(Func<ulong>));
|
||||
return () => func();
|
||||
}
|
||||
case TypeCode.Int16:
|
||||
{
|
||||
var func = (Func<short>)mInfo.CreateDelegate(typeof(Func<short>));
|
||||
return () => func();
|
||||
}
|
||||
case TypeCode.Int32:
|
||||
{
|
||||
var f = (Func<int>)mInfo.CreateDelegate(typeof(Func<int>));
|
||||
return () => f();
|
||||
}
|
||||
case TypeCode.Int64:
|
||||
{
|
||||
var f = (Func<long>)mInfo.CreateDelegate(typeof(Func<long>));
|
||||
return () => f();
|
||||
}
|
||||
case TypeCode.Decimal:
|
||||
{
|
||||
var f = (Func<decimal>)mInfo.CreateDelegate(typeof(Func<decimal>));
|
||||
return () => (double)f();
|
||||
}
|
||||
case TypeCode.Double:
|
||||
{
|
||||
var f = (Func<double>)mInfo.CreateDelegate(typeof(Func<double>));
|
||||
return f;
|
||||
}
|
||||
case TypeCode.Single:
|
||||
{
|
||||
var f = (Func<float>)mInfo.CreateDelegate(typeof(Func<float>));
|
||||
return () => f();
|
||||
}
|
||||
default:
|
||||
{
|
||||
var message = $"Method '{mInfo.DeclaringType}.{mInfo.Name} ({mInfo.ReturnType})' is not supported.";
|
||||
Debug.LogException(new Exception(message));
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 87fefa9f373e8411596b00238a65f3c3
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,236 +0,0 @@
|
||||
using System;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Text;
|
||||
|
||||
[assembly: InternalsVisibleTo("Coffee.NanoMonitor.Tests")]
|
||||
|
||||
namespace Coffee.NanoMonitor
|
||||
{
|
||||
internal static class StringBuilderExtensions
|
||||
{
|
||||
public static bool IsEqual(this StringBuilder sb, string other)
|
||||
{
|
||||
if (sb == null || other == null) return false;
|
||||
if (sb.Length != other.Length) return false;
|
||||
|
||||
for (var i = 0; i < sb.Length; i++)
|
||||
{
|
||||
if (sb[i] != other[i]) return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public static void AppendFormatNoAlloc(this StringBuilder sb, string format, double arg0 = 0, double arg1 = 0,
|
||||
double arg2 = 0, double arg3 = 0)
|
||||
{
|
||||
for (var i = 0; i < format.Length; i++)
|
||||
{
|
||||
var c = format[i];
|
||||
|
||||
// Append formatted value
|
||||
if (c == '{')
|
||||
{
|
||||
i = GetFormat(format, i, out var argIndex, out var padding, out var precision, out var alignment);
|
||||
|
||||
switch (argIndex)
|
||||
{
|
||||
case 0:
|
||||
sb.AppendDouble(arg0, padding, precision, alignment);
|
||||
break;
|
||||
case 1:
|
||||
sb.AppendDouble(arg1, padding, precision, alignment);
|
||||
break;
|
||||
case 2:
|
||||
sb.AppendDouble(arg2, padding, precision, alignment);
|
||||
break;
|
||||
case 3:
|
||||
sb.AppendDouble(arg3, padding, precision, alignment);
|
||||
break;
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
// Append character
|
||||
sb.Append(c);
|
||||
}
|
||||
}
|
||||
|
||||
private static void AppendInteger(this StringBuilder sb, double number, int padding, int alignment)
|
||||
{
|
||||
number = Math.Truncate(number);
|
||||
var sign = number < 0;
|
||||
number = sign ? -number : number;
|
||||
|
||||
var startIndex = sb.Length;
|
||||
do
|
||||
{
|
||||
var n = Math.Truncate(number % 10);
|
||||
number /= 10;
|
||||
|
||||
sb.Append((char)(n + 48));
|
||||
} while (1 <= number || sb.Length - startIndex < padding);
|
||||
|
||||
if (sign)
|
||||
{
|
||||
sb.Append('-');
|
||||
}
|
||||
|
||||
var endIndex = sb.Length - 1;
|
||||
|
||||
sb.Reverse(startIndex, endIndex);
|
||||
sb.Alignment(alignment, startIndex, endIndex);
|
||||
}
|
||||
|
||||
private static void AppendDouble(this StringBuilder sb, double number, int padding, int precision,
|
||||
int alignment)
|
||||
{
|
||||
var integer = Math.Truncate(number);
|
||||
var startIndex = sb.Length;
|
||||
sb.AppendInteger(integer, padding, 0);
|
||||
|
||||
if (0 < precision)
|
||||
{
|
||||
sb.Append('.');
|
||||
number -= integer;
|
||||
number = Math.Round(number, precision);
|
||||
for (var p = 0; p < precision; p++)
|
||||
{
|
||||
number *= 10;
|
||||
integer = (long)number;
|
||||
sb.Append((char)(integer + 48));
|
||||
number -= integer;
|
||||
number = Math.Round(number, precision);
|
||||
}
|
||||
}
|
||||
|
||||
sb.Alignment(alignment, startIndex, sb.Length - 1);
|
||||
}
|
||||
|
||||
private static void Reverse(this StringBuilder sb, int start, int end)
|
||||
{
|
||||
while (start < end)
|
||||
{
|
||||
// swap
|
||||
(sb[start], sb[end]) = (sb[end], sb[start]);
|
||||
start++;
|
||||
end--;
|
||||
}
|
||||
}
|
||||
|
||||
private static void Alignment(this StringBuilder sb, int alignment, int start, int end)
|
||||
{
|
||||
if (alignment == 0) return;
|
||||
|
||||
var len = end - start + 1;
|
||||
if (0 < alignment && len < alignment)
|
||||
{
|
||||
sb.Append(' ', alignment - len);
|
||||
for (var i = 0; i < len; i++)
|
||||
{
|
||||
// swap
|
||||
(sb[end - i], sb[start + alignment - i - 1]) = (sb[start + alignment - i - 1], sb[end - i]);
|
||||
}
|
||||
}
|
||||
else if (alignment < 0 && len < -alignment)
|
||||
{
|
||||
sb.Append(' ', -alignment - len);
|
||||
}
|
||||
}
|
||||
|
||||
private static int GetFormat(string format, int i, out int argIndex, out int padding, out int precision,
|
||||
out int alignment)
|
||||
{
|
||||
argIndex = -1;
|
||||
padding = 0;
|
||||
precision = 0;
|
||||
alignment = 0;
|
||||
|
||||
var alignmentSign = false;
|
||||
var readFlag = 0;
|
||||
|
||||
for (; i < format.Length; i++)
|
||||
{
|
||||
var c = format[i];
|
||||
|
||||
// End format
|
||||
if (c == '}')
|
||||
{
|
||||
return i;
|
||||
}
|
||||
|
||||
// Start format
|
||||
if (c == '{')
|
||||
{
|
||||
readFlag = 1;
|
||||
}
|
||||
|
||||
// After '{': Read argument index and format
|
||||
else if (readFlag == 1)
|
||||
{
|
||||
if ('0' <= c && c <= '3')
|
||||
{
|
||||
argIndex = c - 48;
|
||||
}
|
||||
else if (c == ',')
|
||||
{
|
||||
readFlag = 2;
|
||||
}
|
||||
else if (c == ':')
|
||||
{
|
||||
readFlag = 3;
|
||||
}
|
||||
}
|
||||
|
||||
//After ',': Read alignment value
|
||||
else if (readFlag == 2)
|
||||
{
|
||||
if ('0' <= c && c <= '9')
|
||||
{
|
||||
alignment = alignment * 10 + (alignmentSign ? 48 - c : c - 48);
|
||||
}
|
||||
else if (c == '-')
|
||||
{
|
||||
alignmentSign = true;
|
||||
}
|
||||
else if (c == ':')
|
||||
{
|
||||
readFlag = 3;
|
||||
}
|
||||
}
|
||||
|
||||
// After ':': Read format for integral
|
||||
else if (readFlag == 3)
|
||||
{
|
||||
if (c == '.')
|
||||
{
|
||||
precision = 0;
|
||||
readFlag = 4;
|
||||
}
|
||||
else if (c == '0')
|
||||
{
|
||||
padding++;
|
||||
}
|
||||
// Legacy mode
|
||||
else if ('1' <= c && c <= '9')
|
||||
{
|
||||
precision = c - 48;
|
||||
}
|
||||
}
|
||||
|
||||
// After '.': Read decimal precision value
|
||||
else if (readFlag == 4)
|
||||
{
|
||||
if (c == '0')
|
||||
{
|
||||
precision++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
argIndex = -1;
|
||||
return i;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,12 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 23b4d6d0f5b8644b0981a065d7e47478
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences:
|
||||
- m_Material: {fileID: 2100000, guid: 4da4639f724144ddead57bffca64e71f, type: 3}
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,18 +0,0 @@
|
||||
{
|
||||
"name": "com.coffee.nano-monitor",
|
||||
"displayName": "Nano Monitor",
|
||||
"description": "This package displays FPS, memory status and any static properties.\n- extremely fast\n- no allocations (on build)\n-1 set pass call only\n- open/close/refresh (GC) buttons",
|
||||
"version": "1.0.0",
|
||||
"unity": "2018.3",
|
||||
"license": "MIT",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/mob-sakai/MaskTweaksForUGUI.git"
|
||||
},
|
||||
"author": "mob-sakai <sakai861104@gmail.com> (https://github.com/mob-sakai)",
|
||||
"dependencies": {},
|
||||
"keywords": [
|
||||
"monitor",
|
||||
"utility"
|
||||
]
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: be075f23fcc314d319e4f4ebfa6eefdd
|
||||
TextScriptImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,8 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: db256ad6e34f94a4a95dedcbce09ddf1
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,14 +0,0 @@
|
||||
{
|
||||
"name": "Coffee.UIParticle.PerformanceDemo",
|
||||
"references": [
|
||||
"Coffee.UIParticle"
|
||||
],
|
||||
"optionalUnityReferences": [],
|
||||
"includePlatforms": [],
|
||||
"excludePlatforms": [],
|
||||
"allowUnsafeCode": false,
|
||||
"overrideReferences": false,
|
||||
"precompiledReferences": [],
|
||||
"autoReferenced": false,
|
||||
"defineConstraints": []
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 9c1a1a5e813ba46d2b837936f34e33a7
|
||||
AssemblyDefinitionImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,84 +0,0 @@
|
||||
using UnityEngine;
|
||||
using UnityEngine.Serialization;
|
||||
|
||||
namespace Coffee.UIExtensions.Demo
|
||||
{
|
||||
public class UIParticle_PerformanceDemo : MonoBehaviour
|
||||
{
|
||||
[FormerlySerializedAs("copyOrigin")]
|
||||
[SerializeField]
|
||||
private GameObject m_CopyOrigin;
|
||||
|
||||
[FormerlySerializedAs("copyCount")]
|
||||
[SerializeField]
|
||||
public int m_CopyCount;
|
||||
|
||||
[FormerlySerializedAs("root")]
|
||||
[SerializeField]
|
||||
public Canvas m_RootCanvas;
|
||||
|
||||
private void Start()
|
||||
{
|
||||
Application.targetFrameRate = 60;
|
||||
|
||||
if (m_CopyOrigin)
|
||||
{
|
||||
m_CopyOrigin.SetActive(false);
|
||||
|
||||
var parent = m_CopyOrigin.transform.parent;
|
||||
for (var i = 0; i < m_CopyCount; i++)
|
||||
{
|
||||
var go = Instantiate(m_CopyOrigin, parent, false);
|
||||
go.name = string.Format("{0} {1}", m_CopyOrigin.name, i + 1);
|
||||
go.hideFlags = HideFlags.DontSave;
|
||||
|
||||
go.SetActive(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void UIParticle_Enable(bool flag)
|
||||
{
|
||||
foreach (var uip in m_RootCanvas.GetComponentsInChildren<UIParticle>(true))
|
||||
{
|
||||
uip.enabled = flag;
|
||||
}
|
||||
|
||||
if (!flag)
|
||||
{
|
||||
foreach (var ps in FindObjectsOfType<ParticleSystem>())
|
||||
{
|
||||
ps.Play(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void UIParticle_MeshSharing(bool flag)
|
||||
{
|
||||
foreach (var uip in m_RootCanvas.GetComponentsInChildren<UIParticle>(true))
|
||||
{
|
||||
uip.meshSharing = flag
|
||||
? UIParticle.MeshSharing.Auto
|
||||
: UIParticle.MeshSharing.None;
|
||||
}
|
||||
}
|
||||
|
||||
public void UIParticle_RandomGroup(bool flag)
|
||||
{
|
||||
foreach (var uip in m_RootCanvas.GetComponentsInChildren<UIParticle>(true))
|
||||
{
|
||||
uip.groupMaxId = flag
|
||||
? 4
|
||||
: 0;
|
||||
}
|
||||
}
|
||||
|
||||
public void ParticleSystem_SetScale(float scale)
|
||||
{
|
||||
foreach (var ps in FindObjectsOfType<ParticleSystem>())
|
||||
{
|
||||
ps.transform.localScale = new Vector3(scale, scale, scale);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 3a595cf9cf93f4e0686f247a5e7e19ce
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,8 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: aacefbb114f024ec0bd6d3153b28bb36
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 12 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 34 KiB |
@@ -1,88 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 9b9aa386e19cb4bf4b7e055e962419e2
|
||||
TextureImporter:
|
||||
fileIDToRecycleName: {}
|
||||
externalObjects: {}
|
||||
serializedVersion: 9
|
||||
mipmaps:
|
||||
mipMapMode: 0
|
||||
enableMipMap: 0
|
||||
sRGBTexture: 1
|
||||
linearTexture: 0
|
||||
fadeOut: 0
|
||||
borderMipMap: 0
|
||||
mipMapsPreserveCoverage: 0
|
||||
alphaTestReferenceValue: 0.5
|
||||
mipMapFadeDistanceStart: 1
|
||||
mipMapFadeDistanceEnd: 3
|
||||
bumpmap:
|
||||
convertToNormalMap: 0
|
||||
externalNormalMap: 0
|
||||
heightScale: 0.25
|
||||
normalMapFilter: 0
|
||||
isReadable: 0
|
||||
streamingMipmaps: 0
|
||||
streamingMipmapsPriority: 0
|
||||
grayScaleToAlpha: 0
|
||||
generateCubemap: 6
|
||||
cubemapConvolution: 0
|
||||
seamlessCubemap: 0
|
||||
textureFormat: -1
|
||||
maxTextureSize: 2048
|
||||
textureSettings:
|
||||
serializedVersion: 2
|
||||
filterMode: 0
|
||||
aniso: 16
|
||||
mipBias: -100
|
||||
wrapU: 1
|
||||
wrapV: 1
|
||||
wrapW: 1
|
||||
nPOTScale: 0
|
||||
lightmap: 0
|
||||
compressionQuality: 50
|
||||
spriteMode: 1
|
||||
spriteExtrude: 1
|
||||
spriteMeshType: 1
|
||||
alignment: 0
|
||||
spritePivot: {x: 0.5, y: 0.5}
|
||||
spritePixelsToUnits: 100
|
||||
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
|
||||
spriteGenerateFallbackPhysicsShape: 1
|
||||
alphaUsage: 1
|
||||
alphaIsTransparency: 1
|
||||
spriteTessellationDetail: -1
|
||||
textureType: 8
|
||||
textureShape: 1
|
||||
singleChannelComponent: 0
|
||||
maxTextureSizeSet: 0
|
||||
compressionQualitySet: 0
|
||||
textureFormatSet: 0
|
||||
platformSettings:
|
||||
- serializedVersion: 2
|
||||
buildTarget: DefaultTexturePlatform
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
spriteSheet:
|
||||
serializedVersion: 2
|
||||
sprites: []
|
||||
outline: []
|
||||
physicsShape: []
|
||||
bones: []
|
||||
spriteID: 84e9fd7e25cf94cfc81bd77bc4f1d566
|
||||
vertices: []
|
||||
indices:
|
||||
edges: []
|
||||
weights: []
|
||||
spritePackingTag:
|
||||
pSDRemoveMatte: 0
|
||||
pSDShowRemoveMatteOption: 0
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user