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
50 Commits
v4.7.1
...
5.0.0-prev
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
fab2ed1697 | ||
|
|
ef4dbc3cba | ||
|
|
27551a4d47 | ||
|
|
90d966e659 | ||
|
|
0036b03d12 | ||
|
|
934f4b8f1c | ||
|
|
fe4fcc5ddd | ||
|
|
072aac521b | ||
|
|
95235a929b | ||
|
|
1a748f19d0 | ||
|
|
f9ce2c6c96 | ||
|
|
abe09485f6 | ||
|
|
253fb52650 | ||
|
|
3544c593e2 | ||
|
|
4faf151c87 | ||
|
|
afe00a1dde | ||
|
|
c1e3d68f60 | ||
|
|
a1ea8785bc | ||
|
|
2ee69d0424 | ||
|
|
2c1ac4b5e9 | ||
|
|
5f255ec6cd | ||
|
|
1b678c68c6 | ||
|
|
5ff6ec815a | ||
|
|
0ee1671246 | ||
|
|
6a7f08c056 | ||
|
|
1ce4e31a96 | ||
|
|
c08f0d492f | ||
|
|
7069b396e4 | ||
|
|
109caed657 | ||
|
|
2a1cd502b4 | ||
|
|
78d0219235 | ||
|
|
de5c617d12 | ||
|
|
15f9d92567 | ||
|
|
55fb8a0076 | ||
|
|
e6d8e43966 | ||
|
|
10a7fb4b7b | ||
|
|
3834780fdb | ||
|
|
307ed1bf01 | ||
|
|
669deb41d4 | ||
|
|
24e0e8697d | ||
|
|
3e3e35beca | ||
|
|
a182709472 | ||
|
|
be901724e0 | ||
|
|
88a970d93a | ||
|
|
a703c2921c | ||
|
|
de35cba34c | ||
|
|
ae3f3a8e62 | ||
|
|
835817049f | ||
|
|
7035583bdb | ||
|
|
0bb8438301 |
@@ -25,6 +25,7 @@ indent_size = 4
|
||||
trim_trailing_whitespace = true
|
||||
insert_final_newline = true
|
||||
|
||||
csharp_style_namespace_declarations = block_scoped
|
||||
csharp_style_implicit_object_creation_when_type_is_apparent = false
|
||||
resharper_object_creation_when_type_evident = explicitly_typed
|
||||
|
||||
@@ -86,6 +87,9 @@ csharp_style_var_elsewhere = true:suggestion
|
||||
dotnet_style_predefined_type_for_locals_parameters_members = true:suggestion
|
||||
dotnet_style_predefined_type_for_member_access = true:suggestion
|
||||
|
||||
#
|
||||
resharper_keep_existing_embedded_arrangement = true
|
||||
|
||||
# Arguments
|
||||
csharp_arguments_literal = named:suggestion
|
||||
csharp_arguments_string_literal = named:suggestion
|
||||
@@ -134,7 +138,7 @@ dotnet_naming_style._camel_case.capitalization = camel_case
|
||||
|
||||
# Code style defaults
|
||||
dotnet_sort_system_directives_first = true
|
||||
csharp_preserve_single_line_statements = false:none
|
||||
csharp_preserve_single_line_statements = false
|
||||
csharp_prefer_static_local_function = true:suggestion
|
||||
csharp_prefer_simple_using_statement = false:none
|
||||
csharp_style_prefer_switch_expression = true:suggestion
|
||||
@@ -186,7 +190,7 @@ csharp_space_after_dot = false
|
||||
csharp_space_after_keywords_in_control_flow_statements = true
|
||||
csharp_space_after_semicolon_in_for_statement = true
|
||||
csharp_space_around_binary_operators = before_and_after
|
||||
csharp_space_around_declaration_statements = do_not_ignore
|
||||
csharp_space_around_declaration_statements = false
|
||||
csharp_space_before_colon_in_inheritance_clause = true
|
||||
csharp_space_before_comma = false
|
||||
csharp_space_before_dot = false
|
||||
|
||||
20
.github/workflows/release.yml
vendored
20
.github/workflows/release.yml
vendored
@@ -1,12 +1,12 @@
|
||||
name: 🔖 Release
|
||||
run-name: 🔖 Release (${{ github.ref_name }})
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
push:
|
||||
branches:
|
||||
- release
|
||||
- release-preview
|
||||
- release-v4
|
||||
- release-*
|
||||
tags-ignore:
|
||||
- "**"
|
||||
|
||||
@@ -38,7 +38,7 @@ jobs:
|
||||
@semantic-release/changelog
|
||||
@semantic-release/git
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ github.token }}
|
||||
GITHUB_TOKEN: ${{ secrets.GH_TOKEN }}
|
||||
|
||||
- id: summary
|
||||
run: |
|
||||
@@ -50,14 +50,12 @@ jobs:
|
||||
if [ '${{ steps.release.outputs.new_release_published }}' = 'false' ]; then
|
||||
echo "No new release published." | tee -a $GITHUB_STEP_SUMMARY
|
||||
elif [ '${{ github.ref_name }}' = 'release' ]; then
|
||||
echo "merge_to=develop" | tee -a $GITHUB_OUTPUT
|
||||
echo "split_to=main" | tee -a $GITHUB_OUTPUT
|
||||
elif [ '${{ github.ref_name }}' = 'release-preview' ]; then
|
||||
echo "merge_to=develop-preview" | tee -a $GITHUB_OUTPUT
|
||||
echo "split_to=preview" | tee -a $GITHUB_OUTPUT
|
||||
elif [ '${{ github.ref_name }}' = 'release-4.x' ]; then
|
||||
echo "merge_to=develop-4.x" | tee -a $GITHUB_OUTPUT
|
||||
echo "split_to=4.x" | tee -a $GITHUB_OUTPUT
|
||||
echo "merge_to=develop" | tee -a $GITHUB_OUTPUT $GITHUB_STEP_SUMMARY
|
||||
echo "split_to=main" | tee -a $GITHUB_OUTPUT $GITHUB_STEP_SUMMARY
|
||||
else
|
||||
channel=$(echo ${{ github.ref_name }} | sed 's/^release-//')
|
||||
echo "merge_to=develop-${channel}" | tee -a $GITHUB_OUTPUT $GITHUB_STEP_SUMMARY
|
||||
echo "split_to=${channel}" | tee -a $GITHUB_OUTPUT $GITHUB_STEP_SUMMARY
|
||||
fi
|
||||
|
||||
merge-to:
|
||||
|
||||
61
.github/workflows/test.yml
vendored
61
.github/workflows/test.yml
vendored
@@ -3,28 +3,36 @@
|
||||
# UNITY_EMAIL: Unity user email to login
|
||||
# UNITY_PASSWORD: Unity user password to login
|
||||
name: 🧪 Test
|
||||
run-name: 🧪 Test (${{ github.event.pull_request.title || github.ref_name }})
|
||||
|
||||
env:
|
||||
# MINIMUM_VERSION: The minimum version of Unity.
|
||||
MINIMUM_VERSION: 2019.4
|
||||
# EXCLUDE_FILTER: The excluded versions of Unity.
|
||||
EXCLUDE_FILTER: '(2020.2.0)'
|
||||
EXCLUDE_FILTER: "(2020.2.0|2021.1|2023.3)"
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
usePeriodVersions:
|
||||
description: "Use the period versions (.0f1, .10f1, 20f1, ...)."
|
||||
required: false
|
||||
default: "true"
|
||||
push:
|
||||
branches:
|
||||
- develop
|
||||
- develop-preview
|
||||
- develop-4.x
|
||||
tags:
|
||||
- "!*"
|
||||
paths-ignore:
|
||||
- "*.md"
|
||||
pull_request:
|
||||
- "**.md"
|
||||
pull_request_target:
|
||||
types:
|
||||
- opened
|
||||
- reopened
|
||||
- synchronize
|
||||
paths-ignore:
|
||||
- "**.md"
|
||||
|
||||
jobs:
|
||||
setup:
|
||||
@@ -37,9 +45,12 @@ jobs:
|
||||
id: setup
|
||||
run: |
|
||||
echo "==== Target Unity Versions ===="
|
||||
LATEST_VERSIONS=`npx unity-changeset list --versions --latest-patch --min ${MINIMUM_VERSION} --json --all`
|
||||
# ADDITIONAL_VERSIONS=`npx unity-changeset list --versions --grep '0f' --min ${MINIMUM_VERSION} --json`
|
||||
ADDITIONAL_VERSIONS=[]
|
||||
LATEST_VERSIONS=`npx unity-changeset@latest list --versions --latest-patch --min ${MINIMUM_VERSION} --json --all`
|
||||
if [ "${{ inputs.usePeriodVersions }}" = "true" ]; then
|
||||
ADDITIONAL_VERSIONS=`npx unity-changeset list --versions --grep '0f' --min ${MINIMUM_VERSION} --json`
|
||||
else
|
||||
ADDITIONAL_VERSIONS=[]
|
||||
fi
|
||||
|
||||
VERSIONS=`echo "[${LATEST_VERSIONS}, ${ADDITIONAL_VERSIONS}]" \
|
||||
| jq -c '[ flatten | sort | unique | .[] | select( test("${{ env.EXCLUDE_FILTER }}") | not ) ]'`
|
||||
@@ -48,33 +59,44 @@ jobs:
|
||||
test:
|
||||
name: 🧪 Run tests
|
||||
runs-on: ubuntu-latest
|
||||
env:
|
||||
UNITY_EMAIL: ${{ secrets.UNITY_EMAIL }}
|
||||
UNITY_PASSWORD: ${{ secrets.UNITY_PASSWORD }}
|
||||
UNITY_LICENSE: ${{ secrets.UNITY_LICENSE }}
|
||||
permissions:
|
||||
checks: write
|
||||
contents: read
|
||||
needs: setup
|
||||
strategy:
|
||||
fail-fast: false
|
||||
max-parallel: 4
|
||||
max-parallel: 6
|
||||
matrix:
|
||||
unityVersion: ${{ fromJson(needs.setup.outputs.unityVersions) }}
|
||||
steps:
|
||||
- name: 🚚 Checkout
|
||||
- name: 🚚 Checkout ($${{ github.ref }})
|
||||
if: github.event_name == 'push'
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: 🚚 Checkout pull request (pull_request_target)
|
||||
if: github.event_name == 'pull_request_target'
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
ref: ${{ github.event.pull_request.head.sha }}
|
||||
fetch-depth: 0
|
||||
|
||||
- name: 🚚 Marge pull request (pull_request_target)
|
||||
if: github.event_name == 'pull_request_target'
|
||||
run: |
|
||||
git config user.name "GitHub Actions"
|
||||
git config user.email "actions@github.com"
|
||||
git merge origin/${{ github.event.pull_request.base.ref }} --no-edit
|
||||
|
||||
- name: 📥 Cache library
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: Library
|
||||
key: Library-${{ matrix.unityVersion }}-${{ github.sha }}
|
||||
key: Library-${{ matrix.unityVersion }}-${{ github.event.pull_request.head.sha || github.sha }}
|
||||
restore-keys: |
|
||||
Library-${{ matrix.unityVersion }}-
|
||||
Library-
|
||||
|
||||
- name: 🛠️ Build Unity Project
|
||||
- name: 🛠️ Build Unity Project (Test)
|
||||
uses: game-ci/unity-builder@v4
|
||||
timeout-minutes: 45
|
||||
with:
|
||||
@@ -82,6 +104,10 @@ jobs:
|
||||
targetPlatform: StandaloneLinux64
|
||||
allowDirtyBuild: true
|
||||
customParameters: -nographics
|
||||
env:
|
||||
UNITY_EMAIL: ${{ secrets.UNITY_EMAIL }}
|
||||
UNITY_PASSWORD: ${{ secrets.UNITY_PASSWORD }}
|
||||
UNITY_LICENSE: ${{ secrets.UNITY_LICENSE }}
|
||||
|
||||
- name: 🧪 Run tests
|
||||
uses: game-ci/unity-test-runner@v4
|
||||
@@ -92,4 +118,7 @@ jobs:
|
||||
customParameters: -nographics
|
||||
checkName: ${{ matrix.unityVersion }} Test Results
|
||||
githubToken: ${{ github.token }}
|
||||
coverageOptions: "dontClear;generateHtmlReport;generateBadgeReport;pathFilters:+**/Packages/src/**;assemblyFilters:+<packages>,-*.Editor,-*.Test"
|
||||
env:
|
||||
UNITY_EMAIL: ${{ secrets.UNITY_EMAIL }}
|
||||
UNITY_PASSWORD: ${{ secrets.UNITY_PASSWORD }}
|
||||
UNITY_LICENSE: ${{ secrets.UNITY_LICENSE }}
|
||||
|
||||
7046
Assets/Demo/Cartoon FX & War FX Demo/CFXRF Demo.unity
Normal file
7046
Assets/Demo/Cartoon FX & War FX Demo/CFXRF Demo.unity
Normal file
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,4 @@
|
||||
fileFormatVersion: 2
|
||||
guid: e34a092899a9547189add96707de1b5a
|
||||
DefaultImporter:
|
||||
userData:
|
||||
@@ -80,7 +80,11 @@ namespace Coffee.UIExtensions.Demo
|
||||
.SelectMany(x => x.GetTypes())
|
||||
.FirstOrDefault(x => x.Name == typeName);
|
||||
|
||||
#if UNITY_2023_2_OR_NEWER
|
||||
return type == null ? null : FindFirstObjectByType(type);
|
||||
#else
|
||||
return type == null ? null : FindObjectOfType(type);
|
||||
#endif
|
||||
}
|
||||
|
||||
public void SetCanvasWidth(int width)
|
||||
|
||||
8
Assets/Demo/CustomView.meta
Normal file
8
Assets/Demo/CustomView.meta
Normal file
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 157d70e6cb69d4581b4ed450c7ffd33d
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
20178
Assets/Demo/CustomView/CustomView.unity
Normal file
20178
Assets/Demo/CustomView/CustomView.unity
Normal file
File diff suppressed because it is too large
Load Diff
@@ -1,6 +1,6 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 46deb9632f6a14713b8460bd01e879c9
|
||||
PrefabImporter:
|
||||
guid: dfba9a6f2258941f5b4429fba806d8e9
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
42
Assets/Demo/CustomView/UI-Cloud.mat
Normal file
42
Assets/Demo/CustomView/UI-Cloud.mat
Normal file
@@ -0,0 +1,42 @@
|
||||
%YAML 1.1
|
||||
%TAG !u! tag:unity3d.com,2011:
|
||||
--- !u!21 &2100000
|
||||
Material:
|
||||
serializedVersion: 8
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_Name: UI-Cloud
|
||||
m_Shader: {fileID: 4800000, guid: 6b5e4f608f0684d10a4673a7e1cee0f3, type: 3}
|
||||
m_ValidKeywords: []
|
||||
m_InvalidKeywords:
|
||||
- _COLORMODE_MULTIPRY
|
||||
m_LightmapFlags: 4
|
||||
m_EnableInstancingVariants: 0
|
||||
m_DoubleSidedGI: 0
|
||||
m_CustomRenderQueue: -1
|
||||
stringTagMap: {}
|
||||
disabledShaderPasses: []
|
||||
m_SavedProperties:
|
||||
serializedVersion: 3
|
||||
m_TexEnvs:
|
||||
- _MainTex:
|
||||
m_Texture: {fileID: 2800000, guid: 48901c5d75f8c456aa8f4cd3a6b0160e, type: 3}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
m_Ints: []
|
||||
m_Floats:
|
||||
- _ColorMask: 15
|
||||
- _ColorMode: 0
|
||||
- _DstBlend: 10
|
||||
- _SrcBlend: 1
|
||||
- _Stencil: 0
|
||||
- _StencilComp: 8
|
||||
- _StencilOp: 0
|
||||
- _StencilReadMask: 255
|
||||
- _StencilWriteMask: 255
|
||||
- _UseUIAlphaClip: 0
|
||||
m_Colors:
|
||||
- _Color: {r: 1, g: 1, b: 1, a: 1}
|
||||
m_BuildTextureStacks: []
|
||||
8
Assets/Demo/CustomView/UI-Cloud.mat.meta
Normal file
8
Assets/Demo/CustomView/UI-Cloud.mat.meta
Normal file
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 607b55fe0d4534a56902644d3797abed
|
||||
NativeFormatImporter:
|
||||
externalObjects: {}
|
||||
mainObjectFileID: 2100000
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
BIN
Assets/Demo/CustomView/UI-Cloud.png
Normal file
BIN
Assets/Demo/CustomView/UI-Cloud.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 27 KiB |
147
Assets/Demo/CustomView/UI-Cloud.png.meta
Normal file
147
Assets/Demo/CustomView/UI-Cloud.png.meta
Normal file
@@ -0,0 +1,147 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 48901c5d75f8c456aa8f4cd3a6b0160e
|
||||
TextureImporter:
|
||||
internalIDToNameTable: []
|
||||
externalObjects: {}
|
||||
serializedVersion: 12
|
||||
mipmaps:
|
||||
mipMapMode: 0
|
||||
enableMipMap: 0
|
||||
sRGBTexture: 1
|
||||
linearTexture: 0
|
||||
fadeOut: 0
|
||||
borderMipMap: 0
|
||||
mipMapsPreserveCoverage: 0
|
||||
alphaTestReferenceValue: 0.5
|
||||
mipMapFadeDistanceStart: 1
|
||||
mipMapFadeDistanceEnd: 3
|
||||
bumpmap:
|
||||
convertToNormalMap: 0
|
||||
externalNormalMap: 0
|
||||
heightScale: 0.25
|
||||
normalMapFilter: 0
|
||||
isReadable: 0
|
||||
streamingMipmaps: 0
|
||||
streamingMipmapsPriority: 0
|
||||
vTOnly: 0
|
||||
ignoreMasterTextureLimit: 0
|
||||
grayScaleToAlpha: 0
|
||||
generateCubemap: 6
|
||||
cubemapConvolution: 0
|
||||
seamlessCubemap: 0
|
||||
textureFormat: 1
|
||||
maxTextureSize: 2048
|
||||
textureSettings:
|
||||
serializedVersion: 2
|
||||
filterMode: 1
|
||||
aniso: 1
|
||||
mipBias: 0
|
||||
wrapU: 1
|
||||
wrapV: 1
|
||||
wrapW: 1
|
||||
nPOTScale: 0
|
||||
lightmap: 0
|
||||
compressionQuality: 50
|
||||
spriteMode: 1
|
||||
spriteExtrude: 1
|
||||
spriteMeshType: 1
|
||||
alignment: 0
|
||||
spritePivot: {x: 0.5, y: 0.5}
|
||||
spritePixelsToUnits: 100
|
||||
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
|
||||
spriteGenerateFallbackPhysicsShape: 1
|
||||
alphaUsage: 1
|
||||
alphaIsTransparency: 1
|
||||
spriteTessellationDetail: -1
|
||||
textureType: 0
|
||||
textureShape: 1
|
||||
singleChannelComponent: 0
|
||||
flipbookRows: 1
|
||||
flipbookColumns: 1
|
||||
maxTextureSizeSet: 0
|
||||
compressionQualitySet: 0
|
||||
textureFormatSet: 0
|
||||
ignorePngGamma: 0
|
||||
applyGammaDecoding: 1
|
||||
cookieLightType: 1
|
||||
platformSettings:
|
||||
- serializedVersion: 3
|
||||
buildTarget: DefaultTexturePlatform
|
||||
maxTextureSize: 256
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
- serializedVersion: 3
|
||||
buildTarget: Standalone
|
||||
maxTextureSize: 256
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
- serializedVersion: 3
|
||||
buildTarget: Android
|
||||
maxTextureSize: 256
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 1
|
||||
- serializedVersion: 3
|
||||
buildTarget: WebGL
|
||||
maxTextureSize: 256
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
- serializedVersion: 3
|
||||
buildTarget: Server
|
||||
maxTextureSize: 256
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
spriteSheet:
|
||||
serializedVersion: 2
|
||||
sprites: []
|
||||
outline: []
|
||||
physicsShape: []
|
||||
bones: []
|
||||
spriteID: 5e97eb03825dee720800000000000000
|
||||
internalID: 0
|
||||
vertices: []
|
||||
indices:
|
||||
edges: []
|
||||
weights: []
|
||||
secondaryTextures: []
|
||||
nameFileIdTable: {}
|
||||
spritePackingTag:
|
||||
pSDRemoveMatte: 0
|
||||
pSDShowRemoveMatteOption: 0
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
177
Assets/Demo/CustomView/UI-Color.shader
Normal file
177
Assets/Demo/CustomView/UI-Color.shader
Normal file
@@ -0,0 +1,177 @@
|
||||
Shader "UI/Color"
|
||||
{
|
||||
Properties
|
||||
{
|
||||
_MainTex ("Main Texture", 2D) = "white" {}
|
||||
_Color ("Tint", Color) = (1,1,1,1)
|
||||
[KeywordEnum(Multipry, Additive, Subtract, Fill)] _ColorMode ("Color Mode", Int) = 0
|
||||
[Enum(UnityEngine.Rendering.BlendMode)] _SrcBlend ("Src Blend Mode", Int) = 1
|
||||
[Enum(UnityEngine.Rendering.BlendMode)] _DstBlend ("Dst Blend Mode", Int) = 10
|
||||
|
||||
_StencilComp ("Stencil Comparison", Float) = 8
|
||||
_Stencil ("Stencil ID", Float) = 0
|
||||
_StencilOp ("Stencil Operation", Float) = 0
|
||||
_StencilWriteMask ("Stencil Write Mask", Float) = 255
|
||||
_StencilReadMask ("Stencil Read Mask", Float) = 255
|
||||
|
||||
_ColorMask ("Color Mask", Float) = 15
|
||||
|
||||
[Toggle(UNITY_UI_ALPHACLIP)] _UseUIAlphaClip ("Use Alpha Clip", Float) = 0
|
||||
}
|
||||
|
||||
SubShader
|
||||
{
|
||||
Tags
|
||||
{
|
||||
"Queue"="Transparent"
|
||||
"IgnoreProjector"="True"
|
||||
"RenderType"="Transparent"
|
||||
"PreviewType"="Plane"
|
||||
"CanUseSpriteAtlas"="True"
|
||||
}
|
||||
|
||||
Stencil
|
||||
{
|
||||
Ref [_Stencil]
|
||||
Comp [_StencilComp]
|
||||
Pass [_StencilOp]
|
||||
ReadMask [_StencilReadMask]
|
||||
WriteMask [_StencilWriteMask]
|
||||
}
|
||||
|
||||
Cull Off
|
||||
Lighting Off
|
||||
ZWrite Off
|
||||
ZTest [unity_GUIZTestMode]
|
||||
Blend [_SrcBlend] [_DstBlend]
|
||||
ColorMask [_ColorMask]
|
||||
|
||||
Pass
|
||||
{
|
||||
Name "Default"
|
||||
CGPROGRAM
|
||||
#pragma vertex vert
|
||||
#pragma fragment frag
|
||||
#pragma target 2.0
|
||||
|
||||
#include "UnityCG.cginc"
|
||||
#include "UnityUI.cginc"
|
||||
|
||||
#pragma multi_compile_local _ UNITY_UI_CLIP_RECT
|
||||
#pragma multi_compile_local _ UNITY_UI_ALPHACLIP
|
||||
|
||||
sampler2D _MainTex;
|
||||
fixed4 _Color;
|
||||
fixed4 _TextureSampleAdd;
|
||||
float4 _ClipRect;
|
||||
float4 _MainTex_ST;
|
||||
float _UIMaskSoftnessX;
|
||||
float _UIMaskSoftnessY;
|
||||
int _UIVertexColorAlwaysGammaSpace;
|
||||
int _ColorMode;
|
||||
|
||||
struct appdata_t
|
||||
{
|
||||
float4 vertex : POSITION;
|
||||
float4 color : COLOR;
|
||||
float2 texcoord : TEXCOORD0;
|
||||
UNITY_VERTEX_INPUT_INSTANCE_ID
|
||||
};
|
||||
|
||||
struct v2f
|
||||
{
|
||||
float4 vertex : SV_POSITION;
|
||||
fixed4 color : COLOR;
|
||||
float2 texcoord : TEXCOORD0;
|
||||
float4 worldPosition : TEXCOORD1;
|
||||
float4 mask : TEXCOORD2;
|
||||
UNITY_VERTEX_OUTPUT_STEREO
|
||||
};
|
||||
|
||||
v2f vert(appdata_t v)
|
||||
{
|
||||
v2f OUT;
|
||||
UNITY_SETUP_INSTANCE_ID(v);
|
||||
UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(OUT);
|
||||
float4 vPosition = UnityObjectToClipPos(v.vertex);
|
||||
OUT.worldPosition = v.vertex;
|
||||
OUT.vertex = vPosition;
|
||||
|
||||
float2 pixelSize = vPosition.w;
|
||||
pixelSize /= float2(1, 1) * abs(mul((float2x2)UNITY_MATRIX_P, _ScreenParams.xy));
|
||||
|
||||
float4 clampedRect = clamp(_ClipRect, -2e10, 2e10);
|
||||
float2 maskUV = (v.vertex.xy - clampedRect.xy) / (clampedRect.zw - clampedRect.xy);
|
||||
OUT.texcoord = TRANSFORM_TEX(v.texcoord.xy, _MainTex);
|
||||
OUT.mask = float4(v.vertex.xy * 2 - clampedRect.xy - clampedRect.zw,
|
||||
0.25 / (0.25 * half2(_UIMaskSoftnessX, _UIMaskSoftnessY) + abs(pixelSize.xy)));
|
||||
|
||||
if (_UIVertexColorAlwaysGammaSpace)
|
||||
{
|
||||
if (!IsGammaSpace())
|
||||
{
|
||||
v.color.rgb = GammaToLinearSpace(v.color.rgb);
|
||||
}
|
||||
}
|
||||
|
||||
OUT.color = v.color * _Color;
|
||||
return OUT;
|
||||
}
|
||||
|
||||
half4 apply_color(half4 color, const half4 factor, const int mode)
|
||||
{
|
||||
const half3 c = factor.rgb * color.a;
|
||||
// Mode 1: Additive
|
||||
if (mode == 1)
|
||||
{
|
||||
color.rgb += c;
|
||||
}
|
||||
// Mode 2: Subtract
|
||||
else if (mode == 2)
|
||||
{
|
||||
color.rgb -= c;
|
||||
}
|
||||
// Mode 3: Replace
|
||||
else if (mode == 3)
|
||||
{
|
||||
color.rgb = c;
|
||||
}
|
||||
// Default: Multiply
|
||||
else
|
||||
{
|
||||
color.rgb *= c;
|
||||
}
|
||||
|
||||
return color * factor.a;
|
||||
}
|
||||
|
||||
fixed4 frag(v2f IN) : SV_Target
|
||||
{
|
||||
//Round up the alpha color coming from the interpolator (to 1.0/256.0 steps)
|
||||
//The incoming alpha could have numerical instability, which makes it very sensible to
|
||||
//HDR color transparency blend, when it blends with the world's texture.
|
||||
const half alphaPrecision = half(0xff);
|
||||
const half invAlphaPrecision = half(1.0 / alphaPrecision);
|
||||
float2 uv = IN.texcoord;
|
||||
|
||||
IN.color.a = round(IN.color.a * alphaPrecision) * invAlphaPrecision;
|
||||
half4 color = tex2D(_MainTex, uv) + _TextureSampleAdd;
|
||||
|
||||
#if UNITY_UI_CLIP_RECT
|
||||
half2 m = saturate((_ClipRect.zw - _ClipRect.xy - abs(IN.mask.xy)) * IN.mask.zw);
|
||||
color.a *= m.x * m.y;
|
||||
#endif
|
||||
|
||||
#if UNITY_UI_ALPHACLIP
|
||||
clip (color.a - 0.001);
|
||||
#endif
|
||||
|
||||
// Apply color mode.
|
||||
color = apply_color(color, IN.color, _ColorMode);
|
||||
|
||||
return color;
|
||||
}
|
||||
ENDCG
|
||||
}
|
||||
}
|
||||
}
|
||||
10
Assets/Demo/CustomView/UI-Color.shader.meta
Normal file
10
Assets/Demo/CustomView/UI-Color.shader.meta
Normal file
@@ -0,0 +1,10 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 6b5e4f608f0684d10a4673a7e1cee0f3
|
||||
ShaderImporter:
|
||||
externalObjects: {}
|
||||
defaultTextures: []
|
||||
nonModifiableTextures: []
|
||||
preprocessorOverride: 0
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
42
Assets/Demo/CustomView/UI-Star-Add.mat
Normal file
42
Assets/Demo/CustomView/UI-Star-Add.mat
Normal file
@@ -0,0 +1,42 @@
|
||||
%YAML 1.1
|
||||
%TAG !u! tag:unity3d.com,2011:
|
||||
--- !u!21 &2100000
|
||||
Material:
|
||||
serializedVersion: 8
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_Name: UI-Star-Add
|
||||
m_Shader: {fileID: 4800000, guid: 6b5e4f608f0684d10a4673a7e1cee0f3, type: 3}
|
||||
m_ValidKeywords: []
|
||||
m_InvalidKeywords:
|
||||
- _COLORMODE_MULTIPRY
|
||||
m_LightmapFlags: 4
|
||||
m_EnableInstancingVariants: 0
|
||||
m_DoubleSidedGI: 0
|
||||
m_CustomRenderQueue: -1
|
||||
stringTagMap: {}
|
||||
disabledShaderPasses: []
|
||||
m_SavedProperties:
|
||||
serializedVersion: 3
|
||||
m_TexEnvs:
|
||||
- _MainTex:
|
||||
m_Texture: {fileID: 2800000, guid: 8412a67c0342348169bea68bf9315a14, type: 3}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
m_Ints: []
|
||||
m_Floats:
|
||||
- _ColorMask: 15
|
||||
- _ColorMode: 0
|
||||
- _DstBlend: 1
|
||||
- _SrcBlend: 1
|
||||
- _Stencil: 0
|
||||
- _StencilComp: 8
|
||||
- _StencilOp: 0
|
||||
- _StencilReadMask: 255
|
||||
- _StencilWriteMask: 255
|
||||
- _UseUIAlphaClip: 0
|
||||
m_Colors:
|
||||
- _Color: {r: 1, g: 1, b: 1, a: 1}
|
||||
m_BuildTextureStacks: []
|
||||
8
Assets/Demo/CustomView/UI-Star-Add.mat.meta
Normal file
8
Assets/Demo/CustomView/UI-Star-Add.mat.meta
Normal file
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: e4d32268c77b14dd99f0e99fcfcd3a46
|
||||
NativeFormatImporter:
|
||||
externalObjects: {}
|
||||
mainObjectFileID: 2100000
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
42
Assets/Demo/CustomView/UI-Star.mat
Normal file
42
Assets/Demo/CustomView/UI-Star.mat
Normal file
@@ -0,0 +1,42 @@
|
||||
%YAML 1.1
|
||||
%TAG !u! tag:unity3d.com,2011:
|
||||
--- !u!21 &2100000
|
||||
Material:
|
||||
serializedVersion: 8
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_Name: UI-Star
|
||||
m_Shader: {fileID: 4800000, guid: 6b5e4f608f0684d10a4673a7e1cee0f3, type: 3}
|
||||
m_ValidKeywords: []
|
||||
m_InvalidKeywords:
|
||||
- _COLORMODE_MULTIPRY
|
||||
m_LightmapFlags: 4
|
||||
m_EnableInstancingVariants: 0
|
||||
m_DoubleSidedGI: 0
|
||||
m_CustomRenderQueue: -1
|
||||
stringTagMap: {}
|
||||
disabledShaderPasses: []
|
||||
m_SavedProperties:
|
||||
serializedVersion: 3
|
||||
m_TexEnvs:
|
||||
- _MainTex:
|
||||
m_Texture: {fileID: 2800000, guid: 8412a67c0342348169bea68bf9315a14, type: 3}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
m_Ints: []
|
||||
m_Floats:
|
||||
- _ColorMask: 15
|
||||
- _ColorMode: 0
|
||||
- _DstBlend: 10
|
||||
- _SrcBlend: 1
|
||||
- _Stencil: 0
|
||||
- _StencilComp: 8
|
||||
- _StencilOp: 0
|
||||
- _StencilReadMask: 255
|
||||
- _StencilWriteMask: 255
|
||||
- _UseUIAlphaClip: 0
|
||||
m_Colors:
|
||||
- _Color: {r: 1, g: 1, b: 1, a: 1}
|
||||
m_BuildTextureStacks: []
|
||||
8
Assets/Demo/CustomView/UI-Star.mat.meta
Normal file
8
Assets/Demo/CustomView/UI-Star.mat.meta
Normal file
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 4c756ed674dab453eb1d0a7d9360a9c1
|
||||
NativeFormatImporter:
|
||||
externalObjects: {}
|
||||
mainObjectFileID: 2100000
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
BIN
Assets/Demo/CustomView/UI-Star.png
Normal file
BIN
Assets/Demo/CustomView/UI-Star.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 15 KiB |
147
Assets/Demo/CustomView/UI-Star.png.meta
Normal file
147
Assets/Demo/CustomView/UI-Star.png.meta
Normal file
@@ -0,0 +1,147 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 8412a67c0342348169bea68bf9315a14
|
||||
TextureImporter:
|
||||
internalIDToNameTable: []
|
||||
externalObjects: {}
|
||||
serializedVersion: 12
|
||||
mipmaps:
|
||||
mipMapMode: 0
|
||||
enableMipMap: 0
|
||||
sRGBTexture: 1
|
||||
linearTexture: 0
|
||||
fadeOut: 0
|
||||
borderMipMap: 0
|
||||
mipMapsPreserveCoverage: 0
|
||||
alphaTestReferenceValue: 0.5
|
||||
mipMapFadeDistanceStart: 1
|
||||
mipMapFadeDistanceEnd: 3
|
||||
bumpmap:
|
||||
convertToNormalMap: 0
|
||||
externalNormalMap: 0
|
||||
heightScale: 0.25
|
||||
normalMapFilter: 0
|
||||
isReadable: 0
|
||||
streamingMipmaps: 0
|
||||
streamingMipmapsPriority: 0
|
||||
vTOnly: 0
|
||||
ignoreMasterTextureLimit: 0
|
||||
grayScaleToAlpha: 0
|
||||
generateCubemap: 6
|
||||
cubemapConvolution: 0
|
||||
seamlessCubemap: 0
|
||||
textureFormat: 1
|
||||
maxTextureSize: 2048
|
||||
textureSettings:
|
||||
serializedVersion: 2
|
||||
filterMode: 1
|
||||
aniso: 1
|
||||
mipBias: 0
|
||||
wrapU: 1
|
||||
wrapV: 1
|
||||
wrapW: 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: 2
|
||||
alphaIsTransparency: 1
|
||||
spriteTessellationDetail: -1
|
||||
textureType: 0
|
||||
textureShape: 1
|
||||
singleChannelComponent: 0
|
||||
flipbookRows: 1
|
||||
flipbookColumns: 1
|
||||
maxTextureSizeSet: 0
|
||||
compressionQualitySet: 0
|
||||
textureFormatSet: 0
|
||||
ignorePngGamma: 0
|
||||
applyGammaDecoding: 1
|
||||
cookieLightType: 1
|
||||
platformSettings:
|
||||
- serializedVersion: 3
|
||||
buildTarget: DefaultTexturePlatform
|
||||
maxTextureSize: 128
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
- serializedVersion: 3
|
||||
buildTarget: Standalone
|
||||
maxTextureSize: 128
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
- serializedVersion: 3
|
||||
buildTarget: Android
|
||||
maxTextureSize: 128
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 1
|
||||
- serializedVersion: 3
|
||||
buildTarget: WebGL
|
||||
maxTextureSize: 128
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: 63
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 1
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
- serializedVersion: 3
|
||||
buildTarget: Server
|
||||
maxTextureSize: 128
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
spriteSheet:
|
||||
serializedVersion: 2
|
||||
sprites: []
|
||||
outline: []
|
||||
physicsShape: []
|
||||
bones: []
|
||||
spriteID: 5e97eb03825dee720800000000000000
|
||||
internalID: 0
|
||||
vertices: []
|
||||
indices:
|
||||
edges: []
|
||||
weights: []
|
||||
secondaryTextures: []
|
||||
nameFileIdTable: {}
|
||||
spritePackingTag:
|
||||
pSDRemoveMatte: 0
|
||||
pSDShowRemoveMatteOption: 0
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
42
Assets/Demo/CustomView/UI-StretchTrait.mat
Normal file
42
Assets/Demo/CustomView/UI-StretchTrait.mat
Normal file
@@ -0,0 +1,42 @@
|
||||
%YAML 1.1
|
||||
%TAG !u! tag:unity3d.com,2011:
|
||||
--- !u!21 &2100000
|
||||
Material:
|
||||
serializedVersion: 8
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_Name: UI-StretchTrait
|
||||
m_Shader: {fileID: 4800000, guid: 6b5e4f608f0684d10a4673a7e1cee0f3, type: 3}
|
||||
m_ValidKeywords: []
|
||||
m_InvalidKeywords:
|
||||
- _COLORMODE_MULTIPRY
|
||||
m_LightmapFlags: 4
|
||||
m_EnableInstancingVariants: 0
|
||||
m_DoubleSidedGI: 0
|
||||
m_CustomRenderQueue: -1
|
||||
stringTagMap: {}
|
||||
disabledShaderPasses: []
|
||||
m_SavedProperties:
|
||||
serializedVersion: 3
|
||||
m_TexEnvs:
|
||||
- _MainTex:
|
||||
m_Texture: {fileID: 2800000, guid: 7d5844d14c31c4ca88cf5653c09ec1f3, type: 3}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
m_Ints: []
|
||||
m_Floats:
|
||||
- _ColorMask: 15
|
||||
- _ColorMode: 0
|
||||
- _DstBlend: 1
|
||||
- _SrcBlend: 1
|
||||
- _Stencil: 0
|
||||
- _StencilComp: 8
|
||||
- _StencilOp: 0
|
||||
- _StencilReadMask: 255
|
||||
- _StencilWriteMask: 255
|
||||
- _UseUIAlphaClip: 0
|
||||
m_Colors:
|
||||
- _Color: {r: 1, g: 1, b: 1, a: 1}
|
||||
m_BuildTextureStacks: []
|
||||
8
Assets/Demo/CustomView/UI-StretchTrait.mat.meta
Normal file
8
Assets/Demo/CustomView/UI-StretchTrait.mat.meta
Normal file
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: bce3318d54bae4f99a2cb35bd8c456b0
|
||||
NativeFormatImporter:
|
||||
externalObjects: {}
|
||||
mainObjectFileID: 2100000
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
BIN
Assets/Demo/CustomView/UI-StretchTrait.png
Normal file
BIN
Assets/Demo/CustomView/UI-StretchTrait.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 8.5 KiB |
147
Assets/Demo/CustomView/UI-StretchTrait.png.meta
Normal file
147
Assets/Demo/CustomView/UI-StretchTrait.png.meta
Normal file
@@ -0,0 +1,147 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 7d5844d14c31c4ca88cf5653c09ec1f3
|
||||
TextureImporter:
|
||||
internalIDToNameTable: []
|
||||
externalObjects: {}
|
||||
serializedVersion: 12
|
||||
mipmaps:
|
||||
mipMapMode: 0
|
||||
enableMipMap: 0
|
||||
sRGBTexture: 1
|
||||
linearTexture: 0
|
||||
fadeOut: 0
|
||||
borderMipMap: 0
|
||||
mipMapsPreserveCoverage: 0
|
||||
alphaTestReferenceValue: 0.5
|
||||
mipMapFadeDistanceStart: 1
|
||||
mipMapFadeDistanceEnd: 3
|
||||
bumpmap:
|
||||
convertToNormalMap: 0
|
||||
externalNormalMap: 0
|
||||
heightScale: 0.25
|
||||
normalMapFilter: 0
|
||||
isReadable: 0
|
||||
streamingMipmaps: 0
|
||||
streamingMipmapsPriority: 0
|
||||
vTOnly: 0
|
||||
ignoreMasterTextureLimit: 0
|
||||
grayScaleToAlpha: 0
|
||||
generateCubemap: 6
|
||||
cubemapConvolution: 0
|
||||
seamlessCubemap: 0
|
||||
textureFormat: 1
|
||||
maxTextureSize: 2048
|
||||
textureSettings:
|
||||
serializedVersion: 2
|
||||
filterMode: 1
|
||||
aniso: 1
|
||||
mipBias: 0
|
||||
wrapU: 1
|
||||
wrapV: 1
|
||||
wrapW: 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: 2
|
||||
alphaIsTransparency: 1
|
||||
spriteTessellationDetail: -1
|
||||
textureType: 0
|
||||
textureShape: 1
|
||||
singleChannelComponent: 0
|
||||
flipbookRows: 1
|
||||
flipbookColumns: 1
|
||||
maxTextureSizeSet: 0
|
||||
compressionQualitySet: 0
|
||||
textureFormatSet: 0
|
||||
ignorePngGamma: 0
|
||||
applyGammaDecoding: 1
|
||||
cookieLightType: 1
|
||||
platformSettings:
|
||||
- serializedVersion: 3
|
||||
buildTarget: DefaultTexturePlatform
|
||||
maxTextureSize: 64
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
- serializedVersion: 3
|
||||
buildTarget: Standalone
|
||||
maxTextureSize: 64
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
- serializedVersion: 3
|
||||
buildTarget: Android
|
||||
maxTextureSize: 64
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 1
|
||||
- serializedVersion: 3
|
||||
buildTarget: WebGL
|
||||
maxTextureSize: 64
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: 63
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 1
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
- serializedVersion: 3
|
||||
buildTarget: Server
|
||||
maxTextureSize: 64
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
spriteSheet:
|
||||
serializedVersion: 2
|
||||
sprites: []
|
||||
outline: []
|
||||
physicsShape: []
|
||||
bones: []
|
||||
spriteID: 5e97eb03825dee720800000000000000
|
||||
internalID: 0
|
||||
vertices: []
|
||||
indices:
|
||||
edges: []
|
||||
weights: []
|
||||
secondaryTextures: []
|
||||
nameFileIdTable: {}
|
||||
spritePackingTag:
|
||||
pSDRemoveMatte: 0
|
||||
pSDShowRemoveMatteOption: 0
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,3 +1,4 @@
|
||||
using Coffee.UIParticleInternal;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Serialization;
|
||||
|
||||
@@ -46,7 +47,7 @@ namespace Coffee.UIExtensions.Demo
|
||||
|
||||
if (!flag)
|
||||
{
|
||||
foreach (var ps in FindObjectsOfType<ParticleSystem>())
|
||||
foreach (var ps in Misc.FindObjectsOfType<ParticleSystem>())
|
||||
{
|
||||
ps.Play(false);
|
||||
}
|
||||
@@ -75,7 +76,7 @@ namespace Coffee.UIExtensions.Demo
|
||||
|
||||
public void ParticleSystem_SetScale(float scale)
|
||||
{
|
||||
foreach (var ps in FindObjectsOfType<ParticleSystem>())
|
||||
foreach (var ps in Misc.FindObjectsOfType<ParticleSystem>())
|
||||
{
|
||||
ps.transform.localScale = new Vector3(scale, scale, scale);
|
||||
}
|
||||
|
||||
@@ -14,15 +14,15 @@ MonoBehaviour:
|
||||
m_EditorClassIdentifier:
|
||||
m_NanoMonitorEnabled: 1
|
||||
m_BootSceneNameRegex: .*
|
||||
m_DevelopmentBuildOnly: 1
|
||||
m_DevelopmentBuildOnly: 0
|
||||
m_EnabledInEditor: 1
|
||||
m_AlwaysIncludeAssembly: 1
|
||||
m_InstantiateOnLoad: 1
|
||||
m_Prefab: {fileID: 7211429669315726685, guid: b73940fc30a2f4eb9a73783e9c1f8da6,
|
||||
type: 3}
|
||||
m_Opened: 1
|
||||
m_Interval: 0.5
|
||||
m_Anchor: 1
|
||||
m_Anchor: 0
|
||||
m_Width: 750
|
||||
m_CustomMonitorItems:
|
||||
- m_Format: Screen:{0}x{1}
|
||||
m_Arg0:
|
||||
@@ -31,3 +31,10 @@ MonoBehaviour:
|
||||
m_Path: UnityEngine.Screen, UnityEngine.CoreModule;height
|
||||
m_Arg2:
|
||||
m_Path:
|
||||
- m_Format: UIParticles:{0} Materials:{1}
|
||||
m_Arg0:
|
||||
m_Path: Coffee.UIExtensions.UIParticleUpdater, Coffee.UIParticle;uiParticleCount
|
||||
m_Arg1:
|
||||
m_Path: Coffee.UIParticleInternal.MaterialRepository, Coffee.UIParticle;count
|
||||
m_Arg2:
|
||||
m_Path:
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,20 +0,0 @@
|
||||
%YAML 1.1
|
||||
%TAG !u! tag:unity3d.com,2011:
|
||||
--- !u!114 &11400000
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 0}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: 94e8c16a26d334eafa227ee444387432, type: 3}
|
||||
m_Name: SimpleSceneNavigator
|
||||
m_EditorClassIdentifier:
|
||||
m_NavigatorEnabled: 1
|
||||
m_EnabledInEditor: 1
|
||||
m_AlwaysIncludeAssembly: 1
|
||||
m_InstantiateOnLoad: 1
|
||||
m_Prefab: {fileID: 7211429669315726685, guid: 46deb9632f6a14713b8460bd01e879c9,
|
||||
type: 3}
|
||||
@@ -1,513 +0,0 @@
|
||||
%YAML 1.1
|
||||
%TAG !u! tag:unity3d.com,2011:
|
||||
--- !u!1 &3877588430955763108
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
serializedVersion: 6
|
||||
m_Component:
|
||||
- component: {fileID: 3877588430955763111}
|
||||
- component: {fileID: 3877588430955763105}
|
||||
- component: {fileID: 3877588430955763110}
|
||||
m_Layer: 5
|
||||
m_Name: Text
|
||||
m_TagString: Untagged
|
||||
m_Icon: {fileID: 0}
|
||||
m_NavMeshLayer: 0
|
||||
m_StaticEditorFlags: 0
|
||||
m_IsActive: 1
|
||||
--- !u!224 &3877588430955763111
|
||||
RectTransform:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 3877588430955763108}
|
||||
m_LocalRotation: {x: -0, y: -0, z: -0, w: 1}
|
||||
m_LocalPosition: {x: 0, y: 0, z: 0}
|
||||
m_LocalScale: {x: 1, y: 1, z: 1}
|
||||
m_Children: []
|
||||
m_Father: {fileID: 3877588431231610297}
|
||||
m_RootOrder: 0
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||
m_AnchorMin: {x: 0, y: 0}
|
||||
m_AnchorMax: {x: 1, y: 1}
|
||||
m_AnchoredPosition: {x: 0, y: 0}
|
||||
m_SizeDelta: {x: 0, y: 0}
|
||||
m_Pivot: {x: 0.5, y: 0.5}
|
||||
--- !u!222 &3877588430955763105
|
||||
CanvasRenderer:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 3877588430955763108}
|
||||
m_CullTransparentMesh: 0
|
||||
--- !u!114 &3877588430955763110
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 3877588430955763108}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: 5f7201a12d95ffc409449d95f23cf332, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
m_Material: {fileID: 0}
|
||||
m_Color: {r: 0.19607843, g: 0.19607843, b: 0.19607843, a: 1}
|
||||
m_RaycastTarget: 1
|
||||
m_Maskable: 1
|
||||
m_OnCullStateChanged:
|
||||
m_PersistentCalls:
|
||||
m_Calls: []
|
||||
m_FontData:
|
||||
m_Font: {fileID: 10102, guid: 0000000000000000e000000000000000, type: 0}
|
||||
m_FontSize: 14
|
||||
m_FontStyle: 0
|
||||
m_BestFit: 0
|
||||
m_MinSize: 10
|
||||
m_MaxSize: 40
|
||||
m_Alignment: 4
|
||||
m_AlignByGeometry: 0
|
||||
m_RichText: 1
|
||||
m_HorizontalOverflow: 1
|
||||
m_VerticalOverflow: 1
|
||||
m_LineSpacing: 1
|
||||
m_Text: '>>'
|
||||
--- !u!1 &3877588431231610301
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
serializedVersion: 6
|
||||
m_Component:
|
||||
- component: {fileID: 3877588431231610297}
|
||||
- component: {fileID: 3877588431231610302}
|
||||
- component: {fileID: 3877588431231610303}
|
||||
- component: {fileID: 3877588431231610300}
|
||||
m_Layer: 5
|
||||
m_Name: Button - >>
|
||||
m_TagString: Untagged
|
||||
m_Icon: {fileID: 0}
|
||||
m_NavMeshLayer: 0
|
||||
m_StaticEditorFlags: 0
|
||||
m_IsActive: 1
|
||||
--- !u!224 &3877588431231610297
|
||||
RectTransform:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 3877588431231610301}
|
||||
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
|
||||
m_LocalPosition: {x: 0, y: 0, z: 0}
|
||||
m_LocalScale: {x: 1, y: 1, z: 1}
|
||||
m_Children:
|
||||
- {fileID: 3877588430955763111}
|
||||
m_Father: {fileID: 7211429669315725985}
|
||||
m_RootOrder: 1
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||
m_AnchorMin: {x: 1, y: 1}
|
||||
m_AnchorMax: {x: 1, y: 1}
|
||||
m_AnchoredPosition: {x: 0, y: 0}
|
||||
m_SizeDelta: {x: 30, y: 30}
|
||||
m_Pivot: {x: 1, y: 1}
|
||||
--- !u!222 &3877588431231610302
|
||||
CanvasRenderer:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 3877588431231610301}
|
||||
m_CullTransparentMesh: 0
|
||||
--- !u!114 &3877588431231610303
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 3877588431231610301}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
m_Material: {fileID: 0}
|
||||
m_Color: {r: 1, g: 1, b: 1, a: 1}
|
||||
m_RaycastTarget: 1
|
||||
m_Maskable: 1
|
||||
m_OnCullStateChanged:
|
||||
m_PersistentCalls:
|
||||
m_Calls: []
|
||||
m_Sprite: {fileID: 10905, guid: 0000000000000000f000000000000000, type: 0}
|
||||
m_Type: 1
|
||||
m_PreserveAspect: 0
|
||||
m_FillCenter: 1
|
||||
m_FillMethod: 4
|
||||
m_FillAmount: 1
|
||||
m_FillClockwise: 1
|
||||
m_FillOrigin: 0
|
||||
m_UseSpriteMesh: 0
|
||||
m_PixelsPerUnitMultiplier: 1
|
||||
--- !u!114 &3877588431231610300
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 3877588431231610301}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: 4e29b1a8efbd4b44bb3f3716e73f07ff, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
m_Navigation:
|
||||
m_Mode: 3
|
||||
m_SelectOnUp: {fileID: 0}
|
||||
m_SelectOnDown: {fileID: 0}
|
||||
m_SelectOnLeft: {fileID: 0}
|
||||
m_SelectOnRight: {fileID: 0}
|
||||
m_Transition: 1
|
||||
m_Colors:
|
||||
m_NormalColor: {r: 1, g: 1, b: 1, a: 1}
|
||||
m_HighlightedColor: {r: 0.9607843, g: 0.9607843, b: 0.9607843, a: 1}
|
||||
m_PressedColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 1}
|
||||
m_SelectedColor: {r: 0.9607843, g: 0.9607843, b: 0.9607843, a: 1}
|
||||
m_DisabledColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 0.5019608}
|
||||
m_ColorMultiplier: 1
|
||||
m_FadeDuration: 0.1
|
||||
m_SpriteState:
|
||||
m_HighlightedSprite: {fileID: 0}
|
||||
m_PressedSprite: {fileID: 0}
|
||||
m_SelectedSprite: {fileID: 0}
|
||||
m_DisabledSprite: {fileID: 0}
|
||||
m_AnimationTriggers:
|
||||
m_NormalTrigger: Normal
|
||||
m_HighlightedTrigger: Highlighted
|
||||
m_PressedTrigger: Pressed
|
||||
m_SelectedTrigger: Selected
|
||||
m_DisabledTrigger: Disabled
|
||||
m_Interactable: 1
|
||||
m_TargetGraphic: {fileID: 3877588431231610303}
|
||||
m_OnClick:
|
||||
m_PersistentCalls:
|
||||
m_Calls: []
|
||||
--- !u!1 &3877588432219069602
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
serializedVersion: 6
|
||||
m_Component:
|
||||
- component: {fileID: 3877588432219069614}
|
||||
- component: {fileID: 3877588432219069615}
|
||||
- component: {fileID: 3877588432219069612}
|
||||
- component: {fileID: 3877588432219069613}
|
||||
m_Layer: 5
|
||||
m_Name: Button - <<
|
||||
m_TagString: Untagged
|
||||
m_Icon: {fileID: 0}
|
||||
m_NavMeshLayer: 0
|
||||
m_StaticEditorFlags: 0
|
||||
m_IsActive: 1
|
||||
--- !u!224 &3877588432219069614
|
||||
RectTransform:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 3877588432219069602}
|
||||
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
|
||||
m_LocalPosition: {x: 0, y: 0, z: 0}
|
||||
m_LocalScale: {x: 1, y: 1, z: 1}
|
||||
m_Children:
|
||||
- {fileID: 1738594088889562266}
|
||||
m_Father: {fileID: 7211429669315725985}
|
||||
m_RootOrder: 0
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||
m_AnchorMin: {x: 0, y: 1}
|
||||
m_AnchorMax: {x: 0, y: 1}
|
||||
m_AnchoredPosition: {x: 0, y: 0}
|
||||
m_SizeDelta: {x: 30, y: 30}
|
||||
m_Pivot: {x: 0, y: 1}
|
||||
--- !u!222 &3877588432219069615
|
||||
CanvasRenderer:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 3877588432219069602}
|
||||
m_CullTransparentMesh: 0
|
||||
--- !u!114 &3877588432219069612
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 3877588432219069602}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
m_Material: {fileID: 0}
|
||||
m_Color: {r: 1, g: 1, b: 1, a: 1}
|
||||
m_RaycastTarget: 1
|
||||
m_Maskable: 1
|
||||
m_OnCullStateChanged:
|
||||
m_PersistentCalls:
|
||||
m_Calls: []
|
||||
m_Sprite: {fileID: 10905, guid: 0000000000000000f000000000000000, type: 0}
|
||||
m_Type: 1
|
||||
m_PreserveAspect: 0
|
||||
m_FillCenter: 1
|
||||
m_FillMethod: 4
|
||||
m_FillAmount: 1
|
||||
m_FillClockwise: 1
|
||||
m_FillOrigin: 0
|
||||
m_UseSpriteMesh: 0
|
||||
m_PixelsPerUnitMultiplier: 1
|
||||
--- !u!114 &3877588432219069613
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 3877588432219069602}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: 4e29b1a8efbd4b44bb3f3716e73f07ff, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
m_Navigation:
|
||||
m_Mode: 3
|
||||
m_SelectOnUp: {fileID: 0}
|
||||
m_SelectOnDown: {fileID: 0}
|
||||
m_SelectOnLeft: {fileID: 0}
|
||||
m_SelectOnRight: {fileID: 0}
|
||||
m_Transition: 1
|
||||
m_Colors:
|
||||
m_NormalColor: {r: 1, g: 1, b: 1, a: 1}
|
||||
m_HighlightedColor: {r: 0.9607843, g: 0.9607843, b: 0.9607843, a: 1}
|
||||
m_PressedColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 1}
|
||||
m_SelectedColor: {r: 0.9607843, g: 0.9607843, b: 0.9607843, a: 1}
|
||||
m_DisabledColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 0.5019608}
|
||||
m_ColorMultiplier: 1
|
||||
m_FadeDuration: 0.1
|
||||
m_SpriteState:
|
||||
m_HighlightedSprite: {fileID: 0}
|
||||
m_PressedSprite: {fileID: 0}
|
||||
m_SelectedSprite: {fileID: 0}
|
||||
m_DisabledSprite: {fileID: 0}
|
||||
m_AnimationTriggers:
|
||||
m_NormalTrigger: Normal
|
||||
m_HighlightedTrigger: Highlighted
|
||||
m_PressedTrigger: Pressed
|
||||
m_SelectedTrigger: Selected
|
||||
m_DisabledTrigger: Disabled
|
||||
m_Interactable: 1
|
||||
m_TargetGraphic: {fileID: 3877588432219069612}
|
||||
m_OnClick:
|
||||
m_PersistentCalls:
|
||||
m_Calls: []
|
||||
--- !u!1 &7211429669315726685
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
serializedVersion: 6
|
||||
m_Component:
|
||||
- component: {fileID: 7211429669315725985}
|
||||
- component: {fileID: 7211429669315726686}
|
||||
- component: {fileID: 7211429669315726687}
|
||||
- component: {fileID: 7143702096253919615}
|
||||
- component: {fileID: 3330778306119167604}
|
||||
m_Layer: 5
|
||||
m_Name: SimpleSceneNavigator
|
||||
m_TagString: Untagged
|
||||
m_Icon: {fileID: 0}
|
||||
m_NavMeshLayer: 0
|
||||
m_StaticEditorFlags: 0
|
||||
m_IsActive: 1
|
||||
--- !u!224 &7211429669315725985
|
||||
RectTransform:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 7211429669315726685}
|
||||
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
|
||||
m_LocalPosition: {x: 0, y: 0, z: 0}
|
||||
m_LocalScale: {x: 0, y: 0, z: 0}
|
||||
m_Children:
|
||||
- {fileID: 3877588432219069614}
|
||||
- {fileID: 3877588431231610297}
|
||||
m_Father: {fileID: 0}
|
||||
m_RootOrder: 0
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||
m_AnchorMin: {x: 0, y: 0}
|
||||
m_AnchorMax: {x: 0, y: 0}
|
||||
m_AnchoredPosition: {x: 0, y: 0}
|
||||
m_SizeDelta: {x: 0, y: 0}
|
||||
m_Pivot: {x: 0, y: 0}
|
||||
--- !u!223 &7211429669315726686
|
||||
Canvas:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 7211429669315726685}
|
||||
m_Enabled: 1
|
||||
serializedVersion: 3
|
||||
m_RenderMode: 0
|
||||
m_Camera: {fileID: 0}
|
||||
m_PlaneDistance: 100
|
||||
m_PixelPerfect: 0
|
||||
m_ReceivesEvents: 1
|
||||
m_OverrideSorting: 0
|
||||
m_OverridePixelPerfect: 0
|
||||
m_SortingBucketNormalizedSize: 0
|
||||
m_AdditionalShaderChannelsFlag: 0
|
||||
m_SortingLayerID: 0
|
||||
m_SortingOrder: 32000
|
||||
m_TargetDisplay: 0
|
||||
--- !u!114 &7211429669315726687
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 7211429669315726685}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: 0cd44c1031e13a943bb63640046fad76, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
m_UiScaleMode: 1
|
||||
m_ReferencePixelsPerUnit: 100
|
||||
m_ScaleFactor: 1
|
||||
m_ReferenceResolution: {x: 600, y: 40}
|
||||
m_ScreenMatchMode: 0
|
||||
m_MatchWidthOrHeight: 0
|
||||
m_PhysicalUnit: 3
|
||||
m_FallbackScreenDPI: 96
|
||||
m_DefaultSpriteDPI: 96
|
||||
m_DynamicPixelsPerUnit: 1
|
||||
--- !u!114 &7143702096253919615
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 7211429669315726685}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: dc42784cf147c0c48a680349fa168899, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
m_IgnoreReversedGraphics: 1
|
||||
m_BlockingObjects: 0
|
||||
m_BlockingMask:
|
||||
serializedVersion: 2
|
||||
m_Bits: 4294967295
|
||||
--- !u!114 &3330778306119167604
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 7211429669315726685}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: e7db36469bd2a46658ff432d65cb62ca, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
m_PrevButton: {fileID: 3877588432219069613}
|
||||
m_NextButton: {fileID: 3877588431231610300}
|
||||
m_PrevName: {fileID: 0}
|
||||
m_NextName: {fileID: 0}
|
||||
--- !u!1 &8570858711609111474
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
serializedVersion: 6
|
||||
m_Component:
|
||||
- component: {fileID: 1738594088889562266}
|
||||
- component: {fileID: 5485386222362727379}
|
||||
- component: {fileID: 3877588430751452752}
|
||||
m_Layer: 5
|
||||
m_Name: Text
|
||||
m_TagString: Untagged
|
||||
m_Icon: {fileID: 0}
|
||||
m_NavMeshLayer: 0
|
||||
m_StaticEditorFlags: 0
|
||||
m_IsActive: 1
|
||||
--- !u!224 &1738594088889562266
|
||||
RectTransform:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 8570858711609111474}
|
||||
m_LocalRotation: {x: -0, y: -0, z: -0, w: 1}
|
||||
m_LocalPosition: {x: 0, y: 0, z: 0}
|
||||
m_LocalScale: {x: 1, y: 1, z: 1}
|
||||
m_Children: []
|
||||
m_Father: {fileID: 3877588432219069614}
|
||||
m_RootOrder: 0
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||
m_AnchorMin: {x: 0, y: 0}
|
||||
m_AnchorMax: {x: 1, y: 1}
|
||||
m_AnchoredPosition: {x: 0, y: 0}
|
||||
m_SizeDelta: {x: 0, y: 0}
|
||||
m_Pivot: {x: 0.5, y: 0.5}
|
||||
--- !u!222 &5485386222362727379
|
||||
CanvasRenderer:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 8570858711609111474}
|
||||
m_CullTransparentMesh: 0
|
||||
--- !u!114 &3877588430751452752
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 8570858711609111474}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: 5f7201a12d95ffc409449d95f23cf332, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
m_Material: {fileID: 0}
|
||||
m_Color: {r: 0.19607843, g: 0.19607843, b: 0.19607843, a: 1}
|
||||
m_RaycastTarget: 1
|
||||
m_Maskable: 1
|
||||
m_OnCullStateChanged:
|
||||
m_PersistentCalls:
|
||||
m_Calls: []
|
||||
m_FontData:
|
||||
m_Font: {fileID: 10102, guid: 0000000000000000e000000000000000, type: 0}
|
||||
m_FontSize: 14
|
||||
m_FontStyle: 0
|
||||
m_BestFit: 0
|
||||
m_MinSize: 10
|
||||
m_MaxSize: 40
|
||||
m_Alignment: 4
|
||||
m_AlignByGeometry: 0
|
||||
m_RichText: 1
|
||||
m_HorizontalOverflow: 1
|
||||
m_VerticalOverflow: 1
|
||||
m_LineSpacing: 1
|
||||
m_Text: <<
|
||||
16
Assets/ProjectSettings/UIParticle.asset
Normal file
16
Assets/ProjectSettings/UIParticle.asset
Normal file
@@ -0,0 +1,16 @@
|
||||
%YAML 1.1
|
||||
%TAG !u! tag:unity3d.com,2011:
|
||||
--- !u!114 &11400000
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 0}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: f22a23b9d98e440478697f4adf30e61c, type: 3}
|
||||
m_Name: UIParticle
|
||||
m_EditorClassIdentifier:
|
||||
m_EnableLinearToGamma: 1
|
||||
m_HideGeneratedObjects: 1
|
||||
@@ -1,5 +1,5 @@
|
||||
fileFormatVersion: 2
|
||||
guid: be3e05903ef7041d39b3ef8ecdd47f08
|
||||
guid: 4b9df7b8a4193489299b8f477348ae0c
|
||||
NativeFormatImporter:
|
||||
externalObjects: {}
|
||||
mainObjectFileID: 11400000
|
||||
@@ -1,6 +1,9 @@
|
||||
{
|
||||
"dependencies": {
|
||||
"com.unity.ide.rider": "3.0.27",
|
||||
"com.coffee.development": "https://github.com/mob-sakai/Coffee.Internal.git?path=Packages/Development",
|
||||
"com.coffee.minimal-resource": "https://github.com/mob-sakai/Coffee.Internal.git?path=Packages/MinimalResource",
|
||||
"com.coffee.nano-monitor": "https://github.com/mob-sakai/Coffee.Internal.git?path=Packages/NanoMonitor",
|
||||
"com.unity.ide.rider": "3.0.31",
|
||||
"com.unity.test-framework": "1.1.33",
|
||||
"com.unity.modules.animation": "1.0.0",
|
||||
"com.unity.modules.physics": "1.0.0"
|
||||
|
||||
@@ -1,5 +1,28 @@
|
||||
{
|
||||
"dependencies": {
|
||||
"com.coffee.development": {
|
||||
"version": "https://github.com/mob-sakai/Coffee.Internal.git?path=Packages/Development",
|
||||
"depth": 0,
|
||||
"source": "git",
|
||||
"dependencies": {},
|
||||
"hash": "52987fb6e66e7fc48498d8d164c3c8808de4de6b"
|
||||
},
|
||||
"com.coffee.minimal-resource": {
|
||||
"version": "https://github.com/mob-sakai/Coffee.Internal.git?path=Packages/MinimalResource",
|
||||
"depth": 0,
|
||||
"source": "git",
|
||||
"dependencies": {},
|
||||
"hash": "52987fb6e66e7fc48498d8d164c3c8808de4de6b"
|
||||
},
|
||||
"com.coffee.nano-monitor": {
|
||||
"version": "https://github.com/mob-sakai/Coffee.Internal.git?path=Packages/NanoMonitor",
|
||||
"depth": 0,
|
||||
"source": "git",
|
||||
"dependencies": {
|
||||
"com.unity.ugui": "1.0.0"
|
||||
},
|
||||
"hash": "52987fb6e66e7fc48498d8d164c3c8808de4de6b"
|
||||
},
|
||||
"com.coffee.ui-particle": {
|
||||
"version": "file:src",
|
||||
"depth": 0,
|
||||
@@ -17,7 +40,7 @@
|
||||
"url": "https://packages.unity.com"
|
||||
},
|
||||
"com.unity.ide.rider": {
|
||||
"version": "3.0.27",
|
||||
"version": "3.0.31",
|
||||
"depth": 0,
|
||||
"source": "registry",
|
||||
"dependencies": {
|
||||
|
||||
1
Packages/src/.coffee.internal.sed
Normal file
1
Packages/src/.coffee.internal.sed
Normal file
@@ -0,0 +1 @@
|
||||
s/Coffee.Internal/Coffee.UIParticleInternal/g
|
||||
@@ -4,7 +4,7 @@
|
||||
"release-4.x",
|
||||
{
|
||||
"name": "release-preview",
|
||||
"prerelease": true
|
||||
"prerelease": "preview"
|
||||
}
|
||||
],
|
||||
"plugins": [
|
||||
|
||||
@@ -1,3 +1,94 @@
|
||||
## [4.10.5](https://github.com/mob-sakai/ParticleEffectForUGUI/compare/v4.10.4...v4.10.5) (2024-12-23)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* '3D' scale toggle in the inspector does not keep on reload ([934f4b8](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/934f4b8f1c61f8ff20228d0ebcea9f636a3758ed)), closes [#346](https://github.com/mob-sakai/ParticleEffectForUGUI/issues/346)
|
||||
|
||||
## [4.10.4](https://github.com/mob-sakai/ParticleEffectForUGUI/compare/v4.10.3...v4.10.4) (2024-12-19)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* rendering issues when playing with opening a prefab stage ([95235a9](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/95235a929b82cf681365ed6eba837d857f83e3d2)), closes [#345](https://github.com/mob-sakai/ParticleEffectForUGUI/issues/345)
|
||||
|
||||
## [4.10.3](https://github.com/mob-sakai/ParticleEffectForUGUI/compare/v4.10.2...v4.10.3) (2024-11-20)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* if not configured as a preloaded asset, the project settings asset will be regenerated ([abe0948](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/abe09485f65dd4efd18e74675e752e0213bdf3be)), closes [#342](https://github.com/mob-sakai/ParticleEffectForUGUI/issues/342)
|
||||
|
||||
## [4.10.2](https://github.com/mob-sakai/ParticleEffectForUGUI/compare/v4.10.1...v4.10.2) (2024-11-01)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* trail incorrect offset ([afe00a1](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/afe00a1dde80eb1c0a7bb668b75f4c3733d3fa43)), closes [#335](https://github.com/mob-sakai/ParticleEffectForUGUI/issues/335)
|
||||
|
||||
## [4.10.1](https://github.com/mob-sakai/ParticleEffectForUGUI/compare/v4.10.0...v4.10.1) (2024-09-29)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* mainTex will be ignored ([2ee69d0](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/2ee69d04245fabce185f67dc9bd68c870e556564))
|
||||
|
||||
# [4.10.0](https://github.com/mob-sakai/ParticleEffectForUGUI/compare/v4.9.1...v4.10.0) (2024-09-29)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* component icon is not set ([5ff6ec8](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/5ff6ec815a174de5d3f16d424f1204c60912a8d8))
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* add project settings ([1ce4e31](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/1ce4e31a9681bf1a201d2723c8d97e07ecc16592))
|
||||
|
||||
## [4.9.1](https://github.com/mob-sakai/ParticleEffectForUGUI/compare/v4.9.0...v4.9.1) (2024-08-07)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* ParticleSystem trails gain offset on parent canvas change ([2a1cd50](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/2a1cd502b452b5b56edf8bcfe91adf99d1bb5147)), closes [#323](https://github.com/mob-sakai/ParticleEffectForUGUI/issues/323)
|
||||
|
||||
# [4.9.0](https://github.com/mob-sakai/ParticleEffectForUGUI/compare/v4.8.1...v4.9.0) (2024-07-18)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* ParticleAttractor supports multiple ParticleSystems ([3834780](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/3834780fdb43443fe6e1ef89df54d26a24d62a91))
|
||||
|
||||
## [4.8.1](https://github.com/mob-sakai/ParticleEffectForUGUI/compare/v4.8.0...v4.8.1) (2024-06-27)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* remove debug code ([669deb4](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/669deb41d4ac589d9db93b29bc8e95383e7f28a5))
|
||||
|
||||
# [4.8.0](https://github.com/mob-sakai/ParticleEffectForUGUI/compare/v4.7.2...v4.8.0) (2024-06-27)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* generated baking-camera object remains in the prefab or scene (again) ([de35cba](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/de35cba34c6312c1405ed522e9927c620c78e72d))
|
||||
* SetParticleSystemInstance/Prefab APIs destroy generated objects ([ae3f3a8](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/ae3f3a8e62cc733420354d237ab765ac777127c8))
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* add 'custom view' option. ([a703c29](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/a703c2921ca08c2280d0c8fde01e4c0b33b5c69e))
|
||||
* remove overlay window (editor) ([8358170](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/835817049f4fcf00dd2bf98dbada14f041ad3544))
|
||||
* restore `Transform.localScale` when setting `autoScalingMode` to something other than `Transform` (again) ([88a970d](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/88a970d93a2b69cf011d86bd1807569e90538e0e))
|
||||
* the rendering order list in inspector is now more compact ([be90172](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/be901724e064befacf617f4940b0331e1d31e1ca))
|
||||
|
||||
## [4.7.2](https://github.com/mob-sakai/ParticleEffectForUGUI/compare/v4.7.1...v4.7.2) (2024-06-21)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* generated baking-camera object remains in the prefab or scene ([0bb8438](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/0bb843830197d8c1252232928becc211c0ada08d))
|
||||
|
||||
## [4.7.1](https://github.com/mob-sakai/ParticleEffectForUGUI/compare/v4.7.0...v4.7.1) (2024-06-20)
|
||||
|
||||
|
||||
|
||||
@@ -31,35 +31,35 @@ namespace Coffee.UIExtensions
|
||||
}
|
||||
else
|
||||
{
|
||||
result.Aggregate(s_Sb, (a, b) => s_Sb.AppendFormat("{0}, ", b));
|
||||
result.Aggregate(s_Sb, (a, b) =>
|
||||
{
|
||||
s_Sb.Append(b);
|
||||
return s_Sb.Append(", ");
|
||||
});
|
||||
s_Sb.Length -= 2;
|
||||
}
|
||||
|
||||
return s_Sb.ToString();
|
||||
}
|
||||
|
||||
public static void Draw(SerializedProperty sp, Material[] mats)
|
||||
public static void Draw(SerializedProperty sp, List<Material> mats)
|
||||
{
|
||||
bool isClicked;
|
||||
using (new EditorGUILayout.HorizontalScope(GUILayout.ExpandWidth(false)))
|
||||
{
|
||||
var pos = EditorGUILayout.GetControlRect(true);
|
||||
var label = new GUIContent(sp.displayName, sp.tooltip);
|
||||
var rect = EditorGUI.PrefixLabel(pos, label);
|
||||
var text = sp.hasMultipleDifferentValues
|
||||
? "-"
|
||||
: CollectActiveNames(sp, s_ActiveNames);
|
||||
isClicked = GUI.Button(rect, text, EditorStyles.popup);
|
||||
}
|
||||
var pos = EditorGUILayout.GetControlRect(true);
|
||||
var label = new GUIContent(sp.displayName, sp.tooltip);
|
||||
var rect = EditorGUI.PrefixLabel(pos, label);
|
||||
var text = sp.hasMultipleDifferentValues
|
||||
? "-"
|
||||
: CollectActiveNames(sp, s_ActiveNames);
|
||||
|
||||
if (!isClicked) return;
|
||||
if (!GUI.Button(rect, text, EditorStyles.popup)) return;
|
||||
|
||||
var gm = new GenericMenu();
|
||||
gm.AddItem(s_ContentNothing, s_ActiveNames.Count == 0, () =>
|
||||
gm.AddItem(s_ContentNothing, s_ActiveNames.Count == 0, x =>
|
||||
{
|
||||
sp.ClearArray();
|
||||
sp.serializedObject.ApplyModifiedProperties();
|
||||
});
|
||||
var current = (SerializedProperty)x;
|
||||
current.ClearArray();
|
||||
current.serializedObject.ApplyModifiedProperties();
|
||||
}, sp);
|
||||
|
||||
if (!sp.hasMultipleDifferentValues)
|
||||
{
|
||||
@@ -73,7 +73,7 @@ namespace Coffee.UIExtensions
|
||||
}
|
||||
|
||||
s_Names.Clear();
|
||||
for (var j = 0; j < mats.Length; j++)
|
||||
for (var j = 0; j < mats.Count; j++)
|
||||
{
|
||||
var mat = mats[j];
|
||||
if (!mat || !mat.shader) continue;
|
||||
@@ -82,8 +82,7 @@ namespace Coffee.UIExtensions
|
||||
{
|
||||
var name = ShaderUtil.GetPropertyName(mat.shader, i);
|
||||
var type = (AnimatableProperty.ShaderPropertyType)ShaderUtil.GetPropertyType(mat.shader, i);
|
||||
if (s_Names.Contains(name)) continue;
|
||||
s_Names.Add(name);
|
||||
if (!s_Names.Add(name)) continue;
|
||||
|
||||
AddMenu(gm, sp, new ShaderProperty(name, type), true);
|
||||
|
||||
|
||||
@@ -5,8 +5,9 @@ using UnityEditor;
|
||||
using UnityEditor.UI;
|
||||
using UnityEditorInternal;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Profiling;
|
||||
using UnityEngine.UI;
|
||||
using Coffee.UIParticleExtensions;
|
||||
using Coffee.UIParticleInternal;
|
||||
#if UNITY_2021_2_OR_NEWER
|
||||
using UnityEditor.Overlays;
|
||||
#else
|
||||
@@ -16,6 +17,7 @@ using Object = UnityEngine.Object;
|
||||
#endif
|
||||
#if UNITY_2021_2_OR_NEWER
|
||||
using UnityEditor.SceneManagement;
|
||||
|
||||
#elif UNITY_2018_3_OR_NEWER
|
||||
using UnityEditor.Experimental.SceneManagement;
|
||||
#endif
|
||||
@@ -26,42 +28,29 @@ namespace Coffee.UIExtensions
|
||||
[CanEditMultipleObjects]
|
||||
internal class UIParticleEditor : GraphicEditor
|
||||
{
|
||||
#if UNITY_2021_2_OR_NEWER
|
||||
#if UNITY_2022_1_OR_NEWER
|
||||
[Overlay(typeof(SceneView), "Scene View/UI Particles", "UI Particles", true,
|
||||
defaultDockPosition = DockPosition.Bottom,
|
||||
defaultDockZone = DockZone.Floating,
|
||||
defaultLayout = Layout.Panel)]
|
||||
#else
|
||||
[Overlay(typeof(SceneView), "Scene View/UI Particles", "UI Particles", true)]
|
||||
#endif
|
||||
private class UIParticleOverlay : IMGUIOverlay, ITransientOverlay
|
||||
internal class State : ScriptableSingleton<State>
|
||||
{
|
||||
public bool visible => s_SerializedObject != null;
|
||||
|
||||
public override void OnGUI()
|
||||
{
|
||||
if (visible)
|
||||
{
|
||||
WindowFunction();
|
||||
}
|
||||
}
|
||||
public bool is3DScaleMode;
|
||||
}
|
||||
#endif
|
||||
|
||||
//################################
|
||||
// Constant or Static Members.
|
||||
//################################
|
||||
private static readonly GUIContent[] s_ContentMaterials = new[]
|
||||
{
|
||||
new GUIContent("Material"),
|
||||
new GUIContent("Trail Material")
|
||||
};
|
||||
|
||||
private static readonly GUIContent s_ContentRenderingOrder = new GUIContent("Rendering Order");
|
||||
private static readonly GUIContent s_ContentRefresh = new GUIContent("Refresh");
|
||||
private static readonly GUIContent s_ContentFix = new GUIContent("Fix");
|
||||
private static readonly GUIContent s_ContentMaterial = new GUIContent("Material");
|
||||
private static readonly GUIContent s_ContentTrailMaterial = new GUIContent("Trail Material");
|
||||
private static readonly GUIContent s_Content3D = new GUIContent("3D");
|
||||
private static readonly GUIContent s_ContentRandom = new GUIContent("Random");
|
||||
private static readonly GUIContent s_ContentScale = new GUIContent("Scale");
|
||||
private static SerializedObject s_SerializedObject;
|
||||
private static bool s_XYZMode;
|
||||
private static readonly GUIContent s_ContentPrimary = new GUIContent("Primary");
|
||||
private static readonly Regex s_RegexBuiltInGuid = new Regex(@"^0{16}.0{15}$", RegexOptions.Compiled);
|
||||
private static readonly List<Material> s_TempMaterials = new List<Material>();
|
||||
|
||||
private SerializedProperty _maskable;
|
||||
private SerializedProperty _scale3D;
|
||||
@@ -71,8 +60,11 @@ namespace Coffee.UIExtensions
|
||||
private SerializedProperty _groupMaxId;
|
||||
private SerializedProperty _positionMode;
|
||||
private SerializedProperty _autoScalingMode;
|
||||
private SerializedProperty _useCustomView;
|
||||
private SerializedProperty _customViewSize;
|
||||
private ReorderableList _ro;
|
||||
private bool _showMax;
|
||||
private bool _is3DScaleMode;
|
||||
|
||||
private static readonly HashSet<Shader> s_Shaders = new HashSet<Shader>();
|
||||
#if UNITY_2018 || UNITY_2019
|
||||
@@ -88,56 +80,6 @@ namespace Coffee.UIExtensions
|
||||
"_ColorMask"
|
||||
};
|
||||
|
||||
[InitializeOnLoadMethod]
|
||||
private static void Init()
|
||||
{
|
||||
#if !UNITY_2021_2_OR_NEWER
|
||||
var miSceneViewOverlayWindow = Type.GetType("UnityEditor.SceneViewOverlay, UnityEditor")
|
||||
?.GetMethods(BindingFlags.Public | BindingFlags.Static)
|
||||
.First(x => x.Name == "Window" && 5 <= x.GetParameters().Length);
|
||||
var windowFunction = (Action<Object, SceneView>)WindowFunction;
|
||||
var windowFunctionType = Type.GetType("UnityEditor.SceneViewOverlay+WindowFunction, UnityEditor");
|
||||
var windowFunctionDelegate = Delegate.CreateDelegate(windowFunctionType, windowFunction.Method);
|
||||
var windowTitle = new GUIContent(ObjectNames.NicifyVariableName(nameof(UIParticle)));
|
||||
#if UNITY_2019_2_OR_NEWER
|
||||
//public static void Window(GUIContent title, WindowFunction sceneViewFunc, int order, Object target, WindowDisplayOption option, EditorWindow window = null)
|
||||
var sceneViewArgs = new object[] { windowTitle, windowFunctionDelegate, 599, null, 2, null };
|
||||
#else
|
||||
//public static void Window(GUIContent title, WindowFunction sceneViewFunc, int order, Object target, WindowDisplayOption option)
|
||||
var sceneViewArgs = new object[] { windowTitle, windowFunctionDelegate, 599, null, 2 };
|
||||
#endif
|
||||
|
||||
#if UNITY_2019_1_OR_NEWER
|
||||
SceneView.duringSceneGui += _ =>
|
||||
#else
|
||||
SceneView.onSceneGUIDelegate += _ =>
|
||||
#endif
|
||||
{
|
||||
if (s_SerializedObject != null)
|
||||
{
|
||||
miSceneViewOverlayWindow.Invoke(null, sceneViewArgs);
|
||||
}
|
||||
};
|
||||
#endif
|
||||
|
||||
SerializedObject CreateSerializeObject()
|
||||
{
|
||||
var uiParticles = Selection.gameObjects.Select(x => x.GetComponent<ParticleSystem>())
|
||||
.Where(x => x)
|
||||
.Select(x => x.GetComponentInParent<UIParticle>(true))
|
||||
.Where(x => x && x.canvas)
|
||||
.Concat(Selection.gameObjects.Select(x => x.GetComponent<UIParticle>())
|
||||
.Where(x => x && x.canvas))
|
||||
.Distinct()
|
||||
.OfType<Object>()
|
||||
.ToArray();
|
||||
return 0 < uiParticles.Length ? new SerializedObject(uiParticles) : null;
|
||||
}
|
||||
|
||||
s_SerializedObject = CreateSerializeObject();
|
||||
Selection.selectionChanged += () => s_SerializedObject = CreateSerializeObject();
|
||||
}
|
||||
|
||||
//################################
|
||||
// Public/Protected Members.
|
||||
//################################
|
||||
@@ -156,31 +98,43 @@ namespace Coffee.UIExtensions
|
||||
_groupMaxId = serializedObject.FindProperty("m_GroupMaxId");
|
||||
_positionMode = serializedObject.FindProperty("m_PositionMode");
|
||||
_autoScalingMode = serializedObject.FindProperty("m_AutoScalingMode");
|
||||
_useCustomView = serializedObject.FindProperty("m_UseCustomView");
|
||||
_customViewSize = serializedObject.FindProperty("m_CustomViewSize");
|
||||
|
||||
var sp = serializedObject.FindProperty("m_Particles");
|
||||
_ro = new ReorderableList(sp.serializedObject, sp, true, true, true, true)
|
||||
{
|
||||
elementHeight = EditorGUIUtility.singleLineHeight * 3 + 4,
|
||||
elementHeightCallback = _ => 3 * (EditorGUIUtility.singleLineHeight + 2),
|
||||
elementHeightCallback = index =>
|
||||
{
|
||||
var ps = sp.GetArrayElementAtIndex(index).objectReferenceValue as ParticleSystem;
|
||||
var materialCount = 0;
|
||||
if (ps && ps.TryGetComponent<ParticleSystemRenderer>(out var psr))
|
||||
{
|
||||
materialCount = psr.sharedMaterials.Length;
|
||||
}
|
||||
|
||||
return (materialCount + 1) * (EditorGUIUtility.singleLineHeight + 2);
|
||||
},
|
||||
drawElementCallback = (rect, index, _, __) =>
|
||||
{
|
||||
EditorGUI.BeginDisabledGroup(sp.hasMultipleDifferentValues);
|
||||
rect.y += 1;
|
||||
rect.y += 2;
|
||||
rect.height = EditorGUIUtility.singleLineHeight;
|
||||
var p = sp.GetArrayElementAtIndex(index);
|
||||
EditorGUI.ObjectField(rect, p, GUIContent.none);
|
||||
var ps = p.objectReferenceValue as ParticleSystem;
|
||||
if (!ps || !ps.TryGetComponent<ParticleSystemRenderer>(out var psr)) return;
|
||||
|
||||
rect.x += 15;
|
||||
rect.width -= 15;
|
||||
var ps = p.objectReferenceValue as ParticleSystem;
|
||||
var materials = ps
|
||||
? new SerializedObject(ps.GetComponent<ParticleSystemRenderer>()).FindProperty("m_Materials")
|
||||
: null;
|
||||
rect.y += rect.height + 1;
|
||||
MaterialField(rect, s_ContentMaterial, materials, 0);
|
||||
rect.y += rect.height + 1;
|
||||
MaterialField(rect, s_ContentTrailMaterial, materials, 1);
|
||||
EditorGUI.EndDisabledGroup();
|
||||
if (materials != null && materials.serializedObject.hasModifiedProperties)
|
||||
var materials = new SerializedObject(psr).FindProperty("m_Materials");
|
||||
var count = Mathf.Min(materials.arraySize, 2);
|
||||
for (var i = 0; i < count; i++)
|
||||
{
|
||||
rect.y += rect.height + 2;
|
||||
EditorGUI.PropertyField(rect, materials.GetArrayElementAtIndex(i), s_ContentMaterials[i]);
|
||||
}
|
||||
|
||||
if (materials.serializedObject.hasModifiedProperties)
|
||||
{
|
||||
materials.serializedObject.ApplyModifiedProperties();
|
||||
}
|
||||
@@ -214,19 +168,18 @@ namespace Coffee.UIExtensions
|
||||
uip.RefreshParticles(uip.particles);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void MaterialField(Rect rect, GUIContent label, SerializedProperty sp, int index)
|
||||
{
|
||||
if (sp == null || sp.arraySize <= index)
|
||||
// Initialize 3D scale mode.
|
||||
_is3DScaleMode = State.instance.is3DScaleMode;
|
||||
if (!_is3DScaleMode)
|
||||
{
|
||||
EditorGUI.BeginDisabledGroup(true);
|
||||
EditorGUI.ObjectField(rect, label, null, typeof(Material), true);
|
||||
EditorGUI.EndDisabledGroup();
|
||||
}
|
||||
else
|
||||
{
|
||||
EditorGUI.PropertyField(rect, sp.GetArrayElementAtIndex(index), label);
|
||||
var x = _scale3D.FindPropertyRelative("x");
|
||||
var y = _scale3D.FindPropertyRelative("y");
|
||||
var z = _scale3D.FindPropertyRelative("z");
|
||||
_is3DScaleMode = !Mathf.Approximately(x.floatValue, y.floatValue) ||
|
||||
!Mathf.Approximately(y.floatValue, z.floatValue) ||
|
||||
y.hasMultipleDifferentValues ||
|
||||
z.hasMultipleDifferentValues;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -238,6 +191,7 @@ namespace Coffee.UIExtensions
|
||||
var current = target as UIParticle;
|
||||
if (!current) return;
|
||||
|
||||
Profiler.BeginSample("(UIP:E) OnInspectorGUI");
|
||||
serializedObject.Update();
|
||||
|
||||
// Maskable
|
||||
@@ -245,17 +199,16 @@ namespace Coffee.UIExtensions
|
||||
|
||||
// Scale
|
||||
EditorGUI.BeginDisabledGroup(!_meshSharing.hasMultipleDifferentValues && _meshSharing.intValue == 4);
|
||||
s_XYZMode = DrawFloatOrVector3Field(_scale3D, s_XYZMode);
|
||||
if (DrawFloatOrVector3Field(_scale3D, _is3DScaleMode) != _is3DScaleMode)
|
||||
{
|
||||
State.instance.is3DScaleMode = _is3DScaleMode = !_is3DScaleMode;
|
||||
}
|
||||
|
||||
EditorGUI.EndDisabledGroup();
|
||||
|
||||
// AnimatableProperties
|
||||
var mats = current.particles
|
||||
.Where(x => x)
|
||||
.Select(x => x.GetComponent<ParticleSystemRenderer>().sharedMaterial)
|
||||
.Where(x => x)
|
||||
.ToArray();
|
||||
|
||||
AnimatablePropertyEditor.Draw(_animatableProperties, mats);
|
||||
current.GetMaterials(s_TempMaterials);
|
||||
AnimatablePropertyEditor.Draw(_animatableProperties, s_TempMaterials);
|
||||
|
||||
// Mesh sharing
|
||||
EditorGUI.BeginChangeCheck();
|
||||
@@ -263,9 +216,12 @@ namespace Coffee.UIExtensions
|
||||
if (EditorGUI.EndChangeCheck())
|
||||
{
|
||||
serializedObject.ApplyModifiedProperties();
|
||||
foreach (var uip in targets.OfType<UIParticle>())
|
||||
foreach (var t in targets)
|
||||
{
|
||||
uip.ResetGroupId();
|
||||
if (t is UIParticle uip)
|
||||
{
|
||||
uip.ResetGroupId();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -273,16 +229,29 @@ namespace Coffee.UIExtensions
|
||||
EditorGUILayout.PropertyField(_positionMode);
|
||||
|
||||
// Auto Scaling
|
||||
DrawAutoScaling(_autoScalingMode, targets.OfType<UIParticle>());
|
||||
EditorGUILayout.PropertyField(_autoScalingMode);
|
||||
|
||||
// Custom View Size
|
||||
EditorGUILayout.PropertyField(_useCustomView);
|
||||
EditorGUI.BeginChangeCheck();
|
||||
EditorGUI.BeginDisabledGroup(!_useCustomView.boolValue);
|
||||
EditorGUI.indentLevel++;
|
||||
EditorGUILayout.PropertyField(_customViewSize);
|
||||
EditorGUI.indentLevel--;
|
||||
EditorGUI.EndDisabledGroup();
|
||||
if (EditorGUI.EndChangeCheck())
|
||||
{
|
||||
_customViewSize.floatValue = Mathf.Max(0.1f, _customViewSize.floatValue);
|
||||
}
|
||||
|
||||
// Target ParticleSystems.
|
||||
EditorGUI.BeginChangeCheck();
|
||||
EditorGUI.BeginDisabledGroup(targets.OfType<UIParticle>().Any(x => !x.canvas));
|
||||
_ro.DoLayoutList();
|
||||
EditorGUI.EndDisabledGroup();
|
||||
serializedObject.ApplyModifiedProperties();
|
||||
|
||||
if (EditorGUI.EndChangeCheck())
|
||||
{
|
||||
EditorApplication.QueuePlayerLoopUpdate();
|
||||
foreach (var uip in targets.OfType<UIParticle>())
|
||||
{
|
||||
uip.RefreshParticles(uip.particles);
|
||||
@@ -290,7 +259,8 @@ namespace Coffee.UIExtensions
|
||||
}
|
||||
|
||||
// Non-UI built-in shader is not supported.
|
||||
foreach (var mat in current.materials)
|
||||
Profiler.BeginSample("(UIP:E) Non-UI built-in shader is not supported.");
|
||||
foreach (var mat in s_TempMaterials)
|
||||
{
|
||||
if (!mat || !mat.shader) continue;
|
||||
var shader = mat.shader;
|
||||
@@ -303,15 +273,18 @@ namespace Coffee.UIExtensions
|
||||
}
|
||||
}
|
||||
|
||||
Profiler.EndSample();
|
||||
|
||||
// Does the shader support UI masks?
|
||||
Profiler.BeginSample("(UIP:E) Does the shader support UI masks?");
|
||||
if (current.maskable && current.GetComponentInParent<Mask>(false))
|
||||
{
|
||||
foreach (var mat in current.materials)
|
||||
foreach (var mat in s_TempMaterials)
|
||||
{
|
||||
if (!mat || !mat.shader) continue;
|
||||
var shader = mat.shader;
|
||||
if (s_Shaders.Contains(shader)) continue;
|
||||
s_Shaders.Add(shader);
|
||||
if (!s_Shaders.Add(shader)) continue;
|
||||
|
||||
foreach (var propName in s_MaskablePropertyNames)
|
||||
{
|
||||
if (mat.HasProperty(propName)) continue;
|
||||
@@ -325,7 +298,9 @@ namespace Coffee.UIExtensions
|
||||
}
|
||||
}
|
||||
|
||||
s_TempMaterials.Clear();
|
||||
s_Shaders.Clear();
|
||||
Profiler.EndSample();
|
||||
|
||||
// UIParticle for trail should be removed.
|
||||
var label = "This UIParticle component should be removed. The UIParticle for trails is no longer needed.";
|
||||
@@ -364,12 +339,14 @@ namespace Coffee.UIExtensions
|
||||
}
|
||||
}
|
||||
#endif
|
||||
Profiler.EndSample();
|
||||
}
|
||||
|
||||
private bool IsBuiltInObject(Object obj)
|
||||
private static bool IsBuiltInObject(Object obj)
|
||||
{
|
||||
return AssetDatabase.TryGetGUIDAndLocalFileIdentifier(obj, out var guid, out long _)
|
||||
&& Regex.IsMatch(guid, "^0{16}.0{15}$", RegexOptions.Compiled);
|
||||
return AssetDatabase.IsMainAsset(obj)
|
||||
&& AssetDatabase.TryGetGUIDAndLocalFileIdentifier(obj, out var guid, out long _)
|
||||
&& s_RegexBuiltInGuid.IsMatch(guid);
|
||||
}
|
||||
|
||||
#if UNITY_2018 || UNITY_2019
|
||||
@@ -463,7 +440,7 @@ namespace Coffee.UIExtensions
|
||||
{
|
||||
EditorGUI.BeginDisabledGroup(true);
|
||||
var obj = UIParticleUpdater.GetPrimary(spGroupId.intValue);
|
||||
EditorGUILayout.ObjectField("Primary", obj, typeof(UIParticle), false);
|
||||
EditorGUILayout.ObjectField(s_ContentPrimary, obj, typeof(UIParticle), false);
|
||||
EditorGUI.EndDisabledGroup();
|
||||
}
|
||||
|
||||
@@ -473,43 +450,11 @@ namespace Coffee.UIExtensions
|
||||
return showMax;
|
||||
}
|
||||
|
||||
private static void DrawAutoScaling(SerializedProperty prop, IEnumerable<UIParticle> uiParticles)
|
||||
private static void DrawAutoScaling(SerializedProperty prop)
|
||||
{
|
||||
EditorGUILayout.PropertyField(prop);
|
||||
}
|
||||
|
||||
#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>().ToArray();
|
||||
if (uiParticles.Any(x => !x || !x.canvas)) return;
|
||||
|
||||
s_SerializedObject.Update();
|
||||
using (new EditorGUILayout.VerticalScope(GUILayout.Width(220f)))
|
||||
{
|
||||
var labelWidth = EditorGUIUtility.labelWidth;
|
||||
EditorGUIUtility.labelWidth = 100;
|
||||
EditorGUILayout.PropertyField(s_SerializedObject.FindProperty("m_Enabled"));
|
||||
s_XYZMode = DrawFloatOrVector3Field(s_SerializedObject.FindProperty("m_Scale3D"), s_XYZMode);
|
||||
EditorGUILayout.PropertyField(s_SerializedObject.FindProperty("m_PositionMode"));
|
||||
DrawAutoScaling(s_SerializedObject.FindProperty("m_AutoScalingMode"), uiParticles);
|
||||
EditorGUIUtility.labelWidth = labelWidth;
|
||||
}
|
||||
|
||||
s_SerializedObject.ApplyModifiedProperties();
|
||||
}
|
||||
catch
|
||||
{
|
||||
// ignored
|
||||
}
|
||||
}
|
||||
|
||||
private void DestroyUIParticle(UIParticle p, bool ignoreCurrent = false)
|
||||
{
|
||||
if (!p || (ignoreCurrent && target == p)) return;
|
||||
|
||||
@@ -1,61 +1,85 @@
|
||||
# Particle Effect For UGUI (UI Particle)
|
||||
|
||||
This package provides a component to render particle effects for uGUI in Unity 2018.2 or later.
|
||||
The particle rendering is maskable and sortable, without the need for an extra Camera, RenderTexture, or Canvas.
|
||||
# <img alt="UIParticleIcon" src="https://github.com/mob-sakai/ParticleEffectForUGUI/assets/12690315/d76e105e-a840-4f61-a1f6-8cf311c0812d" width="26"/> Particle Effect For UGUI (UI Particle) <!-- omit in toc -->
|
||||
|
||||
[](https://openupm.com/packages/com.coffee.ui-particle/)
|
||||
[](https://github.com/mob-sakai/ParticleEffectForUGUI/releases)
|
||||
[](https://github.com/mob-sakai/ParticleEffectForUGUI/blob/main/LICENSE.txt)
|
||||
[](https://github.com/mob-sakai/ParticleEffectForUGUI/releases)
|
||||
[](https://github.com/mob-sakai/ParticleEffectForUGUI/blob/main/LICENSE.md)
|
||||

|
||||

|
||||

|
||||

|
||||
[](http://makeapullrequest.com)
|
||||
[](https://github.com/mob-sakai/ParticleEffectForUGUI/subscription)
|
||||
[](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-) | [📌 Key Features](#-key-features) | [🎮 Demo](#-demo) | [⚙ Installation](#-installation) | [🚀 Usage](#-usage) | [🛠 Development Note](#-development-note) | [🤝 Contributing](#-contributing) >>
|
||||
|
||||
<br><br>
|
||||
|
||||
## 📝 Description
|
||||
## 📝 Description <!-- omit in toc -->
|
||||
|
||||

|
||||
|
||||
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.
|
||||
This package uses the new APIs `MeshBake/MeshTrailBake` (introduced in Unity 2018.2) to render particles through `CanvasRenderer`.
|
||||
You can render, mask, and sort your `ParticleSystems` for UI without the need for an additional `Camera`, `RenderTexture`, or `Canvas`.
|
||||
|
||||
### Features
|
||||
- [📌 Key Features](#-key-features)
|
||||
- [🎮 Demo](#-demo)
|
||||
- [⚙ Installation](#-installation)
|
||||
- [Install via OpenUPM](#install-via-openupm)
|
||||
- [Install via UPM (with Package Manager UI)](#install-via-upm-with-package-manager-ui)
|
||||
- [Install via UPM (Manually)](#install-via-upm-manually)
|
||||
- [Install as Embedded Package](#install-as-embedded-package)
|
||||
- [🚀 Usage](#-usage)
|
||||
- [Component: UIParticle](#component-uiparticle)
|
||||
- [Basic Usage](#basic-usage)
|
||||
- [Usage with Your Existing ParticleSystem Prefab](#usage-with-your-existing-particlesystem-prefab)
|
||||
- [Usage with `Mask` or `RectMask2D` Component](#usage-with-mask-or-rectmask2d-component)
|
||||
- [Usage with Script](#usage-with-script)
|
||||
- [Component: UIParticleAttractor](#component-uiparticleattractor)
|
||||
- [Project Settings](#project-settings)
|
||||
- [🛠 Development Note](#-development-note)
|
||||
- [Compares the Baking mesh approach with the conventional approach](#compares-the-baking-mesh-approach-with-the-conventional-approach)
|
||||
- [Performance test results](#performance-test-results)
|
||||
- [🔍 FAQ: Why Are My UIParticles Not Displayed Correctly?](#-faq-why-are-my-uiparticles-not-displayed-correctly)
|
||||
- [Shader Limitation](#shader-limitation)
|
||||
- [Built-in shaders are not supported](#built-in-shaders-are-not-supported)
|
||||
- [(Unity 2018 or 2019) UV.zw components will be discarded](#unity-2018-or-2019-uvzw-components-will-be-discarded)
|
||||
- [(Unity 2018 or 2019) Custom vertex streams](#unity-2018-or-2019-custom-vertex-streams)
|
||||
- [Overheads](#overheads)
|
||||
- [How to Make a Custom Shader to Support `Mask` and `RectMask2D` Component](#how-to-make-a-custom-shader-to-support-mask-and-rectmask2d-component)
|
||||
- [🤝 Contributing](#-contributing)
|
||||
- [Issues](#issues)
|
||||
- [Pull Requests](#pull-requests)
|
||||
- [Support](#support)
|
||||
- [License](#license)
|
||||
- [Author](#author)
|
||||
- [See Also](#see-also)
|
||||
|
||||
* 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]
|
||||
<br><br>
|
||||
|
||||
[AnimatableProperty.gif]: https://user-images.githubusercontent.com/12690315/53286323-2d94a980-37b0-11e9-8afb-c4a207805ff2.gif
|
||||
## 📌 Key Features
|
||||
|
||||
[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
|
||||
* **Easy to use:** The package is ready to use out of the box.
|
||||
* **Sortable:** Sort particle effects and other UI elements by sibling index.
|
||||
* **Maskable:** Supports `Mask` or `RectMask2D`.
|
||||
* **No extra components required:** No need for an additional `Camera`, `RenderTexture`, or `Canvas`.
|
||||
* **Trail module support:** Fully supports the Trail module.
|
||||
* **CanvasGroup alpha support:** Integrates with `CanvasGroup` alpha.
|
||||
* **No allocations:** Efficiently renders particles without allocations.
|
||||
* **Any canvas render mode support:** Works with overlay, camera space, and world space.
|
||||
* **Any Render pipeline support:** Compatible with Universal Render Pipeline (URP) and High Definition Render Pipeline (HDRP).
|
||||
* **Disabling domain reload support:** Supports disabling `Enter Play Mode Options > Reload Domain`.
|
||||
* **Animatable material properties:** Supports changing material properties with AnimationClip (AnimatableProperty).
|
||||

|
||||
* **Multiple materials:** Supports 8+ materials.
|
||||
* **Correct positioning:** Adjusts world space particle positions correctly when changing window size for standalone platforms (Windows, MacOSX, and Linux).
|
||||
* **Adaptive scaling:** Provides adaptive scaling for UI (AutoScalingMode).
|
||||
* **Performance optimization:** Mesh sharing group to improve performance.
|
||||
<img alt="MeshSharing.gif" src="https://user-images.githubusercontent.com/12690315/174311048-c882df81-6c34-4eba-b0aa-5645457692f1.gif" width="450"/>
|
||||
* **Particle attractor:** Includes a particle attractor component.
|
||||
<img alt="ParticleAttractor.gif" src="https://user-images.githubusercontent.com/12690315/174311027-462929a4-13f0-4ec4-86ea-9c832f2eecf1.gif" width="450"/>
|
||||
* **Emission position mode:** Supports relative/absolute particle emission position modes.
|
||||
<img alt="AbsolutePosition.gif" src="https://user-images.githubusercontent.com/12690315/175751579-5a2357e8-2ecf-4afd-83c8-66e9771bde39.gif" width="450"/>
|
||||
* **Custom view size:** Fixes min/max particle size mismatch.
|
||||

|
||||
|
||||
<br><br>
|
||||
|
||||
@@ -76,66 +100,86 @@ or Canvas.
|
||||
|
||||
[JMO]: https://assetstore.unity.com/publishers/1669
|
||||
|
||||
|
||||
<br><br>
|
||||
|
||||
## ⚙ Installation
|
||||
|
||||
_This package requires Unity 2018.3 or later._
|
||||
_This package requires **Unity 2018.3 or later**._
|
||||
|
||||
#### 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) package registry.
|
||||
- This is the preferred method of installation, as you can easily receive updates as they're released.
|
||||
- If you have [openupm-cli](https://github.com/openupm/openupm-cli) installed, then run the following command in your project's directory:
|
||||
```
|
||||
openupm add com.coffee.ui-particle
|
||||
```
|
||||
- To update the package, use Package Manager UI (`Window > Package Manager`) or run the following command with `@{version}`:
|
||||
```
|
||||
openupm add com.coffee.ui-particle@4.9.0
|
||||
```
|
||||
|
||||
If you have [openupm-cli](https://github.com/openupm/openupm-cli) installed, then run the following command in your
|
||||
project's directory:
|
||||
#### Install via UPM (with Package Manager UI)
|
||||
|
||||
```sh
|
||||
openupm add com.coffee.ui-particle
|
||||
```
|
||||
- Click `Window > Package Manager` to open Package Manager UI.
|
||||
- Click `+ > Add package from git URL...` and input the repository URL: `https://github.com/mob-sakai/ParticleEffectForUGUI.git`
|
||||

|
||||
- To update the package, change suffix `#{version}` to the target version.
|
||||
- e.g. `https://github.com/mob-sakai/ParticleEffectForUGUI.git#4.9.0`
|
||||
|
||||
#### Install via UPM (using Git URL)
|
||||
#### Install via UPM (Manually)
|
||||
|
||||
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",
|
||||
...
|
||||
- Open the `Packages/manifest.json` file in your project. Then add this package somewhere in the `dependencies` block:
|
||||
```json
|
||||
{
|
||||
"dependencies": {
|
||||
"com.coffee.ui-particle": "https://github.com/mob-sakai/ParticleEffectForUGUI.git",
|
||||
...
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
```
|
||||
|
||||
To update the package, change suffix `#{version}` to the target version.
|
||||
- To update the package, change suffix `#{version}` to the target version.
|
||||
- e.g. `"com.coffee.ui-particle": "https://github.com/mob-sakai/ParticleEffectForUGUI.git#4.9.0",`
|
||||
|
||||
* e.g. `"com.coffee.ui-particle": "https://github.com/mob-sakai/ParticleEffectForUGUI.git#4.6.0",`
|
||||
#### Install as Embedded Package
|
||||
|
||||
Or, use [UpmGitExtension](https://github.com/mob-sakai/UpmGitExtension) to install and update the package.
|
||||
1. Download a source code zip file from [Releases](https://github.com/mob-sakai/ParticleEffectForUGUI.git/releases) and extract it.
|
||||
2. Place it in your project's `Packages` directory.
|
||||

|
||||
- If you want to fix bugs or add features, install it as an embedded package.
|
||||
- To update the package, you need to re-download it and replace the contents.
|
||||
|
||||
<br><br>
|
||||
|
||||
## 🚀 Usage
|
||||
|
||||
### UIParticle Component
|
||||
### Component: UIParticle
|
||||
|
||||
`UIParticle` controls the ParticleSystems that are attached to its own game objects and child game objects.
|
||||
|
||||

|
||||

|
||||
|
||||
- **Maskable**: Does this graphic allow masking.
|
||||
- **Scale**: Scale the rendering. When the `3D` toggle is enabled, 3D scale (x, y, z) is supported.
|
||||
- **Maskable**: Does this graphic allow maskable.
|
||||
- **Scale**: Scale the rendering particles. When the `3D` toggle is enabled, 3D scale (x, y, z) is supported.
|
||||
- **Animatable Properties**: If you want to update material properties (e.g., `_MainTex_ST`, `_Color`) in AnimationClip,
|
||||
use this to mark the changes.
|
||||
use this to mark as animatable.
|
||||
- **Mesh Sharing**: Particle simulation results are shared within the same group. A large number of the same effects can
|
||||
be displayed with a small load. When the `Random` toggle is enabled, it will be grouped randomly.
|
||||
- **None:** Disable mesh sharing.
|
||||
- **Auto:** Automatically select Primary/Replica.
|
||||
- **Primary:** Provides particle simulation results to the same group.
|
||||
- **Primary Simulator:** Primary, but do not render the particle (simulation only).
|
||||
- **Replica:** Render simulation results provided by the primary.
|
||||
- **Position Mode**: Emission position mode.
|
||||
- **Absolute:** 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`.
|
||||
- **Absolute:** The particles will be emitted from the world position.
|
||||
- **Relative:** The particles will be emitted from the scaled position.
|
||||
- **Auto Scaling Mode**: How to automatically adjust when the Canvas scale is changed by the screen size or reference resolution.
|
||||
- **None:** Do nothing.
|
||||
- **Transform:** Transform.lossyScale (=world scale) will be set to (1, 1, 1).
|
||||
- **UIParticle:** UIParticle.scale will be adjusted.
|
||||
- **Use Custom View:** Use this if the particles are not displayed correctly due to min/max particle size.
|
||||
- **Custom view size:** Change the bake view size.
|
||||
- **Rendering Order**: The ParticleSystem list to be rendered. You can change the order and the materials.
|
||||
|
||||
**NOTE:** Press the `Refresh` button to reconstruct the rendering order based on children ParticleSystem's sorting order
|
||||
@@ -143,7 +187,7 @@ and z-position.
|
||||
|
||||
<br><br>
|
||||
|
||||
#### Basic Usage
|
||||
### Basic Usage
|
||||
|
||||
1. Select `GameObject/UI/ParticleSystem` to create UIParticle with a ParticleSystem.
|
||||

|
||||
@@ -152,7 +196,7 @@ and z-position.
|
||||
|
||||
<br>
|
||||
|
||||
#### With Your Existing ParticleSystem Prefab
|
||||
### Usage with Your Existing ParticleSystem Prefab
|
||||
|
||||
1. Select `GameObject/UI/ParticleSystem (Empty)` to create UIParticle.
|
||||

|
||||
@@ -161,7 +205,7 @@ and z-position.
|
||||
|
||||
<br>
|
||||
|
||||
#### With `Mask` or `RectMask2D` Component
|
||||
### Usage with `Mask` or `RectMask2D` Component
|
||||
|
||||
If you want to mask particles, set a stencil-supported shader (such as `UI/UIAdditive`) to the material for
|
||||
ParticleSystem.
|
||||
@@ -173,12 +217,13 @@ section.
|
||||
|
||||
<br><br>
|
||||
|
||||
### Script usage
|
||||
### Usage with Script
|
||||
|
||||
```cs
|
||||
// Instant ParticleSystem prefab with UIParticle on runtime.
|
||||
// Instantiate ParticleSystem prefab with UIParticle on runtime.
|
||||
var go = GameObject.Instantiate(prefab);
|
||||
var uiParticle = go.AddComponent<UIParticle>();
|
||||
uiParticle.scale = 100;
|
||||
|
||||
// Control by ParticleSystem.
|
||||
particleSystem.Play();
|
||||
@@ -191,14 +236,14 @@ uiParticle.Stop();
|
||||
|
||||
<br><br>
|
||||
|
||||
### UIParticleAttractor component
|
||||
### Component: UIParticleAttractor
|
||||
|
||||
`UIParticleAttractor` attracts particles generated by the specified ParticleSystem.
|
||||
|
||||

|
||||

|
||||

|
||||
|
||||
- **Particle System**: Attracts particles generated by the specified particle system.
|
||||
- **Particle Systems**: Attracts particles generated by the specified ParticleSystems.
|
||||
- **Destination Radius**: Once the particle is within the radius, the particle lifetime will become 0, and `OnAttracted`
|
||||
will be called.
|
||||
- **Delay Rate**: Delay to start attracting. It is a percentage of the particle's start lifetime.
|
||||
@@ -212,6 +257,14 @@ uiParticle.Stop();
|
||||
|
||||
<br><br>
|
||||
|
||||
### Project Settings
|
||||
|
||||

|
||||
|
||||
- Click `Edit > Project Settings` to open the Project Settings window and then select `UI > UI Particle` category.
|
||||
|
||||
<br><br>
|
||||
|
||||
## 🛠 Development Note
|
||||
|
||||
### Compares the Baking mesh approach with the conventional approach
|
||||
@@ -343,7 +396,7 @@ When improving performance, keep the following in mind:
|
||||
- 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
|
||||
### How to Make a Custom Shader to Support `Mask` and `RectMask2D` Component
|
||||
|
||||
<details>
|
||||
<summary>Shader tips</summary>
|
||||
|
||||
BIN
Packages/src/Runtime/Coffee.UIParticle.R.dll
Normal file
BIN
Packages/src/Runtime/Coffee.UIParticle.R.dll
Normal file
Binary file not shown.
33
Packages/src/Runtime/Coffee.UIParticle.R.dll.meta
Normal file
33
Packages/src/Runtime/Coffee.UIParticle.R.dll.meta
Normal file
@@ -0,0 +1,33 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 4d73b3825bf044d418ae21bb331d3902
|
||||
PluginImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
iconMap: {}
|
||||
executionOrder: {}
|
||||
defineConstraints: []
|
||||
isPreloaded: 0
|
||||
isOverridable: 1
|
||||
isExplicitlyReferenced: 0
|
||||
validateReferences: 1
|
||||
platformData:
|
||||
- first:
|
||||
Any:
|
||||
second:
|
||||
enabled: 1
|
||||
settings: {}
|
||||
- first:
|
||||
Editor: Editor
|
||||
second:
|
||||
enabled: 0
|
||||
settings:
|
||||
DefaultValueInitialized: true
|
||||
- first:
|
||||
Windows Store Apps: WindowsStoreApps
|
||||
second:
|
||||
enabled: 0
|
||||
settings:
|
||||
CPU: AnyCPU
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
8
Packages/src/Runtime/Internal.meta
Normal file
8
Packages/src/Runtime/Internal.meta
Normal file
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 53aa3f36032944b3fb1455e774c52396
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
8
Packages/src/Runtime/Internal/Extensions.meta
Normal file
8
Packages/src/Runtime/Internal/Extensions.meta
Normal file
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 8cf8018dee45a4c42a19eec890eaa5b1
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
134
Packages/src/Runtime/Internal/Extensions/CanvasExtensions.cs
Normal file
134
Packages/src/Runtime/Internal/Extensions/CanvasExtensions.cs
Normal file
@@ -0,0 +1,134 @@
|
||||
#if UNITY_2021_3_0 || UNITY_2021_3_1 || UNITY_2021_3_2 || UNITY_2021_3_3 || UNITY_2021_3_4 || UNITY_2021_3_5 || UNITY_2021_3_6 || UNITY_2021_3_7 || UNITY_2021_3_8 || UNITY_2021_3_9
|
||||
#elif UNITY_2021_3_10 || UNITY_2021_3_11 || UNITY_2021_3_12 || UNITY_2021_3_13 || UNITY_2021_3_14 || UNITY_2021_3_15 || UNITY_2021_3_16 || UNITY_2021_3_17 || UNITY_2021_3_18 || UNITY_2021_3_19
|
||||
#elif UNITY_2021_3_20 || UNITY_2021_3_21 || UNITY_2021_3_22 || UNITY_2021_3_23 || UNITY_2021_3_24 || UNITY_2021_3_25 || UNITY_2021_3_26 || UNITY_2021_3_27 || UNITY_2021_3_28 || UNITY_2021_3_29
|
||||
#elif UNITY_2021_3_30 || UNITY_2021_3_31 || UNITY_2021_3_32 || UNITY_2021_3_33
|
||||
#elif UNITY_2022_2_0 || UNITY_2022_2_1 || UNITY_2022_2_2 || UNITY_2022_2_3 || UNITY_2022_2_4 || UNITY_2022_2_5 || UNITY_2022_2_6 || UNITY_2022_2_7 || UNITY_2022_2_8 || UNITY_2022_2_9
|
||||
#elif UNITY_2022_2_10 || UNITY_2022_2_11 || UNITY_2022_2_12 || UNITY_2022_2_13 || UNITY_2022_2_14
|
||||
#elif UNITY_2021_3 || UNITY_2022_2 || UNITY_2022_3 || UNITY_2023_2_OR_NEWER
|
||||
#define CANVAS_SUPPORT_ALWAYS_GAMMA
|
||||
#endif
|
||||
|
||||
using UnityEngine;
|
||||
using UnityEngine.Profiling;
|
||||
#if UNITY_MODULE_VR
|
||||
using UnityEngine.XR;
|
||||
#endif
|
||||
|
||||
namespace Coffee.UIParticleInternal
|
||||
{
|
||||
internal static class CanvasExtensions
|
||||
{
|
||||
public static bool ShouldGammaToLinearInShader(this Canvas canvas)
|
||||
{
|
||||
return QualitySettings.activeColorSpace == ColorSpace.Linear &&
|
||||
#if CANVAS_SUPPORT_ALWAYS_GAMMA
|
||||
canvas.vertexColorAlwaysGammaSpace;
|
||||
#else
|
||||
false;
|
||||
#endif
|
||||
}
|
||||
|
||||
public static bool ShouldGammaToLinearInMesh(this Canvas canvas)
|
||||
{
|
||||
return QualitySettings.activeColorSpace == ColorSpace.Linear &&
|
||||
#if CANVAS_SUPPORT_ALWAYS_GAMMA
|
||||
!canvas.vertexColorAlwaysGammaSpace;
|
||||
#else
|
||||
true;
|
||||
#endif
|
||||
}
|
||||
|
||||
public static bool IsStereoCanvas(this Canvas canvas)
|
||||
{
|
||||
#if UNITY_MODULE_VR
|
||||
if (FrameCache.TryGet<bool>(canvas, nameof(IsStereoCanvas), out var stereo)) return stereo;
|
||||
|
||||
stereo =
|
||||
canvas != null && canvas.renderMode != RenderMode.ScreenSpaceOverlay && canvas.worldCamera != null
|
||||
&& XRSettings.enabled && !string.IsNullOrEmpty(XRSettings.loadedDeviceName);
|
||||
FrameCache.Set(canvas, nameof(IsStereoCanvas), stereo);
|
||||
return stereo;
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the view-projection matrix for a Canvas.
|
||||
/// </summary>
|
||||
public static void GetViewProjectionMatrix(this Canvas canvas, out Matrix4x4 vpMatrix)
|
||||
{
|
||||
canvas.GetViewProjectionMatrix(Camera.MonoOrStereoscopicEye.Mono, out vpMatrix);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the view-projection matrix for a Canvas.
|
||||
/// </summary>
|
||||
public static void GetViewProjectionMatrix(this Canvas canvas, Camera.MonoOrStereoscopicEye eye,
|
||||
out Matrix4x4 vpMatrix)
|
||||
{
|
||||
if (FrameCache.TryGet(canvas, nameof(GetViewProjectionMatrix), out vpMatrix)) return;
|
||||
|
||||
canvas.GetViewProjectionMatrix(eye, out var viewMatrix, out var projectionMatrix);
|
||||
vpMatrix = viewMatrix * projectionMatrix;
|
||||
FrameCache.Set(canvas, nameof(GetViewProjectionMatrix), vpMatrix);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the view and projection matrices for a Canvas.
|
||||
/// </summary>
|
||||
public static void GetViewProjectionMatrix(this Canvas canvas, out Matrix4x4 vMatrix, out Matrix4x4 pMatrix)
|
||||
{
|
||||
canvas.GetViewProjectionMatrix(Camera.MonoOrStereoscopicEye.Mono, out vMatrix, out pMatrix);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the view and projection matrices for a Canvas.
|
||||
/// </summary>
|
||||
public static void GetViewProjectionMatrix(this Canvas canvas, Camera.MonoOrStereoscopicEye eye,
|
||||
out Matrix4x4 vMatrix, out Matrix4x4 pMatrix)
|
||||
{
|
||||
if (FrameCache.TryGet(canvas, "GetViewMatrix", (int)eye, out vMatrix) &&
|
||||
FrameCache.TryGet(canvas, "GetProjectionMatrix", (int)eye, out pMatrix))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Get view and projection matrices.
|
||||
Profiler.BeginSample("(COF)[CanvasExt] GetViewProjectionMatrix");
|
||||
var rootCanvas = canvas.rootCanvas;
|
||||
var cam = rootCanvas.worldCamera;
|
||||
if (rootCanvas && rootCanvas.renderMode != RenderMode.ScreenSpaceOverlay && cam)
|
||||
{
|
||||
if (eye == Camera.MonoOrStereoscopicEye.Mono)
|
||||
{
|
||||
vMatrix = cam.worldToCameraMatrix;
|
||||
pMatrix = GL.GetGPUProjectionMatrix(cam.projectionMatrix, false);
|
||||
}
|
||||
else
|
||||
{
|
||||
pMatrix = cam.GetStereoProjectionMatrix((Camera.StereoscopicEye)eye);
|
||||
vMatrix = cam.GetStereoViewMatrix((Camera.StereoscopicEye)eye);
|
||||
pMatrix = GL.GetGPUProjectionMatrix(pMatrix, false);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
var pos = rootCanvas.transform.position;
|
||||
vMatrix = Matrix4x4.TRS(
|
||||
new Vector3(-pos.x, -pos.y, -1000),
|
||||
Quaternion.identity,
|
||||
new Vector3(1, 1, -1f));
|
||||
pMatrix = Matrix4x4.TRS(
|
||||
new Vector3(0, 0, -1),
|
||||
Quaternion.identity,
|
||||
new Vector3(1 / pos.x, 1 / pos.y, -2 / 10000f));
|
||||
}
|
||||
|
||||
FrameCache.Set(canvas, "GetViewMatrix", (int)eye, vMatrix);
|
||||
FrameCache.Set(canvas, "GetProjectionMatrix", (int)eye, pMatrix);
|
||||
|
||||
Profiler.EndSample();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b0beae5bb1cb142b9ab90dc0d371f026
|
||||
guid: 9dd767b8c0f95478386e7d5079cd44df
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
@@ -0,0 +1,77 @@
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Profiling;
|
||||
|
||||
namespace Coffee.UIParticleInternal
|
||||
{
|
||||
internal static class Color32Extensions
|
||||
{
|
||||
private static readonly List<Color32> s_Colors = new List<Color32>();
|
||||
private static byte[] s_LinearToGammaLut;
|
||||
private static byte[] s_GammaToLinearLut;
|
||||
|
||||
public static byte LinearToGamma(this byte self)
|
||||
{
|
||||
if (s_LinearToGammaLut == null)
|
||||
{
|
||||
s_LinearToGammaLut = new byte[256];
|
||||
for (var i = 0; i < 256; i++)
|
||||
{
|
||||
s_LinearToGammaLut[i] = (byte)(Mathf.LinearToGammaSpace(i / 255f) * 255f);
|
||||
}
|
||||
}
|
||||
|
||||
return s_LinearToGammaLut[self];
|
||||
}
|
||||
|
||||
public static byte GammaToLinear(this byte self)
|
||||
{
|
||||
if (s_GammaToLinearLut == null)
|
||||
{
|
||||
s_GammaToLinearLut = new byte[256];
|
||||
for (var i = 0; i < 256; i++)
|
||||
{
|
||||
s_GammaToLinearLut[i] = (byte)(Mathf.GammaToLinearSpace(i / 255f) * 255f);
|
||||
}
|
||||
}
|
||||
|
||||
return s_GammaToLinearLut[self];
|
||||
}
|
||||
|
||||
public static void LinearToGamma(this Mesh self)
|
||||
{
|
||||
Profiler.BeginSample("(COF)[ColorExt] LinearToGamma (Mesh)");
|
||||
self.GetColors(s_Colors);
|
||||
var count = s_Colors.Count;
|
||||
for (var i = 0; i < count; i++)
|
||||
{
|
||||
var c = s_Colors[i];
|
||||
c.r = c.r.LinearToGamma();
|
||||
c.g = c.g.LinearToGamma();
|
||||
c.b = c.b.LinearToGamma();
|
||||
s_Colors[i] = c;
|
||||
}
|
||||
|
||||
self.SetColors(s_Colors);
|
||||
Profiler.EndSample();
|
||||
}
|
||||
|
||||
public static void GammaToLinear(this Mesh self)
|
||||
{
|
||||
Profiler.BeginSample("(COF)[ColorExt] GammaToLinear (Mesh)");
|
||||
self.GetColors(s_Colors);
|
||||
var count = s_Colors.Count;
|
||||
for (var i = 0; i < count; i++)
|
||||
{
|
||||
var c = s_Colors[i];
|
||||
c.r = c.r.GammaToLinear();
|
||||
c.g = c.g.GammaToLinear();
|
||||
c.b = c.b.GammaToLinear();
|
||||
s_Colors[i] = c;
|
||||
}
|
||||
|
||||
self.SetColors(s_Colors);
|
||||
Profiler.EndSample();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
fileFormatVersion: 2
|
||||
guid: d188d31b140094ebc84a9caafbc7ac71
|
||||
guid: 0ef431b9df32c410ea5fa46be81def6b
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
227
Packages/src/Runtime/Internal/Extensions/ComponentExtensions.cs
Normal file
227
Packages/src/Runtime/Internal/Extensions/ComponentExtensions.cs
Normal file
@@ -0,0 +1,227 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Profiling;
|
||||
using Object = UnityEngine.Object;
|
||||
|
||||
namespace Coffee.UIParticleInternal
|
||||
{
|
||||
/// <summary>
|
||||
/// Extension methods for Component class.
|
||||
/// </summary>
|
||||
internal static class ComponentExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// Get components in children of a specific type in the hierarchy of a GameObject.
|
||||
/// </summary>
|
||||
public static T[] GetComponentsInChildren<T>(this Component self, int depth)
|
||||
where T : Component
|
||||
{
|
||||
var results = InternalListPool<T>.Rent();
|
||||
self.GetComponentsInChildren_Internal(results, depth);
|
||||
var array = results.ToArray();
|
||||
InternalListPool<T>.Return(ref results);
|
||||
return array;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get components in children of a specific type in the hierarchy of a GameObject.
|
||||
/// </summary>
|
||||
public static void GetComponentsInChildren<T>(this Component self, List<T> results, int depth)
|
||||
where T : Component
|
||||
{
|
||||
results.Clear();
|
||||
self.GetComponentsInChildren_Internal(results, depth);
|
||||
}
|
||||
|
||||
private static void GetComponentsInChildren_Internal<T>(this Component self, List<T> results, int depth)
|
||||
where T : Component
|
||||
{
|
||||
if (!self || results == null || depth < 0) return;
|
||||
|
||||
var tr = self.transform;
|
||||
if (tr.TryGetComponent<T>(out var t))
|
||||
{
|
||||
results.Add(t);
|
||||
}
|
||||
|
||||
if (depth - 1 < 0) return;
|
||||
var childCount = tr.childCount;
|
||||
for (var i = 0; i < childCount; i++)
|
||||
{
|
||||
tr.GetChild(i).GetComponentsInChildren_Internal(results, depth - 1);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get or add a component of a specific type to a GameObject.
|
||||
/// </summary>
|
||||
public static T GetOrAddComponent<T>(this Component self) where T : Component
|
||||
{
|
||||
if (!self) return null;
|
||||
return self.TryGetComponent<T>(out var component)
|
||||
? component
|
||||
: self.gameObject.AddComponent<T>();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the root component of a specific type in the hierarchy of a GameObject.
|
||||
/// </summary>
|
||||
public static T GetRootComponent<T>(this Component self) where T : Component
|
||||
{
|
||||
T component = null;
|
||||
var transform = self.transform;
|
||||
while (transform)
|
||||
{
|
||||
if (transform.TryGetComponent<T>(out var c))
|
||||
{
|
||||
component = c;
|
||||
}
|
||||
|
||||
transform = transform.parent;
|
||||
}
|
||||
|
||||
return component;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get a component of a specific type in the parent hierarchy of a GameObject.
|
||||
/// </summary>
|
||||
public static T GetComponentInParent<T>(this Component self, bool includeSelf, Transform stopAfter,
|
||||
Predicate<T> valid)
|
||||
where T : Component
|
||||
{
|
||||
var tr = includeSelf ? self.transform : self.transform.parent;
|
||||
while (tr)
|
||||
{
|
||||
if (tr.TryGetComponent<T>(out var c) && valid(c)) return c;
|
||||
if (tr == stopAfter) return null;
|
||||
tr = tr.parent;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Add a component of a specific type to the children of a GameObject.
|
||||
/// </summary>
|
||||
public static void AddComponentOnChildren<T>(this Component self, HideFlags hideFlags, bool includeSelf)
|
||||
where T : Component
|
||||
{
|
||||
if (self == null) return;
|
||||
|
||||
Profiler.BeginSample("(COF)[ComponentExt] AddComponentOnChildren > Self");
|
||||
if (includeSelf && !self.TryGetComponent<T>(out _))
|
||||
{
|
||||
var c = self.gameObject.AddComponent<T>();
|
||||
c.hideFlags = hideFlags;
|
||||
}
|
||||
|
||||
Profiler.EndSample();
|
||||
|
||||
Profiler.BeginSample("(COF)[ComponentExt] AddComponentOnChildren > Child");
|
||||
var childCount = self.transform.childCount;
|
||||
for (var i = 0; i < childCount; i++)
|
||||
{
|
||||
var child = self.transform.GetChild(i);
|
||||
if (child.TryGetComponent<T>(out _)) continue;
|
||||
|
||||
var c = child.gameObject.AddComponent<T>();
|
||||
c.hideFlags = hideFlags;
|
||||
}
|
||||
|
||||
Profiler.EndSample();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Add a component of a specific type to the children of a GameObject.
|
||||
/// </summary>
|
||||
public static void AddComponentOnChildren<T>(this Component self, bool includeSelf)
|
||||
where T : Component
|
||||
{
|
||||
if (self == null) return;
|
||||
|
||||
Profiler.BeginSample("(COF)[ComponentExt] AddComponentOnChildren > Self");
|
||||
if (includeSelf && !self.TryGetComponent<T>(out _))
|
||||
{
|
||||
self.gameObject.AddComponent<T>();
|
||||
}
|
||||
|
||||
Profiler.EndSample();
|
||||
|
||||
Profiler.BeginSample("(COF)[ComponentExt] AddComponentOnChildren > Child");
|
||||
var childCount = self.transform.childCount;
|
||||
for (var i = 0; i < childCount; i++)
|
||||
{
|
||||
var child = self.transform.GetChild(i);
|
||||
if (child.TryGetComponent<T>(out _)) continue;
|
||||
|
||||
child.gameObject.AddComponent<T>();
|
||||
}
|
||||
|
||||
Profiler.EndSample();
|
||||
}
|
||||
|
||||
#if !UNITY_2021_2_OR_NEWER && !UNITY_2020_3_45 && !UNITY_2020_3_46 && !UNITY_2020_3_47 && !UNITY_2020_3_48
|
||||
public static T GetComponentInParent<T>(this Component self, bool includeInactive) where T : Component
|
||||
{
|
||||
if (!self) return null;
|
||||
if (!includeInactive) return self.GetComponentInParent<T>();
|
||||
|
||||
var current = self.transform;
|
||||
while (current)
|
||||
{
|
||||
if (current.TryGetComponent<T>(out var c)) return c;
|
||||
current = current.parent;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if UNITY_EDITOR
|
||||
/// <summary>
|
||||
/// Verify whether it can be converted to the specified component.
|
||||
/// </summary>
|
||||
internal static bool CanConvertTo<T>(this Object context) where T : MonoBehaviour
|
||||
{
|
||||
return context && context.GetType() != typeof(T);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Convert to the specified component.
|
||||
/// </summary>
|
||||
internal static void ConvertTo<T>(this Object context) where T : MonoBehaviour
|
||||
{
|
||||
var target = context as MonoBehaviour;
|
||||
if (target == null) return;
|
||||
|
||||
var so = new SerializedObject(target);
|
||||
so.Update();
|
||||
|
||||
var oldEnable = target.enabled;
|
||||
target.enabled = false;
|
||||
|
||||
// Find MonoScript of the specified component.
|
||||
foreach (var script in Resources.FindObjectsOfTypeAll<MonoScript>())
|
||||
{
|
||||
if (script.GetClass() != typeof(T))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// Set 'm_Script' to convert.
|
||||
so.FindProperty("m_Script").objectReferenceValue = script;
|
||||
so.ApplyModifiedProperties();
|
||||
break;
|
||||
}
|
||||
|
||||
if (so.targetObject is MonoBehaviour mb)
|
||||
{
|
||||
mb.enabled = oldEnable;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 8455ee485a5ee4cacbdf558f66af65fb
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
60
Packages/src/Runtime/Internal/Extensions/SpriteExtensions.cs
Normal file
60
Packages/src/Runtime/Internal/Extensions/SpriteExtensions.cs
Normal file
@@ -0,0 +1,60 @@
|
||||
using System;
|
||||
using UnityEngine;
|
||||
using UnityEngine.U2D;
|
||||
#if UNITY_EDITOR
|
||||
using System.Reflection;
|
||||
#endif
|
||||
|
||||
namespace Coffee.UIParticleInternal
|
||||
{
|
||||
/// <summary>
|
||||
/// Extension methods for Sprite class.
|
||||
/// </summary>
|
||||
internal static class SpriteExtensions
|
||||
{
|
||||
#if UNITY_EDITOR
|
||||
private static readonly Type s_SpriteEditorExtensionType =
|
||||
Type.GetType("UnityEditor.Experimental.U2D.SpriteEditorExtension, UnityEditor")
|
||||
?? Type.GetType("UnityEditor.U2D.SpriteEditorExtension, UnityEditor");
|
||||
|
||||
private static readonly Func<Sprite, Texture2D> s_GetActiveAtlasTextureMethod =
|
||||
(Func<Sprite, Texture2D>)Delegate.CreateDelegate(typeof(Func<Sprite, Texture2D>),
|
||||
s_SpriteEditorExtensionType
|
||||
.GetMethod("GetActiveAtlasTexture", BindingFlags.Static | BindingFlags.NonPublic));
|
||||
|
||||
private static readonly Func<Sprite, SpriteAtlas> s_GetActiveAtlasMethod =
|
||||
(Func<Sprite, SpriteAtlas>)Delegate.CreateDelegate(typeof(Func<Sprite, SpriteAtlas>),
|
||||
s_SpriteEditorExtensionType
|
||||
.GetMethod("GetActiveAtlas", BindingFlags.Static | BindingFlags.NonPublic));
|
||||
|
||||
/// <summary>
|
||||
/// Get the actual texture of a sprite in play mode or edit mode.
|
||||
/// </summary>
|
||||
public static Texture2D GetActualTexture(this Sprite self)
|
||||
{
|
||||
if (!self) return null;
|
||||
|
||||
var ret = s_GetActiveAtlasTextureMethod(self);
|
||||
return ret ? ret : self.texture;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the active sprite atlas of a sprite in play mode or edit mode.
|
||||
/// </summary>
|
||||
public static SpriteAtlas GetActiveAtlas(this Sprite self)
|
||||
{
|
||||
if (!self) return null;
|
||||
|
||||
return s_GetActiveAtlasMethod(self);
|
||||
}
|
||||
#else
|
||||
/// <summary>
|
||||
/// Get the actual texture of a sprite in play mode.
|
||||
/// </summary>
|
||||
internal static Texture2D GetActualTexture(this Sprite self)
|
||||
{
|
||||
return self ? self.texture : null;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: a7a2e11131111447cb7fc0394a14da65
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,46 @@
|
||||
using UnityEngine;
|
||||
|
||||
namespace Coffee.UIParticleInternal
|
||||
{
|
||||
internal static class Vector3Extensions
|
||||
{
|
||||
public static Vector3 Inverse(this Vector3 self)
|
||||
{
|
||||
self.x = Mathf.Approximately(self.x, 0) ? 1 : 1 / self.x;
|
||||
self.y = Mathf.Approximately(self.y, 0) ? 1 : 1 / self.y;
|
||||
self.z = Mathf.Approximately(self.z, 0) ? 1 : 1 / self.z;
|
||||
return self;
|
||||
}
|
||||
|
||||
public static Vector3 GetScaled(this Vector3 self, Vector3 other1)
|
||||
{
|
||||
self.Scale(other1);
|
||||
return self;
|
||||
}
|
||||
|
||||
public static Vector3 GetScaled(this Vector3 self, Vector3 other1, Vector3 other2)
|
||||
{
|
||||
self.Scale(other1);
|
||||
self.Scale(other2);
|
||||
return self;
|
||||
}
|
||||
|
||||
public static Vector3 GetScaled(this Vector3 self, Vector3 other1, Vector3 other2, Vector3 other3)
|
||||
{
|
||||
self.Scale(other1);
|
||||
self.Scale(other2);
|
||||
self.Scale(other3);
|
||||
return self;
|
||||
}
|
||||
|
||||
public static bool IsVisible(this Vector3 self)
|
||||
{
|
||||
return 0 < Mathf.Abs(self.x * self.y * self.z);
|
||||
}
|
||||
|
||||
public static bool IsVisible2D(this Vector3 self)
|
||||
{
|
||||
return 0 < Mathf.Abs(self.x * self.y);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 6a7b5fb989e4b48c8bc7ecce834060f5
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
8
Packages/src/Runtime/Internal/ProjectSettings.meta
Normal file
8
Packages/src/Runtime/Internal/ProjectSettings.meta
Normal file
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 398e06c9985ad4291a95f0749c2927fb
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,242 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using UnityEngine;
|
||||
using Object = UnityEngine.Object;
|
||||
#if UNITY_EDITOR
|
||||
using System.IO;
|
||||
using UnityEditor;
|
||||
using UnityEditor.Build;
|
||||
using UnityEditor.Build.Reporting;
|
||||
#endif
|
||||
|
||||
namespace Coffee.UIParticleInternal
|
||||
{
|
||||
public abstract class PreloadedProjectSettings : ScriptableObject
|
||||
#if UNITY_EDITOR
|
||||
{
|
||||
private class Postprocessor : AssetPostprocessor
|
||||
{
|
||||
private static void OnPostprocessAllAssets(string[] _, string[] __, string[] ___, string[] ____)
|
||||
{
|
||||
Initialize();
|
||||
}
|
||||
}
|
||||
|
||||
private class PreprocessBuildWithReport : IPreprocessBuildWithReport
|
||||
{
|
||||
int IOrderedCallback.callbackOrder => 0;
|
||||
|
||||
void IPreprocessBuildWithReport.OnPreprocessBuild(BuildReport report)
|
||||
{
|
||||
Initialize();
|
||||
}
|
||||
}
|
||||
|
||||
private static void Initialize()
|
||||
{
|
||||
foreach (var t in TypeCache.GetTypesDerivedFrom(typeof(PreloadedProjectSettings<>)))
|
||||
{
|
||||
var defaultSettings = GetDefaultSettings(t);
|
||||
if (!defaultSettings)
|
||||
{
|
||||
// When create a new instance, automatically set it as default settings.
|
||||
defaultSettings = CreateInstance(t) as PreloadedProjectSettings;
|
||||
SetDefaultSettings(defaultSettings);
|
||||
}
|
||||
else if (GetPreloadedSettings(t).Length != 1)
|
||||
{
|
||||
SetDefaultSettings(defaultSettings);
|
||||
}
|
||||
|
||||
if (defaultSettings)
|
||||
{
|
||||
defaultSettings.OnInitialize();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected static string GetDefaultName(Type type, bool nicify)
|
||||
{
|
||||
var typeName = type.Name;
|
||||
return nicify
|
||||
? ObjectNames.NicifyVariableName(typeName)
|
||||
: typeName;
|
||||
}
|
||||
|
||||
private static Object[] GetPreloadedSettings(Type type)
|
||||
{
|
||||
return PlayerSettings.GetPreloadedAssets()
|
||||
.Where(x => x && x.GetType() == type)
|
||||
.ToArray();
|
||||
}
|
||||
|
||||
protected static PreloadedProjectSettings GetDefaultSettings(Type type)
|
||||
{
|
||||
return GetPreloadedSettings(type).FirstOrDefault() as PreloadedProjectSettings
|
||||
?? AssetDatabase.FindAssets($"t:{nameof(PreloadedProjectSettings)}")
|
||||
.Select(AssetDatabase.GUIDToAssetPath)
|
||||
.Select(AssetDatabase.LoadAssetAtPath<PreloadedProjectSettings>)
|
||||
.FirstOrDefault(x => x && x.GetType() == type);
|
||||
}
|
||||
|
||||
protected static void SetDefaultSettings(PreloadedProjectSettings asset)
|
||||
{
|
||||
if (!asset) return;
|
||||
|
||||
var type = asset.GetType();
|
||||
if (string.IsNullOrEmpty(AssetDatabase.GetAssetPath(asset)))
|
||||
{
|
||||
if (!AssetDatabase.IsValidFolder("Assets/ProjectSettings"))
|
||||
{
|
||||
AssetDatabase.CreateFolder("Assets", "ProjectSettings");
|
||||
}
|
||||
|
||||
var assetPath = $"Assets/ProjectSettings/{GetDefaultName(type, false)}.asset";
|
||||
assetPath = AssetDatabase.GenerateUniqueAssetPath(assetPath);
|
||||
if (!File.Exists(assetPath))
|
||||
{
|
||||
AssetDatabase.CreateAsset(asset, assetPath);
|
||||
asset.OnCreateAsset();
|
||||
}
|
||||
}
|
||||
|
||||
var preloadedAssets = PlayerSettings.GetPreloadedAssets();
|
||||
var projectSettings = GetPreloadedSettings(type);
|
||||
PlayerSettings.SetPreloadedAssets(preloadedAssets
|
||||
.Where(x => x)
|
||||
.Except(projectSettings.Except(new[] { asset }))
|
||||
.Append(asset)
|
||||
.Distinct()
|
||||
.ToArray());
|
||||
|
||||
AssetDatabase.Refresh();
|
||||
}
|
||||
|
||||
protected virtual void OnCreateAsset()
|
||||
{
|
||||
}
|
||||
|
||||
protected virtual void OnInitialize()
|
||||
{
|
||||
}
|
||||
}
|
||||
#else
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
||||
public abstract class PreloadedProjectSettings<T> : PreloadedProjectSettings
|
||||
where T : PreloadedProjectSettings<T>
|
||||
{
|
||||
private static T s_Instance;
|
||||
|
||||
#if UNITY_EDITOR
|
||||
private string _jsonText;
|
||||
|
||||
public static bool hasInstance => s_Instance;
|
||||
|
||||
public static T instance
|
||||
{
|
||||
get
|
||||
{
|
||||
if (s_Instance) return s_Instance;
|
||||
|
||||
s_Instance = GetDefaultSettings(typeof(T)) as T;
|
||||
if (s_Instance) return s_Instance;
|
||||
|
||||
s_Instance = CreateInstance<T>();
|
||||
if (!s_Instance)
|
||||
{
|
||||
s_Instance = null;
|
||||
return s_Instance;
|
||||
}
|
||||
|
||||
SetDefaultSettings(s_Instance);
|
||||
return s_Instance;
|
||||
}
|
||||
}
|
||||
|
||||
private void OnPlayModeStateChanged(PlayModeStateChange state)
|
||||
{
|
||||
switch (state)
|
||||
{
|
||||
case PlayModeStateChange.ExitingEditMode:
|
||||
_jsonText = EditorJsonUtility.ToJson(this);
|
||||
break;
|
||||
case PlayModeStateChange.ExitingPlayMode:
|
||||
if (_jsonText != null)
|
||||
{
|
||||
EditorJsonUtility.FromJsonOverwrite(_jsonText, this);
|
||||
_jsonText = null;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
#else
|
||||
public static T instance => s_Instance ? s_Instance : s_Instance = CreateInstance<T>();
|
||||
#endif
|
||||
|
||||
/// <summary>
|
||||
/// This function is called when the object becomes enabled and active.
|
||||
/// </summary>
|
||||
protected virtual void OnEnable()
|
||||
{
|
||||
#if UNITY_EDITOR
|
||||
var isDefaultSettings = !s_Instance || s_Instance == this || GetDefaultSettings(typeof(T)) == this;
|
||||
if (!isDefaultSettings)
|
||||
{
|
||||
DestroyImmediate(this, true);
|
||||
return;
|
||||
}
|
||||
|
||||
EditorApplication.playModeStateChanged += OnPlayModeStateChanged;
|
||||
#endif
|
||||
|
||||
if (s_Instance) return;
|
||||
s_Instance = this as T;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This function is called when the behaviour becomes disabled.
|
||||
/// </summary>
|
||||
protected virtual void OnDisable()
|
||||
{
|
||||
#if UNITY_EDITOR
|
||||
EditorApplication.playModeStateChanged -= OnPlayModeStateChanged;
|
||||
#endif
|
||||
if (s_Instance != this) return;
|
||||
|
||||
s_Instance = null;
|
||||
}
|
||||
|
||||
#if UNITY_EDITOR
|
||||
protected sealed class PreloadedProjectSettingsProvider : SettingsProvider
|
||||
{
|
||||
private Editor _editor;
|
||||
private PreloadedProjectSettings<T> _target;
|
||||
|
||||
public PreloadedProjectSettingsProvider(string path) : base(path, SettingsScope.Project)
|
||||
{
|
||||
}
|
||||
|
||||
public override void OnGUI(string searchContext)
|
||||
{
|
||||
if (!_target)
|
||||
{
|
||||
if (_editor)
|
||||
{
|
||||
DestroyImmediate(_editor);
|
||||
_editor = null;
|
||||
}
|
||||
|
||||
_target = instance;
|
||||
_editor = Editor.CreateEditor(_target);
|
||||
}
|
||||
|
||||
_editor.OnInspectorGUI();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 790ea008741dc411497c8794745319eb
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
8
Packages/src/Runtime/Internal/Utilities.meta
Normal file
8
Packages/src/Runtime/Internal/Utilities.meta
Normal file
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 1b2877595f27c4a70a426991d515434f
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
89
Packages/src/Runtime/Internal/Utilities/FastAction.cs
Executable file
89
Packages/src/Runtime/Internal/Utilities/FastAction.cs
Executable file
@@ -0,0 +1,89 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Profiling;
|
||||
|
||||
namespace Coffee.UIParticleInternal
|
||||
{
|
||||
/// <summary>
|
||||
/// Base class for a fast action.
|
||||
/// </summary>
|
||||
internal class FastActionBase<T>
|
||||
{
|
||||
private static readonly InternalObjectPool<LinkedListNode<T>> s_NodePool =
|
||||
new InternalObjectPool<LinkedListNode<T>>(() => new LinkedListNode<T>(default), _ => true,
|
||||
x => x.Value = default);
|
||||
|
||||
private readonly LinkedList<T> _delegates = new LinkedList<T>();
|
||||
|
||||
/// <summary>
|
||||
/// Adds a delegate to the action.
|
||||
/// </summary>
|
||||
public void Add(T rhs)
|
||||
{
|
||||
if (rhs == null) return;
|
||||
Profiler.BeginSample("(COF)[FastAction] Add Action");
|
||||
var node = s_NodePool.Rent();
|
||||
node.Value = rhs;
|
||||
_delegates.AddLast(node);
|
||||
Profiler.EndSample();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Removes a delegate from the action.
|
||||
/// </summary>
|
||||
public void Remove(T rhs)
|
||||
{
|
||||
if (rhs == null) return;
|
||||
Profiler.BeginSample("(COF)[FastAction] Remove Action");
|
||||
var node = _delegates.Find(rhs);
|
||||
if (node != null)
|
||||
{
|
||||
_delegates.Remove(node);
|
||||
s_NodePool.Return(ref node);
|
||||
}
|
||||
|
||||
Profiler.EndSample();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Invokes the action with a callback function.
|
||||
/// </summary>
|
||||
protected void Invoke(Action<T> callback)
|
||||
{
|
||||
var node = _delegates.First;
|
||||
while (node != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
callback(node.Value);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Debug.LogException(e);
|
||||
}
|
||||
|
||||
node = node.Next;
|
||||
}
|
||||
}
|
||||
|
||||
public void Clear()
|
||||
{
|
||||
_delegates.Clear();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// A fast action without parameters.
|
||||
/// </summary>
|
||||
internal class FastAction : FastActionBase<Action>
|
||||
{
|
||||
/// <summary>
|
||||
/// Invoke all the registered delegates.
|
||||
/// </summary>
|
||||
public void Invoke()
|
||||
{
|
||||
Invoke(action => action.Invoke());
|
||||
}
|
||||
}
|
||||
}
|
||||
11
Packages/src/Runtime/Internal/Utilities/FastAction.cs.meta
Normal file
11
Packages/src/Runtime/Internal/Utilities/FastAction.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: a7c8c268a827b4787a8e050f1fe95ad5
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
101
Packages/src/Runtime/Internal/Utilities/FrameCache.cs
Normal file
101
Packages/src/Runtime/Internal/Utilities/FrameCache.cs
Normal file
@@ -0,0 +1,101 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Coffee.UIParticleInternal
|
||||
{
|
||||
internal static class FrameCache
|
||||
{
|
||||
private static readonly Dictionary<Type, IFrameCache> s_Caches = new Dictionary<Type, IFrameCache>();
|
||||
|
||||
static FrameCache()
|
||||
{
|
||||
s_Caches.Clear();
|
||||
UIExtraCallbacks.onLateAfterCanvasRebuild += ClearAllCache;
|
||||
}
|
||||
|
||||
#if UNITY_EDITOR
|
||||
[RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.SubsystemRegistration)]
|
||||
private static void Clear()
|
||||
{
|
||||
s_Caches.Clear();
|
||||
}
|
||||
#endif
|
||||
|
||||
/// <summary>
|
||||
/// Tries to retrieve a value from the frame cache with a specified key.
|
||||
/// </summary>
|
||||
public static bool TryGet<T>(object key1, string key2, out T result)
|
||||
{
|
||||
return GetFrameCache<T>().TryGet((key1.GetHashCode(), key2.GetHashCode()), out result);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tries to retrieve a value from the frame cache with a specified key.
|
||||
/// </summary>
|
||||
public static bool TryGet<T>(object key1, string key2, int key3, out T result)
|
||||
{
|
||||
return GetFrameCache<T>().TryGet((key1.GetHashCode(), key2.GetHashCode() + key3), out result);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets a value in the frame cache with a specified key.
|
||||
/// </summary>
|
||||
public static void Set<T>(object key1, string key2, T result)
|
||||
{
|
||||
GetFrameCache<T>().Set((key1.GetHashCode(), key2.GetHashCode()), result);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets a value in the frame cache with a specified key.
|
||||
/// </summary>
|
||||
public static void Set<T>(object key1, string key2, int key3, T result)
|
||||
{
|
||||
GetFrameCache<T>().Set((key1.GetHashCode(), key2.GetHashCode() + key3), result);
|
||||
}
|
||||
|
||||
private static void ClearAllCache()
|
||||
{
|
||||
foreach (var cache in s_Caches.Values)
|
||||
{
|
||||
cache.Clear();
|
||||
}
|
||||
}
|
||||
|
||||
private static FrameCacheContainer<T> GetFrameCache<T>()
|
||||
{
|
||||
var t = typeof(T);
|
||||
if (s_Caches.TryGetValue(t, out var frameCache)) return frameCache as FrameCacheContainer<T>;
|
||||
|
||||
frameCache = new FrameCacheContainer<T>();
|
||||
s_Caches.Add(t, frameCache);
|
||||
|
||||
return (FrameCacheContainer<T>)frameCache;
|
||||
}
|
||||
|
||||
private interface IFrameCache
|
||||
{
|
||||
void Clear();
|
||||
}
|
||||
|
||||
private class FrameCacheContainer<T> : IFrameCache
|
||||
{
|
||||
private readonly Dictionary<(int, int), T> _caches = new Dictionary<(int, int), T>();
|
||||
|
||||
public void Clear()
|
||||
{
|
||||
_caches.Clear();
|
||||
}
|
||||
|
||||
public bool TryGet((int, int) key, out T result)
|
||||
{
|
||||
return _caches.TryGetValue(key, out result);
|
||||
}
|
||||
|
||||
public void Set((int, int) key, T result)
|
||||
{
|
||||
_caches[key] = result;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
11
Packages/src/Runtime/Internal/Utilities/FrameCache.cs.meta
Normal file
11
Packages/src/Runtime/Internal/Utilities/FrameCache.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 5f129e3b07ffb4d3bbb4cc5f6bd94087
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
254
Packages/src/Runtime/Internal/Utilities/Logging.cs
Normal file
254
Packages/src/Runtime/Internal/Utilities/Logging.cs
Normal file
@@ -0,0 +1,254 @@
|
||||
using System;
|
||||
using System.Text;
|
||||
using UnityEngine;
|
||||
using Object = UnityEngine.Object;
|
||||
#if ENABLE_COFFEE_LOGGER
|
||||
using System.Reflection;
|
||||
using System.Collections.Generic;
|
||||
#else
|
||||
using Conditional = System.Diagnostics.ConditionalAttribute;
|
||||
#endif
|
||||
|
||||
namespace Coffee.UIParticleInternal
|
||||
{
|
||||
internal static class Logging
|
||||
{
|
||||
#if !ENABLE_COFFEE_LOGGER
|
||||
private const string k_DisableSymbol = "DISABLE_COFFEE_LOGGER";
|
||||
|
||||
[Conditional(k_DisableSymbol)]
|
||||
#endif
|
||||
private static void Log_Internal(LogType type, object tag, object message, Object context)
|
||||
{
|
||||
#if ENABLE_COFFEE_LOGGER
|
||||
AppendTag(s_Sb, tag);
|
||||
s_Sb.Append(message);
|
||||
switch (type)
|
||||
{
|
||||
case LogType.Error:
|
||||
case LogType.Assert:
|
||||
case LogType.Exception:
|
||||
Debug.LogError(s_Sb, context);
|
||||
break;
|
||||
case LogType.Warning:
|
||||
Debug.LogWarning(s_Sb, context);
|
||||
break;
|
||||
case LogType.Log:
|
||||
Debug.Log(s_Sb, context);
|
||||
break;
|
||||
}
|
||||
|
||||
s_Sb.Length = 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
#if !ENABLE_COFFEE_LOGGER
|
||||
[Conditional(k_DisableSymbol)]
|
||||
#endif
|
||||
public static void LogIf(bool enable, object tag, object message, Object context = null)
|
||||
{
|
||||
if (!enable) return;
|
||||
Log_Internal(LogType.Log, tag, message, context ? context : tag as Object);
|
||||
}
|
||||
|
||||
#if !ENABLE_COFFEE_LOGGER
|
||||
[Conditional(k_DisableSymbol)]
|
||||
#endif
|
||||
public static void Log(object tag, object message, Object context = null)
|
||||
{
|
||||
Log_Internal(LogType.Log, tag, message, context ? context : tag as Object);
|
||||
}
|
||||
|
||||
#if !ENABLE_COFFEE_LOGGER
|
||||
[Conditional(k_DisableSymbol)]
|
||||
#endif
|
||||
public static void LogWarning(object tag, object message, Object context = null)
|
||||
{
|
||||
Log_Internal(LogType.Warning, tag, message, context ? context : tag as Object);
|
||||
}
|
||||
|
||||
public static void LogError(object tag, object message, Object context = null)
|
||||
{
|
||||
#if ENABLE_COFFEE_LOGGER
|
||||
Log_Internal(LogType.Error, tag, message, context ? context : tag as Object);
|
||||
#else
|
||||
Debug.LogError($"{tag}: {message}", context);
|
||||
#endif
|
||||
}
|
||||
|
||||
#if !ENABLE_COFFEE_LOGGER
|
||||
[Conditional(k_DisableSymbol)]
|
||||
#endif
|
||||
public static void LogMulticast(Type type, string fieldName, object instance = null, string message = null)
|
||||
{
|
||||
#if ENABLE_COFFEE_LOGGER
|
||||
AppendTag(s_Sb, instance ?? type);
|
||||
|
||||
var handler = type
|
||||
.GetField(fieldName,
|
||||
BindingFlags.Static | BindingFlags.Instance | BindingFlags.Static | BindingFlags.NonPublic)
|
||||
?.GetValue(instance);
|
||||
|
||||
var list = ((MulticastDelegate)handler)?.GetInvocationList() ?? Array.Empty<Delegate>();
|
||||
s_Sb.Append("<color=orange>");
|
||||
s_Sb.Append(type.Name);
|
||||
s_Sb.Append(".");
|
||||
s_Sb.Append(fieldName);
|
||||
s_Sb.Append(" has ");
|
||||
s_Sb.Append(list.Length);
|
||||
s_Sb.Append(" callbacks");
|
||||
if (message != null)
|
||||
{
|
||||
s_Sb.Append(" (");
|
||||
s_Sb.Append(message);
|
||||
s_Sb.Append(")");
|
||||
}
|
||||
|
||||
s_Sb.Append(":</color>");
|
||||
|
||||
for (var i = 0; i < list.Length; i++)
|
||||
{
|
||||
s_Sb.Append("\n - ");
|
||||
s_Sb.Append(list[i].Method.DeclaringType?.Name);
|
||||
s_Sb.Append(".");
|
||||
s_Sb.Append(list[i].Method.Name);
|
||||
}
|
||||
|
||||
Debug.Log(s_Sb);
|
||||
s_Sb.Length = 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
#if !ENABLE_COFFEE_LOGGER
|
||||
[Conditional(k_DisableSymbol)]
|
||||
#endif
|
||||
private static void AppendTag(StringBuilder sb, object tag)
|
||||
{
|
||||
#if ENABLE_COFFEE_LOGGER
|
||||
try
|
||||
{
|
||||
sb.Append("f");
|
||||
sb.Append(Time.frameCount);
|
||||
sb.Append(":<color=#");
|
||||
AppendReadableCode(sb, tag);
|
||||
sb.Append("><b>[");
|
||||
|
||||
switch (tag)
|
||||
{
|
||||
case string name:
|
||||
sb.Append(name);
|
||||
break;
|
||||
case Type type:
|
||||
AppendType(sb, type);
|
||||
break;
|
||||
case Object uObject:
|
||||
AppendType(sb, tag.GetType());
|
||||
sb.Append(" #");
|
||||
sb.Append(uObject.name);
|
||||
break;
|
||||
default:
|
||||
AppendType(sb, tag.GetType());
|
||||
break;
|
||||
}
|
||||
|
||||
sb.Append("]</b></color> ");
|
||||
}
|
||||
catch
|
||||
{
|
||||
sb.Append("f");
|
||||
sb.Append(Time.frameCount);
|
||||
sb.Append(":<b>[");
|
||||
sb.Append(tag);
|
||||
sb.Append("]</b> ");
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
#if !ENABLE_COFFEE_LOGGER
|
||||
[Conditional(k_DisableSymbol)]
|
||||
#endif
|
||||
private static void AppendType(StringBuilder sb, Type type)
|
||||
{
|
||||
#if ENABLE_COFFEE_LOGGER
|
||||
if (s_TypeNameCache.TryGetValue(type, out var name))
|
||||
{
|
||||
sb.Append(name);
|
||||
return;
|
||||
}
|
||||
|
||||
// New type found
|
||||
var start = sb.Length;
|
||||
if (0 < start && sb[start - 1] == '<' && (type.Name == "Material" || type.Name == "Color"))
|
||||
{
|
||||
sb.Append('@');
|
||||
}
|
||||
|
||||
sb.Append(type.Name);
|
||||
if (type.IsGenericType)
|
||||
{
|
||||
sb.Length -= 2;
|
||||
sb.Append("<");
|
||||
foreach (var gType in type.GetGenericArguments())
|
||||
{
|
||||
AppendType(sb, gType);
|
||||
sb.Append(", ");
|
||||
}
|
||||
|
||||
sb.Length -= 2;
|
||||
sb.Append(">");
|
||||
}
|
||||
|
||||
s_TypeNameCache.Add(type, sb.ToString(start, sb.Length - start));
|
||||
#endif
|
||||
}
|
||||
|
||||
#if !ENABLE_COFFEE_LOGGER
|
||||
[Conditional(k_DisableSymbol)]
|
||||
#endif
|
||||
private static void AppendReadableCode(StringBuilder sb, object tag)
|
||||
{
|
||||
#if ENABLE_COFFEE_LOGGER
|
||||
int hash;
|
||||
try
|
||||
{
|
||||
switch (tag)
|
||||
{
|
||||
case string text:
|
||||
hash = text.GetHashCode();
|
||||
break;
|
||||
case Type type:
|
||||
type = type.IsGenericType ? type.GetGenericTypeDefinition() : type;
|
||||
hash = type.FullName?.GetHashCode() ?? 0;
|
||||
break;
|
||||
default:
|
||||
hash = tag.GetType().FullName?.GetHashCode() ?? 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
sb.Append("FFFFFF");
|
||||
return;
|
||||
}
|
||||
|
||||
hash = hash & (s_Codes.Length - 1);
|
||||
if (s_Codes[hash] == null)
|
||||
{
|
||||
var hue = hash / (float)s_Codes.Length;
|
||||
var modifier = 1f - Mathf.Clamp01(Mathf.Abs(hue - 0.65f) / 0.2f);
|
||||
var saturation = 0.7f + modifier * -0.2f;
|
||||
var value = 0.8f + modifier * 0.3f;
|
||||
s_Codes[hash] = ColorUtility.ToHtmlStringRGB(Color.HSVToRGB(hue, saturation, value));
|
||||
}
|
||||
|
||||
sb.Append(s_Codes[hash]);
|
||||
#endif
|
||||
}
|
||||
|
||||
#if ENABLE_COFFEE_LOGGER
|
||||
private static readonly StringBuilder s_Sb = new StringBuilder();
|
||||
private static readonly string[] s_Codes = new string[64];
|
||||
private static readonly Dictionary<Type, string> s_TypeNameCache = new Dictionary<Type, string>();
|
||||
#endif
|
||||
}
|
||||
}
|
||||
11
Packages/src/Runtime/Internal/Utilities/Logging.cs.meta
Normal file
11
Packages/src/Runtime/Internal/Utilities/Logging.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 8255313895da84e7cbdc876be3795334
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,92 @@
|
||||
using System;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Profiling;
|
||||
|
||||
namespace Coffee.UIParticleInternal
|
||||
{
|
||||
/// <summary>
|
||||
/// Provides functionality to manage materials.
|
||||
/// </summary>
|
||||
internal static class MaterialRepository
|
||||
{
|
||||
private static readonly ObjectRepository<Material> s_Repository = new ObjectRepository<Material>();
|
||||
|
||||
public static int count => s_Repository.count;
|
||||
|
||||
#if UNITY_EDITOR
|
||||
[RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.SubsystemRegistration)]
|
||||
public static void Clear()
|
||||
{
|
||||
s_Repository.Clear();
|
||||
}
|
||||
#endif
|
||||
|
||||
/// <summary>
|
||||
/// Retrieves a cached material based on the hash.
|
||||
/// </summary>
|
||||
public static bool Valid(Hash128 hash, Material material)
|
||||
{
|
||||
Profiler.BeginSample("(COF)[MaterialRegistry] Valid");
|
||||
var ret = s_Repository.Valid(hash, material);
|
||||
Profiler.EndSample();
|
||||
return ret;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds or retrieves a cached material based on the hash.
|
||||
/// </summary>
|
||||
public static void Get(Hash128 hash, ref Material material, Func<Material> onCreate)
|
||||
{
|
||||
Profiler.BeginSample("(COF)[MaterialRepository] Get");
|
||||
s_Repository.Get(hash, ref material, onCreate);
|
||||
Profiler.EndSample();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds or retrieves a cached material based on the hash.
|
||||
/// </summary>
|
||||
public static void Get(Hash128 hash, ref Material material, string shaderName)
|
||||
{
|
||||
Profiler.BeginSample("(COF)[MaterialRepository] Get");
|
||||
s_Repository.Get(hash, ref material, x => new Material(Shader.Find(x))
|
||||
{
|
||||
hideFlags = HideFlags.DontSave | HideFlags.NotEditable
|
||||
}, shaderName);
|
||||
Profiler.EndSample();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds or retrieves a cached material based on the hash.
|
||||
/// </summary>
|
||||
public static void Get(Hash128 hash, ref Material material, string shaderName, string[] keywords)
|
||||
{
|
||||
Profiler.BeginSample("(COF)[MaterialRepository] Get");
|
||||
s_Repository.Get(hash, ref material, x => new Material(Shader.Find(x.shaderName))
|
||||
{
|
||||
hideFlags = HideFlags.DontSave | HideFlags.NotEditable,
|
||||
shaderKeywords = x.keywords
|
||||
}, (shaderName, keywords));
|
||||
Profiler.EndSample();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds or retrieves a cached material based on the hash.
|
||||
/// </summary>
|
||||
public static void Get<T>(Hash128 hash, ref Material material, Func<T, Material> onCreate, T source)
|
||||
{
|
||||
Profiler.BeginSample("(COF)[MaterialRepository] Get");
|
||||
s_Repository.Get(hash, ref material, onCreate, source);
|
||||
Profiler.EndSample();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Removes a soft mask material from the cache.
|
||||
/// </summary>
|
||||
public static void Release(ref Material material)
|
||||
{
|
||||
Profiler.BeginSample("(COF)[MaterialRepository] Release");
|
||||
s_Repository.Release(ref material);
|
||||
Profiler.EndSample();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 702912f2ee2ec49bb8003a64151ae4f7
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
76
Packages/src/Runtime/Internal/Utilities/Misc.cs
Normal file
76
Packages/src/Runtime/Internal/Utilities/Misc.cs
Normal file
@@ -0,0 +1,76 @@
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
using Object = UnityEngine.Object;
|
||||
#if UNITY_EDITOR && UNITY_2021_2_OR_NEWER
|
||||
using UnityEditor.SceneManagement;
|
||||
#elif UNITY_EDITOR
|
||||
using UnityEditor.Experimental.SceneManagement;
|
||||
#endif
|
||||
|
||||
namespace Coffee.UIParticleInternal
|
||||
{
|
||||
internal static class Misc
|
||||
{
|
||||
public static T[] FindObjectsOfType<T>() where T : Object
|
||||
{
|
||||
#if UNITY_2023_1_OR_NEWER
|
||||
return Object.FindObjectsByType<T>(FindObjectsInactive.Include, FindObjectsSortMode.None);
|
||||
#else
|
||||
return Object.FindObjectsOfType<T>();
|
||||
#endif
|
||||
}
|
||||
|
||||
public static void Destroy(Object obj)
|
||||
{
|
||||
if (!obj) return;
|
||||
#if UNITY_EDITOR
|
||||
if (!Application.isPlaying)
|
||||
{
|
||||
Object.DestroyImmediate(obj);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
Object.Destroy(obj);
|
||||
}
|
||||
}
|
||||
|
||||
public static void DestroyImmediate(Object obj)
|
||||
{
|
||||
if (!obj) return;
|
||||
#if UNITY_EDITOR
|
||||
if (Application.isEditor)
|
||||
{
|
||||
Object.DestroyImmediate(obj);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
Object.Destroy(obj);
|
||||
}
|
||||
}
|
||||
|
||||
[Conditional("UNITY_EDITOR")]
|
||||
public static void SetDirty(Object obj)
|
||||
{
|
||||
#if UNITY_EDITOR
|
||||
if (!obj) return;
|
||||
EditorUtility.SetDirty(obj);
|
||||
#endif
|
||||
}
|
||||
|
||||
#if UNITY_EDITOR
|
||||
public static T[] GetAllComponentsInPrefabStage<T>() where T : Component
|
||||
{
|
||||
var prefabStage = PrefabStageUtility.GetCurrentPrefabStage();
|
||||
if (prefabStage == null) return Array.Empty<T>();
|
||||
|
||||
return prefabStage.prefabContentsRoot.GetComponentsInChildren<T>(true);
|
||||
}
|
||||
|
||||
public static bool isBatchOrBuilding => Application.isBatchMode || BuildPipeline.isBuildingPlayer;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
11
Packages/src/Runtime/Internal/Utilities/Misc.cs.meta
Normal file
11
Packages/src/Runtime/Internal/Utilities/Misc.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 182319ecc315e4858b119764af0fbcb0
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
154
Packages/src/Runtime/Internal/Utilities/ObjectPool.cs
Normal file
154
Packages/src/Runtime/Internal/Utilities/ObjectPool.cs
Normal file
@@ -0,0 +1,154 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Coffee.UIParticleInternal
|
||||
{
|
||||
/// <summary>
|
||||
/// Object pool.
|
||||
/// </summary>
|
||||
internal class InternalObjectPool<T> where T : class
|
||||
{
|
||||
#if UNITY_2021_1_OR_NEWER
|
||||
private readonly Predicate<T> _onValid; // Delegate for checking if instances are valid
|
||||
private readonly UnityEngine.Pool.ObjectPool<T> _pool;
|
||||
|
||||
public InternalObjectPool(Func<T> onCreate, Predicate<T> onValid, Action<T> onReturn)
|
||||
{
|
||||
_pool = new UnityEngine.Pool.ObjectPool<T>(onCreate, null, onReturn);
|
||||
_onValid = onValid;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Rent an instance from the pool.
|
||||
/// When you no longer need it, return it with <see cref="Return" />.
|
||||
/// </summary>
|
||||
public T Rent()
|
||||
{
|
||||
while (0 < _pool.CountInactive)
|
||||
{
|
||||
var instance = _pool.Get();
|
||||
if (_onValid(instance))
|
||||
{
|
||||
return instance;
|
||||
}
|
||||
}
|
||||
|
||||
// If there are no instances in the pool, create a new one.
|
||||
Logging.Log(this, $"A new instance is created (pooled: {_pool.CountInactive}, created: {_pool.CountAll}).");
|
||||
return _pool.Get();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Return an instance to the pool and assign null.
|
||||
/// Be sure to return the instance obtained with <see cref="Rent" /> with this method.
|
||||
/// </summary>
|
||||
public void Return(ref T instance)
|
||||
{
|
||||
if (instance == null) return; // Ignore if already pooled or null.
|
||||
|
||||
_pool.Release(instance);
|
||||
Logging.Log(this, $"An instance is released (pooled: {_pool.CountInactive}, created: {_pool.CountAll}).");
|
||||
instance = default; // Set the reference to null.
|
||||
}
|
||||
#else
|
||||
private readonly Func<T> _onCreate; // Delegate for creating instances
|
||||
private readonly Action<T> _onReturn; // Delegate for returning instances to the pool
|
||||
private readonly Predicate<T> _onValid; // Delegate for checking if instances are valid
|
||||
private readonly Stack<T> _pool = new Stack<T>(32); // Object pool
|
||||
private int _count; // Total count of created instances
|
||||
|
||||
public InternalObjectPool(Func<T> onCreate, Predicate<T> onValid, Action<T> onReturn)
|
||||
{
|
||||
_onCreate = onCreate;
|
||||
_onValid = onValid;
|
||||
_onReturn = onReturn;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Rent an instance from the pool.
|
||||
/// When you no longer need it, return it with <see cref="Return" />.
|
||||
/// </summary>
|
||||
public T Rent()
|
||||
{
|
||||
while (0 < _pool.Count)
|
||||
{
|
||||
var instance = _pool.Pop();
|
||||
if (_onValid(instance))
|
||||
{
|
||||
return instance;
|
||||
}
|
||||
}
|
||||
|
||||
// If there are no instances in the pool, create a new one.
|
||||
Logging.Log(this, $"A new instance is created (pooled: {_pool.Count}, created: {++_count}).");
|
||||
return _onCreate();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Return an instance to the pool and assign null.
|
||||
/// Be sure to return the instance obtained with <see cref="Rent" /> with this method.
|
||||
/// </summary>
|
||||
public void Return(ref T instance)
|
||||
{
|
||||
if (instance == null || _pool.Contains(instance)) return; // Ignore if already pooled or null.
|
||||
|
||||
_onReturn(instance); // Return the instance to the pool.
|
||||
_pool.Push(instance);
|
||||
Logging.Log(this, $"An instance is released (pooled: {_pool.Count}, created: {_count}).");
|
||||
instance = default; // Set the reference to null.
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Object pool for <see cref="List{T}" />.
|
||||
/// </summary>
|
||||
internal static class InternalListPool<T>
|
||||
{
|
||||
#if UNITY_2021_1_OR_NEWER
|
||||
/// <summary>
|
||||
/// Rent an instance from the pool.
|
||||
/// When you no longer need it, return it with <see cref="Return" />.
|
||||
/// </summary>
|
||||
public static List<T> Rent()
|
||||
{
|
||||
return UnityEngine.Pool.ListPool<T>.Get();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Return an instance to the pool and assign null.
|
||||
/// Be sure to return the instance obtained with <see cref="Rent" /> with this method.
|
||||
/// </summary>
|
||||
public static void Return(ref List<T> toRelease)
|
||||
{
|
||||
if (toRelease != null)
|
||||
{
|
||||
UnityEngine.Pool.ListPool<T>.Release(toRelease);
|
||||
}
|
||||
|
||||
toRelease = null;
|
||||
}
|
||||
#else
|
||||
private static readonly InternalObjectPool<List<T>> s_ListPool =
|
||||
new InternalObjectPool<List<T>>(() => new List<T>(), _ => true, x => x.Clear());
|
||||
|
||||
/// <summary>
|
||||
/// Rent an instance from the pool.
|
||||
/// When you no longer need it, return it with <see cref="Return" />.
|
||||
/// </summary>
|
||||
public static List<T> Rent()
|
||||
{
|
||||
return s_ListPool.Rent();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Return an instance to the pool and assign null.
|
||||
/// Be sure to return the instance obtained with <see cref="Rent" /> with this method.
|
||||
/// </summary>
|
||||
public static void Return(ref List<T> toRelease)
|
||||
{
|
||||
s_ListPool.Return(ref toRelease);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
11
Packages/src/Runtime/Internal/Utilities/ObjectPool.cs.meta
Normal file
11
Packages/src/Runtime/Internal/Utilities/ObjectPool.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 632cb1ba34e6a4e80b55a32bb63ca369
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
209
Packages/src/Runtime/Internal/Utilities/ObjectRepository.cs
Normal file
209
Packages/src/Runtime/Internal/Utilities/ObjectRepository.cs
Normal file
@@ -0,0 +1,209 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Profiling;
|
||||
using Object = UnityEngine.Object;
|
||||
|
||||
namespace Coffee.UIParticleInternal
|
||||
{
|
||||
internal class ObjectRepository<T> where T : Object
|
||||
{
|
||||
private readonly Dictionary<Hash128, Entry> _cache = new Dictionary<Hash128, Entry>(8);
|
||||
private readonly Dictionary<int, Hash128> _objectKey = new Dictionary<int, Hash128>(8);
|
||||
private readonly string _name;
|
||||
private readonly Action<T> _onRelease;
|
||||
private readonly Stack<Entry> _pool = new Stack<Entry>(8);
|
||||
|
||||
public ObjectRepository(Action<T> onRelease = null)
|
||||
{
|
||||
_name = $"{typeof(T).Name}Repository";
|
||||
if (onRelease == null)
|
||||
{
|
||||
_onRelease = x =>
|
||||
{
|
||||
#if UNITY_EDITOR
|
||||
if (!Application.isPlaying)
|
||||
{
|
||||
Object.DestroyImmediate(x, false);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
Object.Destroy(x);
|
||||
}
|
||||
};
|
||||
}
|
||||
else
|
||||
{
|
||||
_onRelease = onRelease;
|
||||
}
|
||||
|
||||
for (var i = 0; i < 8; i++)
|
||||
{
|
||||
_pool.Push(new Entry());
|
||||
}
|
||||
}
|
||||
|
||||
public int count => _cache.Count;
|
||||
|
||||
public void Clear()
|
||||
{
|
||||
foreach (var kv in _cache)
|
||||
{
|
||||
var entry = kv.Value;
|
||||
if (entry == null) continue;
|
||||
|
||||
entry.Release(_onRelease);
|
||||
_pool.Push(entry);
|
||||
}
|
||||
|
||||
_cache.Clear();
|
||||
_objectKey.Clear();
|
||||
}
|
||||
|
||||
public bool Valid(Hash128 hash, T obj)
|
||||
{
|
||||
return _cache.TryGetValue(hash, out var entry) && entry.storedObject == obj;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds or retrieves a cached object based on the hash.
|
||||
/// </summary>
|
||||
public void Get(Hash128 hash, ref T obj, Func<T> onCreate)
|
||||
{
|
||||
if (GetFromCache(hash, ref obj)) return;
|
||||
Add(hash, ref obj, onCreate());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds or retrieves a cached object based on the hash.
|
||||
/// </summary>
|
||||
public void Get<TS>(Hash128 hash, ref T obj, Func<TS, T> onCreate, TS source)
|
||||
{
|
||||
if (GetFromCache(hash, ref obj)) return;
|
||||
Add(hash, ref obj, onCreate(source));
|
||||
}
|
||||
|
||||
private bool GetFromCache(Hash128 hash, ref T obj)
|
||||
{
|
||||
// Find existing entry.
|
||||
Profiler.BeginSample("(COF)[ObjectRepository] GetFromCache");
|
||||
if (_cache.TryGetValue(hash, out var entry))
|
||||
{
|
||||
if (!entry.storedObject)
|
||||
{
|
||||
Release(ref entry.storedObject);
|
||||
Profiler.EndSample();
|
||||
return false;
|
||||
}
|
||||
|
||||
if (entry.storedObject != obj)
|
||||
{
|
||||
// if the object is different, release the old one.
|
||||
Release(ref obj);
|
||||
++entry.reference;
|
||||
obj = entry.storedObject;
|
||||
Logging.Log(_name, $"Get(total#{count}): {entry}");
|
||||
}
|
||||
|
||||
Profiler.EndSample();
|
||||
return true;
|
||||
}
|
||||
|
||||
Profiler.EndSample();
|
||||
return false;
|
||||
}
|
||||
|
||||
private void Add(Hash128 hash, ref T obj, T newObject)
|
||||
{
|
||||
if (!newObject)
|
||||
{
|
||||
Release(ref obj);
|
||||
obj = newObject;
|
||||
return;
|
||||
}
|
||||
|
||||
// Create and add a new entry.
|
||||
Profiler.BeginSample("(COF)[ObjectRepository] Add");
|
||||
var newEntry = 0 < _pool.Count ? _pool.Pop() : new Entry();
|
||||
newEntry.storedObject = newObject;
|
||||
newEntry.hash = hash;
|
||||
newEntry.reference = 1;
|
||||
_cache[hash] = newEntry;
|
||||
_objectKey[newObject.GetInstanceID()] = hash;
|
||||
Logging.Log(_name, $"<color=#03c700>Add</color>(total#{count}): {newEntry}");
|
||||
Release(ref obj);
|
||||
obj = newObject;
|
||||
Profiler.EndSample();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Release a object.
|
||||
/// </summary>
|
||||
public void Release(ref T obj)
|
||||
{
|
||||
if (ReferenceEquals(obj, null)) return;
|
||||
|
||||
// Find and release the entry.
|
||||
Profiler.BeginSample("(COF)[ObjectRepository] Release");
|
||||
var id = obj.GetInstanceID();
|
||||
if (_objectKey.TryGetValue(id, out var hash)
|
||||
&& _cache.TryGetValue(hash, out var entry))
|
||||
{
|
||||
entry.reference--;
|
||||
if (entry.reference <= 0 || !entry.storedObject)
|
||||
{
|
||||
Remove(entry);
|
||||
}
|
||||
else
|
||||
{
|
||||
Logging.Log(_name, $"Release(total#{_cache.Count}): {entry}");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Logging.Log(_name, $"Release(total#{_cache.Count}): <color=red>Already released: {obj}</color>");
|
||||
}
|
||||
|
||||
obj = null;
|
||||
Profiler.EndSample();
|
||||
}
|
||||
|
||||
private void Remove(Entry entry)
|
||||
{
|
||||
if (ReferenceEquals(entry, null)) return;
|
||||
|
||||
Profiler.BeginSample("(COF)[ObjectRepository] Remove");
|
||||
_cache.Remove(entry.hash);
|
||||
_objectKey.Remove(entry.storedObject.GetInstanceID());
|
||||
_pool.Push(entry);
|
||||
entry.reference = 0;
|
||||
Logging.Log(_name, $"<color=#f29e03>Remove</color>(total#{_cache.Count}): {entry}");
|
||||
entry.Release(_onRelease);
|
||||
Profiler.EndSample();
|
||||
}
|
||||
|
||||
private class Entry
|
||||
{
|
||||
public Hash128 hash;
|
||||
public int reference;
|
||||
public T storedObject;
|
||||
|
||||
public void Release(Action<T> onRelease)
|
||||
{
|
||||
reference = 0;
|
||||
if (storedObject)
|
||||
{
|
||||
onRelease?.Invoke(storedObject);
|
||||
}
|
||||
|
||||
storedObject = null;
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return $"h{(uint)hash.GetHashCode()} (refs#{reference}), {storedObject}";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: a713d67bdb31e45e296e5f18460717e2
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
115
Packages/src/Runtime/Internal/Utilities/UIExtraCallbacks.cs
Executable file
115
Packages/src/Runtime/Internal/Utilities/UIExtraCallbacks.cs
Executable file
@@ -0,0 +1,115 @@
|
||||
using System;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
|
||||
namespace Coffee.UIParticleInternal
|
||||
{
|
||||
/// <summary>
|
||||
/// Provides additional callbacks related to canvas and UI system.
|
||||
/// </summary>
|
||||
internal static class UIExtraCallbacks
|
||||
{
|
||||
private static bool s_IsInitializedAfterCanvasRebuild;
|
||||
private static readonly FastAction s_AfterCanvasRebuildAction = new FastAction();
|
||||
private static readonly FastAction s_LateAfterCanvasRebuildAction = new FastAction();
|
||||
private static readonly FastAction s_BeforeCanvasRebuildAction = new FastAction();
|
||||
private static readonly FastAction s_OnScreenSizeChangedAction = new FastAction();
|
||||
private static Vector2Int s_LastScreenSize;
|
||||
|
||||
static UIExtraCallbacks()
|
||||
{
|
||||
Canvas.willRenderCanvases += OnBeforeCanvasRebuild;
|
||||
Logging.LogMulticast(typeof(Canvas), "willRenderCanvases", message: "ctor");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Event that occurs after canvas rebuilds.
|
||||
/// </summary>
|
||||
public static event Action onLateAfterCanvasRebuild
|
||||
{
|
||||
add => s_LateAfterCanvasRebuildAction.Add(value);
|
||||
remove => s_LateAfterCanvasRebuildAction.Remove(value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Event that occurs before canvas rebuilds.
|
||||
/// </summary>
|
||||
public static event Action onBeforeCanvasRebuild
|
||||
{
|
||||
add => s_BeforeCanvasRebuildAction.Add(value);
|
||||
remove => s_BeforeCanvasRebuildAction.Remove(value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Event that occurs after canvas rebuilds.
|
||||
/// </summary>
|
||||
public static event Action onAfterCanvasRebuild
|
||||
{
|
||||
add => s_AfterCanvasRebuildAction.Add(value);
|
||||
remove => s_AfterCanvasRebuildAction.Remove(value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Event that occurs when the screen size changes.
|
||||
/// </summary>
|
||||
public static event Action onScreenSizeChanged
|
||||
{
|
||||
add => s_OnScreenSizeChangedAction.Add(value);
|
||||
remove => s_OnScreenSizeChangedAction.Remove(value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes the UIExtraCallbacks to ensure proper event handling.
|
||||
/// </summary>
|
||||
private static void InitializeAfterCanvasRebuild()
|
||||
{
|
||||
if (s_IsInitializedAfterCanvasRebuild) return;
|
||||
s_IsInitializedAfterCanvasRebuild = true;
|
||||
|
||||
CanvasUpdateRegistry.IsRebuildingLayout();
|
||||
Canvas.willRenderCanvases += OnAfterCanvasRebuild;
|
||||
Logging.LogMulticast(typeof(Canvas), "willRenderCanvases",
|
||||
message: "InitializeAfterCanvasRebuild");
|
||||
}
|
||||
|
||||
#if UNITY_EDITOR
|
||||
[InitializeOnLoadMethod]
|
||||
#endif
|
||||
[RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.BeforeSceneLoad)]
|
||||
private static void InitializeOnLoad()
|
||||
{
|
||||
Canvas.willRenderCanvases -= OnAfterCanvasRebuild;
|
||||
s_IsInitializedAfterCanvasRebuild = false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Callback method called before canvas rebuilds.
|
||||
/// </summary>
|
||||
private static void OnBeforeCanvasRebuild()
|
||||
{
|
||||
var screenSize = new Vector2Int(Screen.width, Screen.height);
|
||||
if (s_LastScreenSize != screenSize)
|
||||
{
|
||||
if (s_LastScreenSize != default)
|
||||
{
|
||||
s_OnScreenSizeChangedAction.Invoke();
|
||||
}
|
||||
|
||||
s_LastScreenSize = screenSize;
|
||||
}
|
||||
|
||||
s_BeforeCanvasRebuildAction.Invoke();
|
||||
InitializeAfterCanvasRebuild();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Callback method called after canvas rebuilds.
|
||||
/// </summary>
|
||||
private static void OnAfterCanvasRebuild()
|
||||
{
|
||||
s_AfterCanvasRebuildAction.Invoke();
|
||||
s_LateAfterCanvasRebuildAction.Invoke();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 9ea318e6e3e6c46aa97c72e28230bdc9
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,72 +0,0 @@
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Coffee.UIParticleExtensions
|
||||
{
|
||||
internal class ModifiedMaterial
|
||||
{
|
||||
private static readonly List<MatEntry> s_Entries = new List<MatEntry>();
|
||||
|
||||
public static Material Add(Material baseMat, Texture texture, int id, int props)
|
||||
{
|
||||
MatEntry e;
|
||||
for (var i = 0; i < s_Entries.Count; i++)
|
||||
{
|
||||
e = s_Entries[i];
|
||||
if (e.baseMat != baseMat || e.texture != texture || e.id != id || e.props != props) continue;
|
||||
++e.count;
|
||||
return e.customMat;
|
||||
}
|
||||
|
||||
e = new MatEntry
|
||||
{
|
||||
count = 1,
|
||||
baseMat = baseMat,
|
||||
texture = texture,
|
||||
id = id,
|
||||
props = props,
|
||||
customMat = new Material(baseMat)
|
||||
{
|
||||
name = $"{baseMat.name}_{id}",
|
||||
hideFlags = HideFlags.DontSave | HideFlags.NotEditable,
|
||||
mainTexture = texture ? texture : baseMat.mainTexture
|
||||
}
|
||||
};
|
||||
s_Entries.Add(e);
|
||||
//Debug.LogFormat(">>>> ModifiedMaterial.Add -> count = count:{0}, mat:{1}, tex:{2}, id:{3}", s_Entries.Count, baseMat, texture, id);
|
||||
return e.customMat;
|
||||
}
|
||||
|
||||
public static void Remove(Material customMat)
|
||||
{
|
||||
if (!customMat) return;
|
||||
|
||||
for (var i = 0; i < s_Entries.Count; ++i)
|
||||
{
|
||||
var e = s_Entries[i];
|
||||
if (e.customMat != customMat) continue;
|
||||
if (--e.count == 0)
|
||||
{
|
||||
//Debug.LogFormat(">>>> ModifiedMaterial.Remove -> count:{0}, mat:{1}, tex:{2}, id:{3}", s_Entries.Count - 1, e.customMat, e.texture, e.id);
|
||||
Misc.DestroyImmediate(e.customMat);
|
||||
e.customMat = null;
|
||||
e.baseMat = null;
|
||||
e.texture = null;
|
||||
s_Entries.RemoveAt(i);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private class MatEntry
|
||||
{
|
||||
public Material baseMat;
|
||||
public int count;
|
||||
public Material customMat;
|
||||
public int id;
|
||||
public int props;
|
||||
public Texture texture;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Runtime.CompilerServices;
|
||||
using Coffee.UIParticleExtensions;
|
||||
using Coffee.UIParticleInternal;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Rendering;
|
||||
using UnityEngine.Serialization;
|
||||
@@ -9,6 +9,8 @@ using UnityEngine.UI;
|
||||
using Random = UnityEngine.Random;
|
||||
|
||||
[assembly: InternalsVisibleTo("Coffee.UIParticle.Editor")]
|
||||
[assembly: InternalsVisibleTo("Coffee.UIParticle.PerformanceDemo")]
|
||||
[assembly: InternalsVisibleTo("Coffee.UIParticle.Demo")]
|
||||
|
||||
namespace Coffee.UIExtensions
|
||||
{
|
||||
@@ -44,23 +46,26 @@ namespace Coffee.UIExtensions
|
||||
|
||||
[HideInInspector]
|
||||
[SerializeField]
|
||||
[Obsolete]
|
||||
internal bool m_IsTrail;
|
||||
|
||||
[HideInInspector]
|
||||
[FormerlySerializedAs("m_IgnoreParent")]
|
||||
[SerializeField]
|
||||
[Obsolete]
|
||||
private bool m_IgnoreCanvasScaler;
|
||||
|
||||
[HideInInspector]
|
||||
[SerializeField]
|
||||
private bool m_AbsoluteMode;
|
||||
[Obsolete]
|
||||
internal bool m_AbsoluteMode;
|
||||
|
||||
[Tooltip("Particle effect scale")]
|
||||
[Tooltip("Scale the rendering particles. When the `3D` toggle is enabled, 3D scale (x, y, z) is supported.")]
|
||||
[SerializeField]
|
||||
private Vector3 m_Scale3D = new Vector3(10, 10, 10);
|
||||
|
||||
[Tooltip("Animatable material properties.\n" +
|
||||
"If you want to change the material properties of the ParticleSystem in Animation, enable it.")]
|
||||
[Tooltip("If you want to update material properties (e.g. _MainTex_ST, _Color) in AnimationClip, " +
|
||||
"use this to mark as animatable.")]
|
||||
[SerializeField]
|
||||
internal AnimatableProperty[] m_AnimatableProperties = new AnimatableProperty[0];
|
||||
|
||||
@@ -68,12 +73,13 @@ namespace Coffee.UIExtensions
|
||||
[SerializeField]
|
||||
private List<ParticleSystem> m_Particles = new List<ParticleSystem>();
|
||||
|
||||
[Tooltip("Mesh sharing.\n" +
|
||||
"None: disable mesh sharing.\n" +
|
||||
"Auto: automatically select Primary/Replica.\n" +
|
||||
"Primary: provides particle simulation results to the same group.\n" +
|
||||
[Tooltip("Particle simulation results are shared within the same group. " +
|
||||
"A large number of the same effects can be displayed with a small load.\n" +
|
||||
"None: Disable mesh sharing.\n" +
|
||||
"Auto: Automatically select Primary/Replica.\n" +
|
||||
"Primary: Provides particle simulation results to the same group.\n" +
|
||||
"Primary Simulator: Primary, but do not render the particle (simulation only).\n" +
|
||||
"Replica: render simulation results provided by the primary.")]
|
||||
"Replica: Render simulation results provided by the primary.")]
|
||||
[SerializeField]
|
||||
private MeshSharing m_MeshSharing = MeshSharing.None;
|
||||
|
||||
@@ -85,26 +91,40 @@ namespace Coffee.UIExtensions
|
||||
[SerializeField]
|
||||
private int m_GroupMaxId;
|
||||
|
||||
[Tooltip("Relative: The particles will be emitted from the scaled position of ParticleSystem.\n" +
|
||||
"Absolute: The particles will be emitted from the world position of ParticleSystem.")]
|
||||
[Tooltip("Emission position mode.\n" +
|
||||
"Relative: The particles will be emitted from the scaled position.\n" +
|
||||
"Absolute: The particles will be emitted from the world position.")]
|
||||
[SerializeField]
|
||||
private PositionMode m_PositionMode = PositionMode.Relative;
|
||||
|
||||
[SerializeField]
|
||||
[Tooltip("Prevent the root-Canvas scale from affecting the hierarchy-scaled ParticleSystem.")]
|
||||
private bool m_AutoScaling = true;
|
||||
[Obsolete]
|
||||
internal bool m_AutoScaling;
|
||||
|
||||
[SerializeField]
|
||||
[Tooltip("Transform: Transform.lossyScale (=world scale) will be set to (1, 1, 1)." +
|
||||
"UIParticle: UIParticle.scale will be adjusted.")]
|
||||
[Tooltip(
|
||||
"How to automatically adjust when the Canvas scale is changed by the screen size or reference resolution.\n" +
|
||||
"None: Do nothing.\n" +
|
||||
"Transform: Transform.lossyScale (=world scale) will be set to (1, 1, 1).\n" +
|
||||
"UIParticle: UIParticle.scale will be adjusted.")]
|
||||
private AutoScalingMode m_AutoScalingMode = AutoScalingMode.Transform;
|
||||
|
||||
[SerializeField]
|
||||
[Tooltip("Use a custom view.\n" +
|
||||
"Use this if the particles are not displayed correctly due to min/max particle size.")]
|
||||
private bool m_UseCustomView;
|
||||
|
||||
[SerializeField]
|
||||
[Tooltip("Custom view size.\n" +
|
||||
"Change the bake view size.")]
|
||||
private float m_CustomViewSize = 10;
|
||||
|
||||
private readonly List<UIParticleRenderer> _renderers = new List<UIParticleRenderer>();
|
||||
private int _groupId;
|
||||
private Camera _bakeCamera;
|
||||
private DrivenRectTransformTracker _tracker;
|
||||
private Vector3 _storedScale;
|
||||
private int _groupId;
|
||||
private bool _isScaleStored;
|
||||
private Vector3 _storedScale;
|
||||
private DrivenRectTransformTracker _tracker;
|
||||
|
||||
/// <summary>
|
||||
/// Should this graphic be considered a target for ray-casting?
|
||||
@@ -116,7 +136,8 @@ namespace Coffee.UIExtensions
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Mesh sharing.
|
||||
/// Particle simulation results are shared within the same group.
|
||||
/// A large number of the same effects can be displayed with a small load.
|
||||
/// None: disable mesh sharing.
|
||||
/// Auto: automatically select Primary/Replica.
|
||||
/// Primary: provides particle simulation results to the same group.
|
||||
@@ -159,9 +180,9 @@ namespace Coffee.UIExtensions
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Particle position mode.
|
||||
/// Relative: The particles will be emitted from the scaled position of the ParticleSystem.
|
||||
/// Absolute: The particles will be emitted from the world position of the ParticleSystem.
|
||||
/// Emission position mode.
|
||||
/// Relative: The particles will be emitted from the scaled position.
|
||||
/// Absolute: The particles will be emitted from the world position.
|
||||
/// </summary>
|
||||
public PositionMode positionMode
|
||||
{
|
||||
@@ -174,6 +195,7 @@ namespace Coffee.UIExtensions
|
||||
/// Relative: The particles will be emitted from the scaled position of the ParticleSystem.
|
||||
/// Absolute: The particles will be emitted from the world position of the ParticleSystem.
|
||||
/// </summary>
|
||||
[Obsolete("The absoluteMode is now obsolete. Please use the autoScalingMode instead.", false)]
|
||||
public bool absoluteMode
|
||||
{
|
||||
get => m_PositionMode == PositionMode.Absolute;
|
||||
@@ -191,8 +213,12 @@ namespace Coffee.UIExtensions
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Auto scaling mode.
|
||||
/// How to automatically adjust when the Canvas scale is changed by the screen size or reference resolution.
|
||||
/// <para/>
|
||||
/// None: Do nothing.
|
||||
/// <para/>
|
||||
/// Transform: Transform.lossyScale (=world scale) will be set to (1, 1, 1).
|
||||
/// <para/>
|
||||
/// UIParticle: UIParticle.scale will be adjusted.
|
||||
/// </summary>
|
||||
public AutoScalingMode autoScalingMode
|
||||
@@ -211,6 +237,26 @@ namespace Coffee.UIExtensions
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Use a custom view.
|
||||
/// Use this if the particles are not displayed correctly due to min/max particle size.
|
||||
/// </summary>
|
||||
public bool useCustomView
|
||||
{
|
||||
get => m_UseCustomView;
|
||||
set => m_UseCustomView = value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Custom view size.
|
||||
/// Change the bake view size.
|
||||
/// </summary>
|
||||
public float customViewSize
|
||||
{
|
||||
get => m_CustomViewSize;
|
||||
set => m_CustomViewSize = Mathf.Max(0.1f, value);
|
||||
}
|
||||
|
||||
internal bool useMeshSharing => m_MeshSharing != MeshSharing.None;
|
||||
|
||||
internal bool isPrimary =>
|
||||
@@ -256,24 +302,6 @@ namespace Coffee.UIExtensions
|
||||
|
||||
public List<ParticleSystem> particles => m_Particles;
|
||||
|
||||
/// <summary>
|
||||
/// Get all base materials to render.
|
||||
/// </summary>
|
||||
public IEnumerable<Material> materials
|
||||
{
|
||||
get
|
||||
{
|
||||
for (var i = 0; i < _renderers.Count; i++)
|
||||
{
|
||||
var r = _renderers[i];
|
||||
if (!r || !r.material) continue;
|
||||
yield return r.material;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override Material materialForRendering => null;
|
||||
|
||||
/// <summary>
|
||||
/// Paused.
|
||||
/// </summary>
|
||||
@@ -334,6 +362,7 @@ namespace Coffee.UIExtensions
|
||||
|
||||
void ISerializationCallbackReceiver.OnAfterDeserialize()
|
||||
{
|
||||
#pragma warning disable CS0612 // Type or member is obsolete
|
||||
if (m_IgnoreCanvasScaler || m_AutoScaling)
|
||||
{
|
||||
m_IgnoreCanvasScaler = false;
|
||||
@@ -346,31 +375,47 @@ namespace Coffee.UIExtensions
|
||||
m_AbsoluteMode = false;
|
||||
m_PositionMode = PositionMode.Absolute;
|
||||
}
|
||||
#pragma warning restore CS0612 // Type or member is obsolete
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Play the ParticleSystems.
|
||||
/// </summary>
|
||||
public void Play()
|
||||
{
|
||||
particles.Exec(p => p.Simulate(0, false, true));
|
||||
isPaused = false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Pause the ParticleSystems.
|
||||
/// </summary>
|
||||
public void Pause()
|
||||
{
|
||||
particles.Exec(p => p.Pause());
|
||||
isPaused = true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Unpause the ParticleSystems.
|
||||
/// </summary>
|
||||
public void Resume()
|
||||
{
|
||||
isPaused = false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Stop the ParticleSystems.
|
||||
/// </summary>
|
||||
public void Stop()
|
||||
{
|
||||
particles.Exec(p => p.Stop());
|
||||
isPaused = true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Start emission of the ParticleSystems.
|
||||
/// </summary>
|
||||
public void StartEmission()
|
||||
{
|
||||
particles.Exec(p =>
|
||||
@@ -380,6 +425,9 @@ namespace Coffee.UIExtensions
|
||||
});
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Stop emission of the ParticleSystems.
|
||||
/// </summary>
|
||||
public void StopEmission()
|
||||
{
|
||||
particles.Exec(p =>
|
||||
@@ -389,24 +437,52 @@ namespace Coffee.UIExtensions
|
||||
});
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Clear the particles of the ParticleSystems.
|
||||
/// </summary>
|
||||
public void Clear()
|
||||
{
|
||||
particles.Exec(p => p.Clear());
|
||||
isPaused = true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get all base materials to render.
|
||||
/// </summary>
|
||||
public void GetMaterials(List<Material> result)
|
||||
{
|
||||
if (result == null) return;
|
||||
|
||||
for (var i = 0; i < _renderers.Count; i++)
|
||||
{
|
||||
var r = _renderers[i];
|
||||
if (!r || !r.material) continue;
|
||||
result.Add(r.material);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Refresh UIParticle using the ParticleSystem instance.
|
||||
/// </summary>
|
||||
public void SetParticleSystemInstance(GameObject instance)
|
||||
{
|
||||
SetParticleSystemInstance(instance, true);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Refresh UIParticle using the ParticleSystem instance.
|
||||
/// </summary>
|
||||
public void SetParticleSystemInstance(GameObject instance, bool destroyOldParticles)
|
||||
{
|
||||
if (!instance) return;
|
||||
|
||||
foreach (Transform child in transform)
|
||||
var childCount = transform.childCount;
|
||||
for (var i = 0; i < childCount; i++)
|
||||
{
|
||||
var go = child.gameObject;
|
||||
var go = transform.GetChild(i).gameObject;
|
||||
if (go.TryGetComponent<Camera>(out var cam) && cam == _bakeCamera) continue;
|
||||
if (go.TryGetComponent<UIParticleRenderer>(out var _)) continue;
|
||||
|
||||
go.SetActive(false);
|
||||
if (destroyOldParticles)
|
||||
{
|
||||
@@ -421,6 +497,10 @@ namespace Coffee.UIExtensions
|
||||
RefreshParticles(instance);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Refresh UIParticle using the prefab.
|
||||
/// The prefab is automatically instantiated.
|
||||
/// </summary>
|
||||
public void SetParticleSystemPrefab(GameObject prefab)
|
||||
{
|
||||
if (!prefab) return;
|
||||
@@ -428,16 +508,31 @@ namespace Coffee.UIExtensions
|
||||
SetParticleSystemInstance(Instantiate(prefab.gameObject), true);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Refresh UIParticle.
|
||||
/// Collect ParticleSystems under the GameObject and refresh the UIParticle.
|
||||
/// </summary>
|
||||
public void RefreshParticles()
|
||||
{
|
||||
RefreshParticles(gameObject);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Refresh UIParticle.
|
||||
/// Collect ParticleSystems under the GameObject and refresh the UIParticle.
|
||||
/// </summary>
|
||||
private void RefreshParticles(GameObject root)
|
||||
{
|
||||
if (!root) return;
|
||||
root.GetComponentsInChildren(true, particles);
|
||||
particles.RemoveAll(x => x.GetComponentInParent<UIParticle>(true) != this);
|
||||
for (var i = particles.Count - 1; 0 <= i; i--)
|
||||
{
|
||||
var ps = particles[i];
|
||||
if (!ps || ps.GetComponentInParent<UIParticle>(true) != this)
|
||||
{
|
||||
particles.RemoveAt(i);
|
||||
}
|
||||
}
|
||||
|
||||
for (var i = 0; i < particles.Count; i++)
|
||||
{
|
||||
@@ -452,34 +547,44 @@ namespace Coffee.UIExtensions
|
||||
RefreshParticles(particles);
|
||||
}
|
||||
|
||||
public void RefreshParticles(List<ParticleSystem> particles)
|
||||
/// <summary>
|
||||
/// Refresh UIParticle using a list of ParticleSystems.
|
||||
/// </summary>
|
||||
public void RefreshParticles(List<ParticleSystem> particleSystems)
|
||||
{
|
||||
// Collect children UIParticleRenderer components.
|
||||
// #246: Nullptr exceptions when using nested UIParticle components in hierarchy
|
||||
_renderers.Clear();
|
||||
foreach (Transform child in transform)
|
||||
var childCount = transform.childCount;
|
||||
for (var i = 0; i < childCount; i++)
|
||||
{
|
||||
var uiParticleRenderer = child.GetComponent<UIParticleRenderer>();
|
||||
|
||||
if (uiParticleRenderer != null)
|
||||
var child = transform.GetChild(i);
|
||||
if (child.TryGetComponent(out UIParticleRenderer uiParticleRenderer))
|
||||
{
|
||||
_renderers.Add(uiParticleRenderer);
|
||||
}
|
||||
}
|
||||
|
||||
// Reset the UIParticleRenderer components.
|
||||
for (var i = 0; i < _renderers.Count; i++)
|
||||
{
|
||||
_renderers[i].Reset(i);
|
||||
}
|
||||
|
||||
// Set the ParticleSystem to the UIParticleRenderer. If the trail is enabled, set it additionally.
|
||||
var j = 0;
|
||||
for (var i = 0; i < particles.Count; i++)
|
||||
for (var i = 0; i < particleSystems.Count; i++)
|
||||
{
|
||||
var ps = particles[i];
|
||||
var ps = particleSystems[i];
|
||||
if (!ps) continue;
|
||||
GetRenderer(j++).Set(this, ps, false);
|
||||
|
||||
var mainEmitter = ps.GetMainEmitter(particleSystems);
|
||||
GetRenderer(j++).Set(this, ps, false, mainEmitter);
|
||||
|
||||
// If the trail is enabled, set it additionally.
|
||||
if (ps.trails.enabled)
|
||||
{
|
||||
GetRenderer(j++).Set(this, ps, true);
|
||||
GetRenderer(j++).Set(this, ps, true, mainEmitter);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -501,8 +606,12 @@ namespace Coffee.UIExtensions
|
||||
}
|
||||
|
||||
var currentScale = transform.localScale;
|
||||
_storedScale = currentScale;
|
||||
_isScaleStored = true;
|
||||
if (!_isScaleStored)
|
||||
{
|
||||
_storedScale = currentScale.IsVisible() ? currentScale : Vector3.one;
|
||||
_isScaleStored = true;
|
||||
}
|
||||
|
||||
_tracker.Add(this, rectTransform, DrivenTransformProperties.Scale);
|
||||
var newScale = parentScale.Inverse();
|
||||
if (currentScale != newScale)
|
||||
@@ -518,11 +627,10 @@ namespace Coffee.UIExtensions
|
||||
for (var i = 0; i < _renderers.Count; i++)
|
||||
{
|
||||
var r = _renderers[i];
|
||||
if (!r)
|
||||
{
|
||||
RefreshParticles(particles);
|
||||
break;
|
||||
}
|
||||
if (r) continue;
|
||||
|
||||
RefreshParticles(particles);
|
||||
break;
|
||||
}
|
||||
|
||||
var bakeCamera = GetBakeCamera();
|
||||
@@ -530,6 +638,7 @@ namespace Coffee.UIExtensions
|
||||
{
|
||||
var r = _renderers[i];
|
||||
if (!r) continue;
|
||||
|
||||
r.UpdateMesh(bakeCamera);
|
||||
}
|
||||
}
|
||||
@@ -581,7 +690,16 @@ namespace Coffee.UIExtensions
|
||||
private Camera GetBakeCamera()
|
||||
{
|
||||
if (!canvas) return Camera.main;
|
||||
if (_bakeCamera) return _bakeCamera;
|
||||
if (!useCustomView && canvas.renderMode != RenderMode.ScreenSpaceOverlay && canvas.rootCanvas.worldCamera)
|
||||
{
|
||||
return canvas.rootCanvas.worldCamera;
|
||||
}
|
||||
|
||||
if (_bakeCamera)
|
||||
{
|
||||
_bakeCamera.orthographicSize = useCustomView ? customViewSize : 10;
|
||||
return _bakeCamera;
|
||||
}
|
||||
|
||||
// Find existing baking camera.
|
||||
var childCount = transform.childCount;
|
||||
@@ -598,11 +716,7 @@ namespace Coffee.UIExtensions
|
||||
// Create baking camera.
|
||||
if (!_bakeCamera)
|
||||
{
|
||||
var go = new GameObject("[generated] UIParticle BakingCamera")
|
||||
{
|
||||
// hideFlags = HideFlags.HideAndDontSave
|
||||
hideFlags = HideFlags.DontSave
|
||||
};
|
||||
var go = new GameObject("[generated] UIParticle BakingCamera");
|
||||
go.SetActive(false);
|
||||
go.transform.SetParent(transform, false);
|
||||
_bakeCamera = go.AddComponent<Camera>();
|
||||
@@ -610,7 +724,7 @@ namespace Coffee.UIExtensions
|
||||
|
||||
// Setup baking camera.
|
||||
_bakeCamera.enabled = false;
|
||||
_bakeCamera.orthographicSize = 1000;
|
||||
_bakeCamera.orthographicSize = useCustomView ? customViewSize : 10;
|
||||
_bakeCamera.transform.SetPositionAndRotation(new Vector3(0, 0, -1000), Quaternion.identity);
|
||||
_bakeCamera.orthographic = true;
|
||||
_bakeCamera.farClipPlane = 2000f;
|
||||
@@ -621,6 +735,9 @@ namespace Coffee.UIExtensions
|
||||
_bakeCamera.renderingPath = RenderingPath.Forward;
|
||||
_bakeCamera.useOcclusionCulling = false;
|
||||
|
||||
_bakeCamera.gameObject.SetActive(false);
|
||||
_bakeCamera.gameObject.hideFlags = UIParticleProjectSettings.globalHideFlags;
|
||||
|
||||
return _bakeCamera;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,12 +1,13 @@
|
||||
using System;
|
||||
using Coffee.UIParticleExtensions;
|
||||
using System.Collections.Generic;
|
||||
using Coffee.UIParticleInternal;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Events;
|
||||
|
||||
namespace Coffee.UIExtensions
|
||||
{
|
||||
[ExecuteAlways]
|
||||
public class UIParticleAttractor : MonoBehaviour
|
||||
public class UIParticleAttractor : MonoBehaviour, ISerializationCallbackReceiver
|
||||
{
|
||||
public enum Movement
|
||||
{
|
||||
@@ -22,8 +23,12 @@ namespace Coffee.UIExtensions
|
||||
}
|
||||
|
||||
[SerializeField]
|
||||
[HideInInspector]
|
||||
private ParticleSystem m_ParticleSystem;
|
||||
|
||||
[SerializeField]
|
||||
private List<ParticleSystem> m_ParticleSystems = new List<ParticleSystem>();
|
||||
|
||||
[Range(0.1f, 10f)]
|
||||
[SerializeField]
|
||||
private float m_DestinationRadius = 1;
|
||||
@@ -45,7 +50,7 @@ namespace Coffee.UIExtensions
|
||||
[SerializeField]
|
||||
private UnityEvent m_OnAttracted;
|
||||
|
||||
private UIParticle _uiParticle;
|
||||
private List<UIParticle> _uiParticles = new List<UIParticle>();
|
||||
|
||||
public float destinationRadius
|
||||
{
|
||||
@@ -84,25 +89,46 @@ namespace Coffee.UIExtensions
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The target ParticleSystem to attract.
|
||||
/// The target ParticleSystems to attract. Use <see cref="AddParticleSystem"/> and
|
||||
/// <see cref="RemoveParticleSystem"/> to modify the list.
|
||||
/// </summary>
|
||||
#if UNITY_EDITOR
|
||||
public new ParticleSystem particleSystem
|
||||
#else
|
||||
public ParticleSystem particleSystem
|
||||
#endif
|
||||
public IReadOnlyList<ParticleSystem> particleSystems => m_ParticleSystems;
|
||||
|
||||
public void AddParticleSystem(ParticleSystem ps)
|
||||
{
|
||||
get => m_ParticleSystem;
|
||||
set
|
||||
if (m_ParticleSystems == null)
|
||||
{
|
||||
m_ParticleSystem = value;
|
||||
ApplyParticleSystem();
|
||||
m_ParticleSystems = new List<ParticleSystem>();
|
||||
}
|
||||
|
||||
var i = m_ParticleSystems.IndexOf(ps);
|
||||
if (0 <= i) return; // Already added: skip
|
||||
|
||||
m_ParticleSystems.Add(ps);
|
||||
_uiParticles.Clear();
|
||||
}
|
||||
|
||||
public void RemoveParticleSystem(ParticleSystem ps)
|
||||
{
|
||||
if (m_ParticleSystems == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var i = m_ParticleSystems.IndexOf(ps);
|
||||
if (i < 0) return; // Not found. skip
|
||||
|
||||
m_ParticleSystems.RemoveAt(i);
|
||||
_uiParticles.Clear();
|
||||
}
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
UpgradeIfNeeded();
|
||||
}
|
||||
|
||||
private void OnEnable()
|
||||
{
|
||||
ApplyParticleSystem();
|
||||
UIParticleUpdater.Register(this);
|
||||
}
|
||||
|
||||
@@ -113,85 +139,96 @@ namespace Coffee.UIExtensions
|
||||
|
||||
private void OnDestroy()
|
||||
{
|
||||
_uiParticle = null;
|
||||
m_ParticleSystem = null;
|
||||
_uiParticles = null;
|
||||
m_ParticleSystems = null;
|
||||
}
|
||||
|
||||
internal void Attract()
|
||||
{
|
||||
if (m_ParticleSystem == null) return;
|
||||
// Collect UIParticle if needed (same size as m_ParticleSystems)
|
||||
CollectUIParticlesIfNeeded();
|
||||
|
||||
var count = m_ParticleSystem.particleCount;
|
||||
if (count == 0) return;
|
||||
|
||||
var particles = ParticleSystemExtensions.GetParticleArray(count);
|
||||
m_ParticleSystem.GetParticles(particles, count);
|
||||
|
||||
var dstPos = GetDestinationPosition();
|
||||
for (var i = 0; i < count; i++)
|
||||
for (var particleIndex = 0; particleIndex < m_ParticleSystems.Count; particleIndex++)
|
||||
{
|
||||
// Attracted
|
||||
var p = particles[i];
|
||||
if (0f < p.remainingLifetime && Vector3.Distance(p.position, dstPos) < m_DestinationRadius)
|
||||
{
|
||||
p.remainingLifetime = 0f;
|
||||
particles[i] = p;
|
||||
var particleSystem = m_ParticleSystems[particleIndex];
|
||||
|
||||
if (m_OnAttracted != null)
|
||||
// Skip: The ParticleSystem is not active
|
||||
if (particleSystem == null || !particleSystem.gameObject.activeInHierarchy) continue;
|
||||
|
||||
// Skip: No active particles
|
||||
var count = particleSystem.particleCount;
|
||||
if (count == 0) continue;
|
||||
|
||||
var particles = ParticleSystemExtensions.GetParticleArray(count);
|
||||
particleSystem.GetParticles(particles, count);
|
||||
|
||||
var uiParticle = _uiParticles[particleIndex];
|
||||
var dstPos = GetDestinationPosition(uiParticle, particleSystem);
|
||||
for (var i = 0; i < count; i++)
|
||||
{
|
||||
// Attracted
|
||||
var p = particles[i];
|
||||
if (0f < p.remainingLifetime && Vector3.Distance(p.position, dstPos) < m_DestinationRadius)
|
||||
{
|
||||
try
|
||||
p.remainingLifetime = 0f;
|
||||
particles[i] = p;
|
||||
|
||||
if (m_OnAttracted != null)
|
||||
{
|
||||
m_OnAttracted.Invoke();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Debug.LogException(e);
|
||||
try
|
||||
{
|
||||
m_OnAttracted.Invoke();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Debug.LogException(e);
|
||||
}
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
continue;
|
||||
// Calc attracting time
|
||||
var delayTime = p.startLifetime * m_DelayRate;
|
||||
var duration = p.startLifetime - delayTime;
|
||||
var time = Mathf.Max(0, p.startLifetime - p.remainingLifetime - delayTime);
|
||||
|
||||
// Delay
|
||||
if (time <= 0) continue;
|
||||
|
||||
// Attract
|
||||
p.position = GetAttractedPosition(p.position, dstPos, duration, time);
|
||||
p.velocity *= 0.5f;
|
||||
particles[i] = p;
|
||||
}
|
||||
|
||||
// Calc attracting time
|
||||
var delayTime = p.startLifetime * m_DelayRate;
|
||||
var duration = p.startLifetime - delayTime;
|
||||
var time = Mathf.Max(0, p.startLifetime - p.remainingLifetime - delayTime);
|
||||
|
||||
// Delay
|
||||
if (time <= 0) continue;
|
||||
|
||||
// Attract
|
||||
p.position = GetAttractedPosition(p.position, dstPos, duration, time);
|
||||
p.velocity *= 0.5f;
|
||||
particles[i] = p;
|
||||
particleSystem.SetParticles(particles, count);
|
||||
}
|
||||
|
||||
m_ParticleSystem.SetParticles(particles, count);
|
||||
}
|
||||
|
||||
private Vector3 GetDestinationPosition()
|
||||
private Vector3 GetDestinationPosition(UIParticle uiParticle, ParticleSystem particleSystem)
|
||||
{
|
||||
var isUI = _uiParticle && _uiParticle.enabled;
|
||||
var psPos = m_ParticleSystem.transform.position;
|
||||
var isUI = uiParticle && uiParticle.enabled;
|
||||
var psPos = particleSystem.transform.position;
|
||||
var attractorPos = transform.position;
|
||||
var dstPos = attractorPos;
|
||||
var isLocalSpace = m_ParticleSystem.IsLocalSpace();
|
||||
var isLocalSpace = particleSystem.IsLocalSpace();
|
||||
|
||||
if (isLocalSpace)
|
||||
{
|
||||
dstPos = m_ParticleSystem.transform.InverseTransformPoint(dstPos);
|
||||
dstPos = particleSystem.transform.InverseTransformPoint(dstPos);
|
||||
}
|
||||
|
||||
if (isUI)
|
||||
{
|
||||
var inverseScale = _uiParticle.parentScale.Inverse();
|
||||
var scale3d = _uiParticle.scale3DForCalc;
|
||||
var inverseScale = uiParticle.parentScale.Inverse();
|
||||
var scale3d = uiParticle.scale3DForCalc;
|
||||
dstPos = dstPos.GetScaled(inverseScale, scale3d.Inverse());
|
||||
|
||||
// Relative mode
|
||||
if (_uiParticle.positionMode == UIParticle.PositionMode.Relative)
|
||||
if (uiParticle.positionMode == UIParticle.PositionMode.Relative)
|
||||
{
|
||||
var diff = _uiParticle.transform.position - psPos;
|
||||
var diff = uiParticle.transform.position - psPos;
|
||||
diff.Scale(scale3d - inverseScale);
|
||||
diff.Scale(scale3d.Inverse());
|
||||
dstPos += diff;
|
||||
@@ -237,25 +274,59 @@ namespace Coffee.UIExtensions
|
||||
return Vector3.MoveTowards(current, target, speed);
|
||||
}
|
||||
|
||||
private void ApplyParticleSystem()
|
||||
private void CollectUIParticlesIfNeeded()
|
||||
{
|
||||
_uiParticle = null;
|
||||
if (m_ParticleSystem == null)
|
||||
{
|
||||
#if UNITY_EDITOR
|
||||
if (Application.isPlaying)
|
||||
#endif
|
||||
{
|
||||
Debug.LogError("No particle system attached to particle attractor script", this);
|
||||
}
|
||||
if (m_ParticleSystems.Count == 0 || _uiParticles.Count != 0) return;
|
||||
|
||||
return;
|
||||
// Expand capacity
|
||||
if (_uiParticles.Capacity < m_ParticleSystems.Capacity)
|
||||
{
|
||||
_uiParticles.Capacity = m_ParticleSystems.Capacity;
|
||||
}
|
||||
|
||||
_uiParticle = m_ParticleSystem.GetComponentInParent<UIParticle>(true);
|
||||
if (_uiParticle && !_uiParticle.particles.Contains(m_ParticleSystem))
|
||||
// Find UIParticle that controls the ParticleSystem
|
||||
for (var i = 0; i < m_ParticleSystems.Count; i++)
|
||||
{
|
||||
_uiParticle = null;
|
||||
var ps = m_ParticleSystems[i];
|
||||
if (ps == null)
|
||||
{
|
||||
_uiParticles.Add(null);
|
||||
continue;
|
||||
}
|
||||
|
||||
var uiParticle = ps.GetComponentInParent<UIParticle>(true);
|
||||
_uiParticles.Add(uiParticle.particles.Contains(ps) ? uiParticle : null);
|
||||
}
|
||||
}
|
||||
|
||||
#if UNITY_EDITOR
|
||||
private void OnValidate()
|
||||
{
|
||||
_uiParticles.Clear();
|
||||
}
|
||||
#endif
|
||||
|
||||
void ISerializationCallbackReceiver.OnBeforeSerialize()
|
||||
{
|
||||
UpgradeIfNeeded();
|
||||
}
|
||||
|
||||
void ISerializationCallbackReceiver.OnAfterDeserialize()
|
||||
{
|
||||
}
|
||||
|
||||
private void UpgradeIfNeeded()
|
||||
{
|
||||
// Multiple ParticleSystems support: from 'm_ParticleSystem' to 'm_ParticleSystems'
|
||||
if (m_ParticleSystem != null)
|
||||
{
|
||||
if (!m_ParticleSystems.Contains(m_ParticleSystem))
|
||||
{
|
||||
m_ParticleSystems.Add(m_ParticleSystem);
|
||||
}
|
||||
|
||||
m_ParticleSystem = null;
|
||||
Debug.Log($"Upgraded!");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@ MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
icon: {fileID: 2800000, guid: 5f0675613942149309588d556e33d990, type: 3}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
||||
40
Packages/src/Runtime/UIParticleProjectSettings.cs
Normal file
40
Packages/src/Runtime/UIParticleProjectSettings.cs
Normal file
@@ -0,0 +1,40 @@
|
||||
#pragma warning disable CS0414
|
||||
using Coffee.UIParticleInternal;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Coffee.UIExtensions
|
||||
{
|
||||
public class UIParticleProjectSettings : PreloadedProjectSettings<UIParticleProjectSettings>
|
||||
{
|
||||
[Header("Setting")]
|
||||
[SerializeField]
|
||||
internal bool m_EnableLinearToGamma = true;
|
||||
|
||||
public static bool enableLinearToGamma
|
||||
{
|
||||
get => instance.m_EnableLinearToGamma;
|
||||
set => instance.m_EnableLinearToGamma = value;
|
||||
}
|
||||
|
||||
|
||||
[Header("Editor")]
|
||||
[Tooltip("Hide the automatically generated objects.\n" +
|
||||
" - UIParticleRenderer\n" +
|
||||
" - UIParticle BakingCamera")]
|
||||
[SerializeField]
|
||||
private bool m_HideGeneratedObjects = true;
|
||||
|
||||
public static HideFlags globalHideFlags => instance.m_HideGeneratedObjects
|
||||
? HideFlags.DontSave | HideFlags.NotEditable | HideFlags.HideInHierarchy | HideFlags.HideInInspector
|
||||
: HideFlags.DontSave | HideFlags.NotEditable;
|
||||
|
||||
#if UNITY_EDITOR
|
||||
[SettingsProvider]
|
||||
private static SettingsProvider CreateSettingsProvider()
|
||||
{
|
||||
return new PreloadedProjectSettingsProvider("Project/UI/UI Particle");
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
11
Packages/src/Runtime/UIParticleProjectSettings.cs.meta
Normal file
11
Packages/src/Runtime/UIParticleProjectSettings.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f22a23b9d98e440478697f4adf30e61c
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {fileID: 2800000, guid: 5f0675613942149309588d556e33d990, type: 3}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -6,7 +6,7 @@
|
||||
#endif
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Coffee.UIParticleExtensions;
|
||||
using Coffee.UIParticleInternal;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Profiling;
|
||||
@@ -21,28 +21,26 @@ namespace Coffee.UIExtensions
|
||||
[AddComponentMenu("")]
|
||||
internal class UIParticleRenderer : MaskableGraphic
|
||||
{
|
||||
private static readonly List<Component> s_Components = new List<Component>();
|
||||
private static readonly CombineInstance[] s_CombineInstances = { new CombineInstance() };
|
||||
private static readonly List<Material> s_Materials = new List<Material>(2);
|
||||
private static MaterialPropertyBlock s_Mpb;
|
||||
private static readonly List<UIParticleRenderer> s_Renderers = new List<UIParticleRenderer>();
|
||||
private static readonly List<Color32> s_Colors = new List<Color32>();
|
||||
private static readonly Vector3[] s_Corners = new Vector3[4];
|
||||
private Material _currentMaterialForRendering;
|
||||
private bool _delay;
|
||||
private int _index;
|
||||
private bool _isPrevStored;
|
||||
private bool _isTrail;
|
||||
private Bounds _lastBounds;
|
||||
private Material _materialForRendering;
|
||||
private Material _modifiedMaterial;
|
||||
private UIParticle _parent;
|
||||
private ParticleSystem _particleSystem;
|
||||
private float _prevCanvasScale;
|
||||
private Vector3 _prevPsPos;
|
||||
private Vector3 _prevScale;
|
||||
private bool _isPrevStored;
|
||||
private Vector2Int _prevScreenSize;
|
||||
private bool _prewarm;
|
||||
private bool _preWarm;
|
||||
private ParticleSystemRenderer _renderer;
|
||||
private ParticleSystem _mainEmitter;
|
||||
|
||||
public override Texture mainTexture => _isTrail ? null : _particleSystem.GetTextureForSprite();
|
||||
|
||||
@@ -92,6 +90,19 @@ namespace Coffee.UIExtensions
|
||||
}
|
||||
}
|
||||
|
||||
public override Material materialForRendering
|
||||
{
|
||||
get
|
||||
{
|
||||
if (!_materialForRendering)
|
||||
{
|
||||
_materialForRendering = base.materialForRendering;
|
||||
}
|
||||
|
||||
return _materialForRendering;
|
||||
}
|
||||
}
|
||||
|
||||
public void Reset(int index = -1)
|
||||
{
|
||||
if (_renderer)
|
||||
@@ -102,6 +113,7 @@ namespace Coffee.UIExtensions
|
||||
_parent = null;
|
||||
_particleSystem = null;
|
||||
_renderer = null;
|
||||
_mainEmitter = null;
|
||||
if (0 <= index)
|
||||
{
|
||||
_index = index;
|
||||
@@ -111,16 +123,14 @@ namespace Coffee.UIExtensions
|
||||
if (this && isActiveAndEnabled)
|
||||
{
|
||||
material = null;
|
||||
workerMesh.Clear();
|
||||
canvasRenderer.SetMesh(workerMesh);
|
||||
canvasRenderer.Clear();
|
||||
_lastBounds = new Bounds();
|
||||
enabled = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
ModifiedMaterial.Remove(_modifiedMaterial);
|
||||
_modifiedMaterial = null;
|
||||
_currentMaterialForRendering = null;
|
||||
MaterialRepository.Release(ref _modifiedMaterial);
|
||||
_materialForRendering = null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -128,6 +138,7 @@ namespace Coffee.UIExtensions
|
||||
{
|
||||
base.OnEnable();
|
||||
|
||||
hideFlags = UIParticleProjectSettings.globalHideFlags;
|
||||
if (!s_CombineInstances[0].mesh)
|
||||
{
|
||||
s_CombineInstances[0].mesh = new Mesh
|
||||
@@ -136,17 +147,14 @@ namespace Coffee.UIExtensions
|
||||
hideFlags = HideFlags.HideAndDontSave
|
||||
};
|
||||
}
|
||||
|
||||
_currentMaterialForRendering = null;
|
||||
}
|
||||
|
||||
protected override void OnDisable()
|
||||
{
|
||||
base.OnDisable();
|
||||
|
||||
ModifiedMaterial.Remove(_modifiedMaterial);
|
||||
_modifiedMaterial = null;
|
||||
_currentMaterialForRendering = null;
|
||||
MaterialRepository.Release(ref _modifiedMaterial);
|
||||
_materialForRendering = null;
|
||||
_isPrevStored = false;
|
||||
}
|
||||
|
||||
@@ -155,7 +163,7 @@ namespace Coffee.UIExtensions
|
||||
// Create renderer object.
|
||||
var go = new GameObject("[generated] UIParticleRenderer", typeof(UIParticleRenderer))
|
||||
{
|
||||
hideFlags = HideFlags.HideAndDontSave,
|
||||
hideFlags = UIParticleProjectSettings.globalHideFlags,
|
||||
layer = parent.gameObject.layer
|
||||
};
|
||||
|
||||
@@ -179,12 +187,9 @@ namespace Coffee.UIExtensions
|
||||
/// </summary>
|
||||
public override Material GetModifiedMaterial(Material baseMaterial)
|
||||
{
|
||||
_currentMaterialForRendering = null;
|
||||
|
||||
if (!IsActive() || !_parent)
|
||||
{
|
||||
ModifiedMaterial.Remove(_modifiedMaterial);
|
||||
_modifiedMaterial = null;
|
||||
MaterialRepository.Release(ref _modifiedMaterial);
|
||||
return baseMaterial;
|
||||
}
|
||||
|
||||
@@ -194,26 +199,33 @@ namespace Coffee.UIExtensions
|
||||
var texture = mainTexture;
|
||||
if (texture == null && _parent.m_AnimatableProperties.Length == 0)
|
||||
{
|
||||
ModifiedMaterial.Remove(_modifiedMaterial);
|
||||
_modifiedMaterial = null;
|
||||
MaterialRepository.Release(ref _modifiedMaterial);
|
||||
return modifiedMaterial;
|
||||
}
|
||||
|
||||
//
|
||||
var id = _parent.m_AnimatableProperties.Length == 0 ? 0 : GetInstanceID();
|
||||
var hash = new Hash128(
|
||||
modifiedMaterial ? (uint)modifiedMaterial.GetInstanceID() : 0,
|
||||
texture ? (uint)texture.GetInstanceID() : 0,
|
||||
0 < _parent.m_AnimatableProperties.Length ? (uint)GetInstanceID() : 0,
|
||||
#if UNITY_EDITOR
|
||||
var props = EditorJsonUtility.ToJson(modifiedMaterial).GetHashCode();
|
||||
(uint)EditorJsonUtility.ToJson(modifiedMaterial).GetHashCode()
|
||||
#else
|
||||
var props = 0;
|
||||
0
|
||||
#endif
|
||||
modifiedMaterial = ModifiedMaterial.Add(modifiedMaterial, texture, id, props);
|
||||
ModifiedMaterial.Remove(_modifiedMaterial);
|
||||
_modifiedMaterial = modifiedMaterial;
|
||||
);
|
||||
if (!MaterialRepository.Valid(hash, _modifiedMaterial))
|
||||
{
|
||||
MaterialRepository.Get(hash, ref _modifiedMaterial, x => new Material(x.mat)
|
||||
{
|
||||
hideFlags = HideFlags.HideAndDontSave,
|
||||
mainTexture = x.texture ? x.texture : x.mat.mainTexture
|
||||
}, (mat: modifiedMaterial, texture));
|
||||
}
|
||||
|
||||
return modifiedMaterial;
|
||||
return _modifiedMaterial;
|
||||
}
|
||||
|
||||
public void Set(UIParticle parent, ParticleSystem ps, bool isTrail)
|
||||
public void Set(UIParticle parent, ParticleSystem ps, bool isTrail, ParticleSystem mainEmitter)
|
||||
{
|
||||
_parent = parent;
|
||||
maskable = parent.maskable;
|
||||
@@ -221,25 +233,22 @@ namespace Coffee.UIExtensions
|
||||
gameObject.layer = parent.gameObject.layer;
|
||||
|
||||
_particleSystem = ps;
|
||||
_prewarm = _particleSystem.main.prewarm;
|
||||
_preWarm = _particleSystem.main.prewarm;
|
||||
|
||||
#if UNITY_EDITOR
|
||||
if (Application.isPlaying)
|
||||
#endif
|
||||
{
|
||||
if (_particleSystem.isPlaying || _prewarm)
|
||||
if (_particleSystem.isPlaying || _preWarm)
|
||||
{
|
||||
_particleSystem.Clear();
|
||||
_particleSystem.Pause();
|
||||
}
|
||||
}
|
||||
|
||||
_renderer = ps.GetComponent<ParticleSystemRenderer>();
|
||||
ps.TryGetComponent(out _renderer);
|
||||
_renderer.enabled = false;
|
||||
|
||||
//_emitter = emitter;
|
||||
_isTrail = isTrail;
|
||||
|
||||
_renderer.GetSharedMaterials(s_Materials);
|
||||
material = s_Materials[isTrail ? 1 : 0];
|
||||
s_Materials.Clear();
|
||||
@@ -256,6 +265,7 @@ namespace Coffee.UIExtensions
|
||||
_prevScreenSize = new Vector2Int(Screen.width, Screen.height);
|
||||
_prevCanvasScale = canvas ? canvas.scaleFactor : 1f;
|
||||
_delay = true;
|
||||
_mainEmitter = mainEmitter;
|
||||
|
||||
canvasRenderer.SetTexture(null);
|
||||
|
||||
@@ -293,7 +303,7 @@ namespace Coffee.UIExtensions
|
||||
|
||||
// Simulate particles.
|
||||
Profiler.BeginSample("[UIParticle] Bake Mesh > Simulate Particles");
|
||||
if (!_isTrail && _parent.canSimulate)
|
||||
if (!_isTrail && _parent.canSimulate && !_mainEmitter)
|
||||
{
|
||||
#if UNITY_EDITOR
|
||||
if (!Application.isPlaying)
|
||||
@@ -406,95 +416,67 @@ namespace Coffee.UIExtensions
|
||||
_lastBounds = bounds;
|
||||
|
||||
// Convert linear color to gamma color.
|
||||
if (QualitySettings.activeColorSpace == ColorSpace.Linear)
|
||||
if (UIParticleProjectSettings.enableLinearToGamma && canvas.ShouldGammaToLinearInMesh())
|
||||
{
|
||||
Profiler.BeginSample("[UIParticleRenderer] Convert Linear to Gamma");
|
||||
workerMesh.GetColors(s_Colors);
|
||||
var count_c = s_Colors.Count;
|
||||
for (var i = 0; i < count_c; i++)
|
||||
{
|
||||
var c = s_Colors[i];
|
||||
c.r = c.r.LinearToGamma();
|
||||
c.g = c.g.LinearToGamma();
|
||||
c.b = c.b.LinearToGamma();
|
||||
s_Colors[i] = c;
|
||||
}
|
||||
|
||||
workerMesh.SetColors(s_Colors);
|
||||
Profiler.EndSample();
|
||||
workerMesh.LinearToGamma();
|
||||
}
|
||||
|
||||
GetComponents(typeof(IMeshModifier), s_Components);
|
||||
for (var i = 0; i < s_Components.Count; i++)
|
||||
var components = InternalListPool<Component>.Rent();
|
||||
GetComponents(typeof(IMeshModifier), components);
|
||||
for (var i = 0; i < components.Count; i++)
|
||||
{
|
||||
#pragma warning disable CS0618 // Type or member is obsolete
|
||||
((IMeshModifier)s_Components[i]).ModifyMesh(workerMesh);
|
||||
((IMeshModifier)components[i]).ModifyMesh(workerMesh);
|
||||
#pragma warning restore CS0618 // Type or member is obsolete
|
||||
}
|
||||
|
||||
s_Components.Clear();
|
||||
InternalListPool<Component>.Return(ref components);
|
||||
}
|
||||
|
||||
Profiler.EndSample();
|
||||
|
||||
|
||||
// Get grouped renderers.
|
||||
s_Renderers.Clear();
|
||||
if (_parent.useMeshSharing)
|
||||
{
|
||||
UIParticleUpdater.GetGroupedRenderers(_parent.groupId, _index, s_Renderers);
|
||||
}
|
||||
|
||||
// Set mesh to the CanvasRenderer.
|
||||
Profiler.BeginSample("[UIParticleRenderer] Set Mesh");
|
||||
for (var i = 0; i < s_Renderers.Count; i++)
|
||||
{
|
||||
if (s_Renderers[i] == this) continue;
|
||||
s_Renderers[i].canvasRenderer.SetMesh(workerMesh);
|
||||
s_Renderers[i]._lastBounds = _lastBounds;
|
||||
}
|
||||
|
||||
if (!_parent.canRender)
|
||||
{
|
||||
workerMesh.Clear();
|
||||
}
|
||||
|
||||
canvasRenderer.SetMesh(workerMesh);
|
||||
Profiler.EndSample();
|
||||
|
||||
// Update animatable material properties.
|
||||
Profiler.BeginSample("[UIParticleRenderer] Update Animatable Material Properties");
|
||||
|
||||
#if UNITY_EDITOR
|
||||
if (_modifiedMaterial != material)
|
||||
{
|
||||
_renderer.GetSharedMaterials(s_Materials);
|
||||
material = s_Materials[_isTrail ? 1 : 0];
|
||||
s_Materials.Clear();
|
||||
SetMaterialDirty();
|
||||
}
|
||||
#endif
|
||||
|
||||
UpdateMaterialProperties();
|
||||
Profiler.EndSample();
|
||||
|
||||
// Get grouped renderers.
|
||||
Profiler.BeginSample("[UIParticleRenderer] Set Mesh");
|
||||
var renderers = InternalListPool<UIParticleRenderer>.Rent();
|
||||
if (_parent.useMeshSharing)
|
||||
{
|
||||
if (!_currentMaterialForRendering)
|
||||
{
|
||||
_currentMaterialForRendering = materialForRendering;
|
||||
}
|
||||
UIParticleUpdater.GetGroupedRenderers(_parent.groupId, _index, renderers);
|
||||
}
|
||||
|
||||
for (var i = 0; i < s_Renderers.Count; i++)
|
||||
{
|
||||
if (s_Renderers[i] == this) continue;
|
||||
for (var i = 0; i < renderers.Count; i++)
|
||||
{
|
||||
var r = renderers[i];
|
||||
if (r == this) continue;
|
||||
|
||||
s_Renderers[i].canvasRenderer.materialCount = 1;
|
||||
s_Renderers[i].canvasRenderer.SetMaterial(_currentMaterialForRendering, 0);
|
||||
}
|
||||
r.canvasRenderer.SetMesh(workerMesh);
|
||||
r._lastBounds = _lastBounds;
|
||||
r.canvasRenderer.materialCount = 1;
|
||||
r.canvasRenderer.SetMaterial(materialForRendering, 0);
|
||||
}
|
||||
|
||||
InternalListPool<UIParticleRenderer>.Return(ref renderers);
|
||||
|
||||
if (_parent.canRender)
|
||||
{
|
||||
canvasRenderer.SetMesh(workerMesh);
|
||||
}
|
||||
else
|
||||
{
|
||||
workerMesh.Clear();
|
||||
}
|
||||
|
||||
Profiler.EndSample();
|
||||
}
|
||||
|
||||
s_Renderers.Clear();
|
||||
public override void SetMaterialDirty()
|
||||
{
|
||||
_materialForRendering = null;
|
||||
base.SetMaterialDirty();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -560,13 +542,34 @@ namespace Coffee.UIExtensions
|
||||
return Matrix4x4.Translate(psPos)
|
||||
* Matrix4x4.Scale(scale);
|
||||
case ParticleSystemSimulationSpace.World:
|
||||
if (_isTrail)
|
||||
{
|
||||
return Matrix4x4.Translate(psPos)
|
||||
* Matrix4x4.Scale(scale)
|
||||
* Matrix4x4.Translate(-psPos);
|
||||
}
|
||||
|
||||
if (_mainEmitter)
|
||||
{
|
||||
if (_mainEmitter.IsLocalSpace())
|
||||
{
|
||||
return Matrix4x4.Translate(psPos)
|
||||
* Matrix4x4.Scale(scale)
|
||||
* Matrix4x4.Translate(-psPos);
|
||||
}
|
||||
else
|
||||
{
|
||||
psPos = _particleSystem.transform.position - _mainEmitter.transform.position;
|
||||
return Matrix4x4.Translate(psPos)
|
||||
* Matrix4x4.Scale(scale)
|
||||
* Matrix4x4.Translate(-psPos);
|
||||
}
|
||||
}
|
||||
|
||||
return Matrix4x4.Scale(scale);
|
||||
case ParticleSystemSimulationSpace.Custom:
|
||||
return Matrix4x4.Translate(_particleSystem.main.customSimulationSpace.position.GetScaled(scale))
|
||||
//* Matrix4x4.Translate(wpos)
|
||||
* Matrix4x4.Scale(scale)
|
||||
//* Matrix4x4.Translate(-wpos)
|
||||
;
|
||||
* Matrix4x4.Scale(scale);
|
||||
default:
|
||||
throw new NotSupportedException();
|
||||
}
|
||||
@@ -582,7 +585,8 @@ namespace Coffee.UIExtensions
|
||||
var screenSize = new Vector2Int(Screen.width, Screen.height);
|
||||
var isWorldSpace = _particleSystem.IsWorldSpace();
|
||||
var canvasScale = _parent.canvas ? _parent.canvas.scaleFactor : 1f;
|
||||
var resolutionChanged = _prevScreenSize != screenSize || _prevCanvasScale != canvasScale;
|
||||
var resolutionChanged = _prevScreenSize != screenSize
|
||||
|| !Mathf.Approximately(_prevCanvasScale, canvasScale);
|
||||
if (resolutionChanged && isWorldSpace && _isPrevStored)
|
||||
{
|
||||
// Update particle array size and get particles.
|
||||
@@ -590,7 +594,7 @@ namespace Coffee.UIExtensions
|
||||
var particles = ParticleSystemExtensions.GetParticleArray(size);
|
||||
_particleSystem.GetParticles(particles, size);
|
||||
|
||||
// Resolusion resolver:
|
||||
// Resolution resolver:
|
||||
// (psPos / scale) / (prevPsPos / prevScale) -> psPos * scale.inv * prevPsPos.inv * prevScale
|
||||
var modifier = psPos.GetScaled(
|
||||
scale.Inverse(),
|
||||
@@ -625,11 +629,11 @@ namespace Coffee.UIExtensions
|
||||
? Time.unscaledDeltaTime
|
||||
: Time.deltaTime;
|
||||
|
||||
// Prewarm:
|
||||
if (0 < deltaTime && _prewarm)
|
||||
// Pre-warm:
|
||||
if (0 < deltaTime && _preWarm)
|
||||
{
|
||||
deltaTime += main.duration;
|
||||
_prewarm = false;
|
||||
_preWarm = false;
|
||||
}
|
||||
|
||||
// get world position.
|
||||
@@ -704,12 +708,12 @@ namespace Coffee.UIExtensions
|
||||
if (s_Mpb.isEmpty) return;
|
||||
|
||||
// #41: Copy the value from MaterialPropertyBlock to CanvasRenderer
|
||||
if (!_modifiedMaterial) return;
|
||||
if (!materialForRendering) return;
|
||||
|
||||
for (var i = 0; i < _parent.m_AnimatableProperties.Length; i++)
|
||||
{
|
||||
var ap = _parent.m_AnimatableProperties[i];
|
||||
ap.UpdateMaterialProperties(_modifiedMaterial, s_Mpb);
|
||||
ap.UpdateMaterialProperties(materialForRendering, s_Mpb);
|
||||
}
|
||||
|
||||
s_Mpb.Clear();
|
||||
|
||||
@@ -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,5 @@
|
||||
using System.Collections.Generic;
|
||||
using Coffee.UIParticleInternal;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
|
||||
@@ -39,12 +40,12 @@ namespace Coffee.UIExtensions
|
||||
|
||||
#if UNITY_EDITOR
|
||||
[InitializeOnLoadMethod]
|
||||
#else
|
||||
[RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.BeforeSceneLoad)]
|
||||
#endif
|
||||
[RuntimeInitializeOnLoadMethod]
|
||||
private static void InitializeOnLoad()
|
||||
{
|
||||
Canvas.willRenderCanvases -= Refresh;
|
||||
Canvas.willRenderCanvases += Refresh;
|
||||
UIExtraCallbacks.onAfterCanvasRebuild += Refresh;
|
||||
}
|
||||
|
||||
private static void Refresh()
|
||||
|
||||
8
Packages/src/Runtime/Utilities.meta
Normal file
8
Packages/src/Runtime/Utilities.meta
Normal file
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 66c42f0f30de84ca4bd8305a1188af85
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,96 +1,11 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Reflection;
|
||||
using UnityEngine;
|
||||
using Object = UnityEngine.Object;
|
||||
|
||||
namespace Coffee.UIParticleExtensions
|
||||
namespace Coffee.UIParticleInternal
|
||||
{
|
||||
public static class Color32Extensions
|
||||
{
|
||||
private static byte[] s_LinearToGammaLut;
|
||||
|
||||
public static byte LinearToGamma(this byte self)
|
||||
{
|
||||
if (s_LinearToGammaLut == null)
|
||||
{
|
||||
s_LinearToGammaLut = new byte[256];
|
||||
for (var i = 0; i < 256; i++)
|
||||
{
|
||||
s_LinearToGammaLut[i] = (byte)(Mathf.LinearToGammaSpace(i / 255f) * 255f);
|
||||
}
|
||||
}
|
||||
|
||||
return s_LinearToGammaLut[self];
|
||||
}
|
||||
}
|
||||
|
||||
public static class Vector3Extensions
|
||||
{
|
||||
public static Vector3 Inverse(this Vector3 self)
|
||||
{
|
||||
self.x = Mathf.Approximately(self.x, 0) ? 1 : 1 / self.x;
|
||||
self.y = Mathf.Approximately(self.y, 0) ? 1 : 1 / self.y;
|
||||
self.z = Mathf.Approximately(self.z, 0) ? 1 : 1 / self.z;
|
||||
return self;
|
||||
}
|
||||
|
||||
public static Vector3 GetScaled(this Vector3 self, Vector3 other1)
|
||||
{
|
||||
self.Scale(other1);
|
||||
return self;
|
||||
}
|
||||
|
||||
public static Vector3 GetScaled(this Vector3 self, Vector3 other1, Vector3 other2)
|
||||
{
|
||||
self.Scale(other1);
|
||||
self.Scale(other2);
|
||||
return self;
|
||||
}
|
||||
|
||||
public static Vector3 GetScaled(this Vector3 self, Vector3 other1, Vector3 other2, Vector3 other3)
|
||||
{
|
||||
self.Scale(other1);
|
||||
self.Scale(other2);
|
||||
self.Scale(other3);
|
||||
return self;
|
||||
}
|
||||
|
||||
public static bool IsVisible(this Vector3 self)
|
||||
{
|
||||
return 0 < Mathf.Abs(self.x * self.y * self.z);
|
||||
}
|
||||
}
|
||||
|
||||
internal static class SpriteExtensions
|
||||
{
|
||||
#if UNITY_EDITOR
|
||||
private static readonly Type s_SpriteEditorExtensionType =
|
||||
Type.GetType("UnityEditor.Experimental.U2D.SpriteEditorExtension, UnityEditor")
|
||||
?? Type.GetType("UnityEditor.U2D.SpriteEditorExtension, UnityEditor");
|
||||
|
||||
private static readonly MethodInfo s_GetActiveAtlasTextureMethodInfo = s_SpriteEditorExtensionType
|
||||
.GetMethod("GetActiveAtlasTexture", BindingFlags.Static | BindingFlags.NonPublic);
|
||||
|
||||
public static Texture2D GetActualTexture(this Sprite self)
|
||||
{
|
||||
if (!self) return null;
|
||||
|
||||
if (Application.isPlaying) return self.texture;
|
||||
var ret = s_GetActiveAtlasTextureMethodInfo.Invoke(null, new object[] { self }) as Texture2D;
|
||||
return ret
|
||||
? ret
|
||||
: self.texture;
|
||||
}
|
||||
#else
|
||||
internal static Texture2D GetActualTexture(this Sprite self)
|
||||
{
|
||||
return self ? self.texture : null;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
public static class ParticleSystemExtensions
|
||||
internal static class ParticleSystemExtensions
|
||||
{
|
||||
private static ParticleSystem.Particle[] s_TmpParticles = new ParticleSystem.Particle[2048];
|
||||
|
||||
@@ -250,59 +165,36 @@ namespace Coffee.UIParticleExtensions
|
||||
|
||||
public static void Exec(this List<ParticleSystem> self, Action<ParticleSystem> action)
|
||||
{
|
||||
self.RemoveAll(p => !p);
|
||||
self.ForEach(action);
|
||||
}
|
||||
}
|
||||
|
||||
internal static class Misc
|
||||
{
|
||||
public static void Destroy(Object obj)
|
||||
{
|
||||
if (!obj) return;
|
||||
#if UNITY_EDITOR
|
||||
if (!Application.isPlaying)
|
||||
foreach (var p in self)
|
||||
{
|
||||
Object.DestroyImmediate(obj);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
Object.Destroy(obj);
|
||||
if (!p) continue;
|
||||
action.Invoke(p);
|
||||
}
|
||||
}
|
||||
|
||||
public static void DestroyImmediate(Object obj)
|
||||
public static ParticleSystem GetMainEmitter(this ParticleSystem self, List<ParticleSystem> list)
|
||||
{
|
||||
if (!obj) return;
|
||||
#if UNITY_EDITOR
|
||||
if (Application.isEditor)
|
||||
{
|
||||
Object.DestroyImmediate(obj);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
Object.Destroy(obj);
|
||||
}
|
||||
}
|
||||
if (!self || list == null || list.Count == 0) return null;
|
||||
|
||||
#if !UNITY_2021_2_OR_NEWER && !UNITY_2020_3_45 && !UNITY_2020_3_46 && !UNITY_2020_3_47 && !UNITY_2020_3_48
|
||||
public static T GetComponentInParent<T>(this Component self, bool includeInactive) where T : Component
|
||||
{
|
||||
if (!self) return null;
|
||||
if (!includeInactive) return self.GetComponentInParent<T>();
|
||||
|
||||
var current = self.transform;
|
||||
while (current)
|
||||
for (var i = 0; i < list.Count; i++)
|
||||
{
|
||||
var component = current.GetComponent<T>();
|
||||
if (component) return component;
|
||||
current = current.parent;
|
||||
var parent = list[i];
|
||||
if (parent != self && IsSubEmitterOf(self, parent)) return parent;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
#endif
|
||||
|
||||
public static bool IsSubEmitterOf(this ParticleSystem self, ParticleSystem parent)
|
||||
{
|
||||
var subEmitters = parent.subEmitters;
|
||||
var count = subEmitters.subEmittersCount;
|
||||
for (var i = 0; i < count; i++)
|
||||
{
|
||||
if (subEmitters.GetSubEmitterSystem(i) == self) return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: e51604bfb810e44519e2710fd1b8af90
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,3 +1,4 @@
|
||||
using Coffee.UIParticleInternal;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Serialization;
|
||||
using UnityEngine.UI;
|
||||
@@ -51,7 +52,7 @@ namespace Coffee.UIExtensions.Demo
|
||||
|
||||
public void EnableAnimations(bool flag)
|
||||
{
|
||||
foreach (var animator in FindObjectsOfType<Animator>())
|
||||
foreach (var animator in Misc.FindObjectsOfType<Animator>())
|
||||
{
|
||||
animator.enabled = flag;
|
||||
}
|
||||
@@ -79,7 +80,7 @@ namespace Coffee.UIExtensions.Demo
|
||||
|
||||
public void UIParticle_Scale(float scale)
|
||||
{
|
||||
foreach (var uip in FindObjectsOfType<UIParticle>())
|
||||
foreach (var uip in Misc.FindObjectsOfType<UIParticle>())
|
||||
{
|
||||
uip.scale = scale;
|
||||
}
|
||||
@@ -87,7 +88,7 @@ namespace Coffee.UIExtensions.Demo
|
||||
|
||||
public void ParticleSystem_WorldSpaseSimulation(bool flag)
|
||||
{
|
||||
foreach (var p in FindObjectsOfType<ParticleSystem>())
|
||||
foreach (var p in Misc.FindObjectsOfType<ParticleSystem>())
|
||||
{
|
||||
var main = p.main;
|
||||
main.simulationSpace = flag
|
||||
@@ -123,7 +124,7 @@ namespace Coffee.UIExtensions.Demo
|
||||
|
||||
public void ParticleSystem_SetScale(float scale)
|
||||
{
|
||||
foreach (var ps in FindObjectsOfType<ParticleSystem>())
|
||||
foreach (var ps in Misc.FindObjectsOfType<ParticleSystem>())
|
||||
{
|
||||
ps.transform.localScale = new Vector3(scale, scale, scale);
|
||||
}
|
||||
|
||||
@@ -42,12 +42,12 @@ TextureImporter:
|
||||
compressionQuality: 50
|
||||
spriteMode: 1
|
||||
spriteExtrude: 1
|
||||
spriteMeshType: 1
|
||||
spriteMeshType: 0
|
||||
alignment: 0
|
||||
spritePivot: {x: 0.5, y: 0.5}
|
||||
spritePixelsToUnits: 100
|
||||
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
|
||||
spriteGenerateFallbackPhysicsShape: 1
|
||||
spriteGenerateFallbackPhysicsShape: 0
|
||||
alphaUsage: 1
|
||||
alphaIsTransparency: 1
|
||||
spriteTessellationDetail: -1
|
||||
|
||||
@@ -27,7 +27,7 @@ TextureImporter:
|
||||
generateCubemap: 6
|
||||
cubemapConvolution: 0
|
||||
seamlessCubemap: 0
|
||||
textureFormat: 1
|
||||
textureFormat: 4
|
||||
maxTextureSize: 2048
|
||||
textureSettings:
|
||||
serializedVersion: 2
|
||||
@@ -42,12 +42,12 @@ TextureImporter:
|
||||
compressionQuality: 50
|
||||
spriteMode: 1
|
||||
spriteExtrude: 1
|
||||
spriteMeshType: 1
|
||||
spriteMeshType: 0
|
||||
alignment: 0
|
||||
spritePivot: {x: 0.5, y: 0.5}
|
||||
spritePixelsToUnits: 100
|
||||
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
|
||||
spriteGenerateFallbackPhysicsShape: 1
|
||||
spriteGenerateFallbackPhysicsShape: 0
|
||||
alphaUsage: 1
|
||||
alphaIsTransparency: 1
|
||||
spriteTessellationDetail: -1
|
||||
|
||||
@@ -42,12 +42,12 @@ TextureImporter:
|
||||
compressionQuality: 50
|
||||
spriteMode: 1
|
||||
spriteExtrude: 1
|
||||
spriteMeshType: 1
|
||||
spriteMeshType: 0
|
||||
alignment: 0
|
||||
spritePivot: {x: 0.5, y: 0.5}
|
||||
spritePixelsToUnits: 100
|
||||
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
|
||||
spriteGenerateFallbackPhysicsShape: 1
|
||||
spriteGenerateFallbackPhysicsShape: 0
|
||||
alphaUsage: 0
|
||||
alphaIsTransparency: 1
|
||||
spriteTessellationDetail: -1
|
||||
|
||||
@@ -27,7 +27,7 @@ TextureImporter:
|
||||
generateCubemap: 6
|
||||
cubemapConvolution: 0
|
||||
seamlessCubemap: 0
|
||||
textureFormat: -1
|
||||
textureFormat: 4
|
||||
maxTextureSize: 2048
|
||||
textureSettings:
|
||||
serializedVersion: 2
|
||||
@@ -42,12 +42,12 @@ TextureImporter:
|
||||
compressionQuality: 50
|
||||
spriteMode: 1
|
||||
spriteExtrude: 1
|
||||
spriteMeshType: 1
|
||||
spriteMeshType: 0
|
||||
alignment: 0
|
||||
spritePivot: {x: 0.5, y: 0.5}
|
||||
spritePixelsToUnits: 100
|
||||
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
|
||||
spriteGenerateFallbackPhysicsShape: 1
|
||||
spriteGenerateFallbackPhysicsShape: 0
|
||||
alphaUsage: 1
|
||||
alphaIsTransparency: 1
|
||||
spriteTessellationDetail: -1
|
||||
|
||||
@@ -40,7 +40,10 @@
|
||||
Lighting Off
|
||||
ZWrite Off
|
||||
ZTest [unity_GUIZTestMode]
|
||||
Fog { Mode Off }
|
||||
Fog
|
||||
{
|
||||
Mode Off
|
||||
}
|
||||
Blend One One
|
||||
|
||||
ColorMask [_ColorMask]
|
||||
@@ -61,21 +64,21 @@
|
||||
|
||||
struct appdata_t
|
||||
{
|
||||
float4 vertex : POSITION;
|
||||
float4 color : COLOR;
|
||||
float4 vertex : POSITION;
|
||||
float4 color : COLOR;
|
||||
float2 texcoord : TEXCOORD0;
|
||||
UNITY_VERTEX_INPUT_INSTANCE_ID
|
||||
};
|
||||
|
||||
struct v2f
|
||||
{
|
||||
float4 vertex : SV_POSITION;
|
||||
fixed4 color : COLOR;
|
||||
float2 texcoord : TEXCOORD0;
|
||||
float4 worldPosition : TEXCOORD1;
|
||||
float4 vertex : SV_POSITION;
|
||||
fixed4 color : COLOR;
|
||||
float2 texcoord : TEXCOORD0;
|
||||
float4 worldPosition : TEXCOORD1;
|
||||
UNITY_VERTEX_OUTPUT_STEREO
|
||||
};
|
||||
|
||||
|
||||
fixed4 _Color;
|
||||
sampler2D _MainTex;
|
||||
float4 _MainTex_ST;
|
||||
@@ -114,4 +117,4 @@
|
||||
ENDCG
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2,7 +2,7 @@
|
||||
"name": "com.coffee.ui-particle",
|
||||
"displayName": "UI Particle",
|
||||
"description": "This package provides a component to render particle effects for uGUI.\nThe particle rendering is maskable and sortable, without the need for an extra Camera, RenderTexture, or Canvas.",
|
||||
"version": "4.7.1",
|
||||
"version": "4.10.5",
|
||||
"unity": "2018.2",
|
||||
"license": "MIT",
|
||||
"repository": {
|
||||
|
||||
11
ProjectSettings/MinimalResourceSettings.json
Normal file
11
ProjectSettings/MinimalResourceSettings.json
Normal file
@@ -0,0 +1,11 @@
|
||||
{
|
||||
"MonoBehaviour": {
|
||||
"m_Enabled": true,
|
||||
"m_EditorHideFlags": 0,
|
||||
"m_Name": "",
|
||||
"m_EditorClassIdentifier": "",
|
||||
"m_OutputDllPaths": [
|
||||
"Packages/com.coffee.ui-particle/Runtime/Coffee.UIParticle.R.dll"
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -124,7 +124,7 @@ PlayerSettings:
|
||||
bundleVersion: 1.0
|
||||
preloadedAssets:
|
||||
- {fileID: 11400000, guid: 86087a0847f384b538391745dad4565c, type: 2}
|
||||
- {fileID: 11400000, guid: be3e05903ef7041d39b3ef8ecdd47f08, type: 2}
|
||||
- {fileID: 11400000, guid: 4b9df7b8a4193489299b8f477348ae0c, type: 2}
|
||||
metroInputSource: 0
|
||||
wsaTransparentSwapchain: 0
|
||||
m_HolographicPauseOnTrackingLoss: 1
|
||||
@@ -520,7 +520,7 @@ PlayerSettings:
|
||||
webGLTemplate: APPLICATION:Default
|
||||
webGLAnalyzeBuildSize: 0
|
||||
webGLUseEmbeddedResources: 0
|
||||
webGLCompressionFormat: 1
|
||||
webGLCompressionFormat: 2
|
||||
webGLLinkerTarget: 0
|
||||
webGLThreadsSupport: 0
|
||||
scriptingDefineSymbols:
|
||||
|
||||
Reference in New Issue
Block a user