You've already forked ParticleEffectForUGUI
mirror of
https://github.com/mob-sakai/ParticleEffectForUGUI.git
synced 2026-05-15 20:50:08 +00:00
Compare commits
3 Commits
v4.8.1
...
asset_upda
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
36ab069eba | ||
|
|
66c76fb92b | ||
|
|
b3a49514b5 |
@@ -25,7 +25,6 @@ indent_size = 4
|
|||||||
trim_trailing_whitespace = true
|
trim_trailing_whitespace = true
|
||||||
insert_final_newline = true
|
insert_final_newline = true
|
||||||
|
|
||||||
csharp_style_namespace_declarations = block_scoped
|
|
||||||
csharp_style_implicit_object_creation_when_type_is_apparent = false
|
csharp_style_implicit_object_creation_when_type_is_apparent = false
|
||||||
resharper_object_creation_when_type_evident = explicitly_typed
|
resharper_object_creation_when_type_evident = explicitly_typed
|
||||||
|
|
||||||
@@ -87,9 +86,6 @@ csharp_style_var_elsewhere = true:suggestion
|
|||||||
dotnet_style_predefined_type_for_locals_parameters_members = true:suggestion
|
dotnet_style_predefined_type_for_locals_parameters_members = true:suggestion
|
||||||
dotnet_style_predefined_type_for_member_access = true:suggestion
|
dotnet_style_predefined_type_for_member_access = true:suggestion
|
||||||
|
|
||||||
#
|
|
||||||
resharper_keep_existing_embedded_arrangement = true
|
|
||||||
|
|
||||||
# Arguments
|
# Arguments
|
||||||
csharp_arguments_literal = named:suggestion
|
csharp_arguments_literal = named:suggestion
|
||||||
csharp_arguments_string_literal = named:suggestion
|
csharp_arguments_string_literal = named:suggestion
|
||||||
@@ -138,7 +134,7 @@ dotnet_naming_style._camel_case.capitalization = camel_case
|
|||||||
|
|
||||||
# Code style defaults
|
# Code style defaults
|
||||||
dotnet_sort_system_directives_first = true
|
dotnet_sort_system_directives_first = true
|
||||||
csharp_preserve_single_line_statements = false
|
csharp_preserve_single_line_statements = false:none
|
||||||
csharp_prefer_static_local_function = true:suggestion
|
csharp_prefer_static_local_function = true:suggestion
|
||||||
csharp_prefer_simple_using_statement = false:none
|
csharp_prefer_simple_using_statement = false:none
|
||||||
csharp_style_prefer_switch_expression = true:suggestion
|
csharp_style_prefer_switch_expression = true:suggestion
|
||||||
@@ -190,7 +186,7 @@ csharp_space_after_dot = false
|
|||||||
csharp_space_after_keywords_in_control_flow_statements = true
|
csharp_space_after_keywords_in_control_flow_statements = true
|
||||||
csharp_space_after_semicolon_in_for_statement = true
|
csharp_space_after_semicolon_in_for_statement = true
|
||||||
csharp_space_around_binary_operators = before_and_after
|
csharp_space_around_binary_operators = before_and_after
|
||||||
csharp_space_around_declaration_statements = false
|
csharp_space_around_declaration_statements = do_not_ignore
|
||||||
csharp_space_before_colon_in_inheritance_clause = true
|
csharp_space_before_colon_in_inheritance_clause = true
|
||||||
csharp_space_before_comma = false
|
csharp_space_before_comma = false
|
||||||
csharp_space_before_dot = false
|
csharp_space_before_dot = false
|
||||||
|
|||||||
53
.github/workflows/release.yml
vendored
53
.github/workflows/release.yml
vendored
@@ -4,9 +4,8 @@ on:
|
|||||||
workflow_dispatch:
|
workflow_dispatch:
|
||||||
push:
|
push:
|
||||||
branches:
|
branches:
|
||||||
|
- preview
|
||||||
- release
|
- release
|
||||||
- release-preview
|
|
||||||
- release-v4
|
|
||||||
tags-ignore:
|
tags-ignore:
|
||||||
- "**"
|
- "**"
|
||||||
|
|
||||||
@@ -23,8 +22,7 @@ jobs:
|
|||||||
released: ${{ steps.release.outputs.new_release_published }}
|
released: ${{ steps.release.outputs.new_release_published }}
|
||||||
tag: ${{ steps.release.outputs.new_release_git_tag }}
|
tag: ${{ steps.release.outputs.new_release_git_tag }}
|
||||||
version: ${{ steps.release.outputs.new_release_version }}
|
version: ${{ steps.release.outputs.new_release_version }}
|
||||||
merge_to: ${{ steps.summary.outputs.merge_to }}
|
notes: ${{ steps.release.outputs.new_release_notes }}
|
||||||
split_to: ${{ steps.summary.outputs.split_to }}
|
|
||||||
steps:
|
steps:
|
||||||
- name: 🚚 Checkout (${{ github.ref_name }})
|
- name: 🚚 Checkout (${{ github.ref_name }})
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v4
|
||||||
@@ -40,51 +38,37 @@ jobs:
|
|||||||
env:
|
env:
|
||||||
GITHUB_TOKEN: ${{ github.token }}
|
GITHUB_TOKEN: ${{ github.token }}
|
||||||
|
|
||||||
- id: summary
|
- run: |
|
||||||
run: |
|
|
||||||
echo "🔖 New release published: '${{ steps.release.outputs.new_release_published }}'" | tee -a $GITHUB_STEP_SUMMARY
|
echo "🔖 New release published: '${{ steps.release.outputs.new_release_published }}'" | tee -a $GITHUB_STEP_SUMMARY
|
||||||
echo "🔖 New release version: '${{ steps.release.outputs.new_release_version }}'" | tee -a $GITHUB_STEP_SUMMARY
|
echo "🔖 New release version: '${{ steps.release.outputs.new_release_version }}'" | tee -a $GITHUB_STEP_SUMMARY
|
||||||
echo "🔖 New release channel: '${{ steps.release.outputs.new_release_channel }}'" | tee -a $GITHUB_STEP_SUMMARY
|
echo "🔖 New release channel: '${{ steps.release.outputs.new_release_channel }}'" | tee -a $GITHUB_STEP_SUMMARY
|
||||||
echo "🔖 New release git tag: '${{ steps.release.outputs.new_release_git_tag }}'" | tee -a $GITHUB_STEP_SUMMARY
|
echo "🔖 New release git tag: '${{ steps.release.outputs.new_release_git_tag }}'" | tee -a $GITHUB_STEP_SUMMARY
|
||||||
|
|
||||||
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
|
|
||||||
fi
|
|
||||||
|
|
||||||
merge-to:
|
merge-to-develop:
|
||||||
if: needs.release.outputs.merge_to != ''
|
if: needs.release.outputs.released == 'true'
|
||||||
needs: release
|
needs: release
|
||||||
name: 🔀 Merge to ${{ needs.release.outputs.merge_to }}
|
name: 🔀 Merge to develop
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
permissions:
|
permissions:
|
||||||
contents: write
|
contents: write
|
||||||
steps:
|
steps:
|
||||||
- name: 🚚 Checkout (${{ needs.release.outputs.merge_to }})
|
- name: 🚚 Checkout (develop)
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v4
|
||||||
with:
|
with:
|
||||||
ref: ${{ needs.release.outputs.merge_to }}
|
ref: develop
|
||||||
fetch-depth: 0
|
fetch-depth: 0
|
||||||
- name: 🔀 Merge '${{ needs.release.outputs.tag }}' into '${{ needs.release.outputs.merge_to }}'
|
- name: 🔀 Merge '${{ needs.release.outputs.tag }}' into 'develop'
|
||||||
run: |
|
run: |
|
||||||
git config --local user.email "github-actions[bot]@users.noreply.github.com"
|
git config --local user.email "github-actions[bot]@users.noreply.github.com"
|
||||||
git config --local user.name "github-actions[bot]"
|
git config --local user.name "github-actions[bot]"
|
||||||
|
|
||||||
git merge ${{ needs.release.outputs.tag }}
|
git merge ${{ needs.release.outputs.tag }}
|
||||||
git push origin ${{ needs.release.outputs.merge_to }}
|
git push origin develop
|
||||||
|
|
||||||
split-to:
|
split-to-main:
|
||||||
if: needs.release.outputs.split_to != ''
|
if: needs.release.outputs.released == 'true'
|
||||||
needs: release
|
needs: release
|
||||||
name: 🔀 Split package to ${{ needs.release.outputs.split_to }}
|
name: 🔀 Split package
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
permissions:
|
permissions:
|
||||||
contents: write
|
contents: write
|
||||||
@@ -94,10 +78,9 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
ref: ${{ needs.release.outputs.tag }}
|
ref: ${{ needs.release.outputs.tag }}
|
||||||
fetch-depth: 0
|
fetch-depth: 0
|
||||||
- name: 🔀 Split subtree 'Packages/src' to '${{ needs.release.outputs.split_to }}'
|
- name: 🔀 Split subtree 'Packages/src' to 'main'
|
||||||
run: |
|
run: |
|
||||||
split_to=${{ needs.release.outputs.split_to }}
|
git branch main origin/main
|
||||||
git branch $split_to origin/$split_to
|
git subtree split --prefix=Packages/src --branch main
|
||||||
git subtree split --prefix=Packages/src --branch $split_to
|
git tag ${{ needs.release.outputs.version }} main
|
||||||
git tag ${{ needs.release.outputs.version }} $split_to
|
git push origin ${{ needs.release.outputs.version }} main:main
|
||||||
git push origin ${{ needs.release.outputs.version }} $split_to:$split_to
|
|
||||||
|
|||||||
3
.github/workflows/test.yml
vendored
3
.github/workflows/test.yml
vendored
@@ -15,8 +15,7 @@ on:
|
|||||||
push:
|
push:
|
||||||
branches:
|
branches:
|
||||||
- develop
|
- develop
|
||||||
- develop-preview
|
- develop_v5
|
||||||
- develop-4.x
|
|
||||||
tags:
|
tags:
|
||||||
- "!*"
|
- "!*"
|
||||||
paths-ignore:
|
paths-ignore:
|
||||||
|
|||||||
1
.gitignore
vendored
1
.gitignore
vendored
@@ -28,4 +28,3 @@ Assets/Plugins/
|
|||||||
obj/
|
obj/
|
||||||
bin/
|
bin/
|
||||||
UserSettings/
|
UserSettings/
|
||||||
*.app
|
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -1,42 +0,0 @@
|
|||||||
%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: []
|
|
||||||
Binary file not shown.
|
Before Width: | Height: | Size: 27 KiB |
@@ -1,147 +0,0 @@
|
|||||||
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:
|
|
||||||
@@ -1,177 +0,0 @@
|
|||||||
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
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,10 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: 6b5e4f608f0684d10a4673a7e1cee0f3
|
|
||||||
ShaderImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
defaultTextures: []
|
|
||||||
nonModifiableTextures: []
|
|
||||||
preprocessorOverride: 0
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
||||||
@@ -1,42 +0,0 @@
|
|||||||
%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: []
|
|
||||||
@@ -1,42 +0,0 @@
|
|||||||
%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: []
|
|
||||||
@@ -1,8 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: 4c756ed674dab453eb1d0a7d9360a9c1
|
|
||||||
NativeFormatImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
mainObjectFileID: 2100000
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
||||||
Binary file not shown.
|
Before Width: | Height: | Size: 15 KiB |
@@ -1,147 +0,0 @@
|
|||||||
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:
|
|
||||||
@@ -1,42 +0,0 @@
|
|||||||
%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: []
|
|
||||||
@@ -1,8 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: bce3318d54bae4f99a2cb35bd8c456b0
|
|
||||||
NativeFormatImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
mainObjectFileID: 2100000
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
||||||
Binary file not shown.
|
Before Width: | Height: | Size: 8.5 KiB |
@@ -1,147 +0,0 @@
|
|||||||
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,6 +1,10 @@
|
|||||||
{
|
{
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"com.unity.ide.rider": "3.0.31",
|
"com.unity.ide.rider": "3.0.27",
|
||||||
|
"com.coffee.development": "https://github.com/mob-sakai/Coffee.Internal.git?path=Packages/Development",
|
||||||
|
"com.coffee.nano-monitor": "https://github.com/mob-sakai/Coffee.Internal.git?path=Packages/NanoMonitor",
|
||||||
|
"com.coffee.simple-scene-navigator": "https://github.com/mob-sakai/Coffee.Internal.git?path=Packages/SceneNavigator",
|
||||||
|
"com.coffee.sub-asset-editor": "https://github.com/mob-sakai/SubAssetEditor.git",
|
||||||
"com.unity.test-framework": "1.1.33",
|
"com.unity.test-framework": "1.1.33",
|
||||||
"com.unity.modules.animation": "1.0.0",
|
"com.unity.modules.animation": "1.0.0",
|
||||||
"com.unity.modules.physics": "1.0.0"
|
"com.unity.modules.physics": "1.0.0"
|
||||||
|
|||||||
@@ -1,5 +1,37 @@
|
|||||||
{
|
{
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"com.coffee.development": {
|
||||||
|
"version": "https://github.com/mob-sakai/Coffee.Internal.git?path=Packages/Development",
|
||||||
|
"depth": 0,
|
||||||
|
"source": "git",
|
||||||
|
"dependencies": {},
|
||||||
|
"hash": "41a1b604af8769b600d9c75db02ff35ec30611dc"
|
||||||
|
},
|
||||||
|
"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": "41a1b604af8769b600d9c75db02ff35ec30611dc"
|
||||||
|
},
|
||||||
|
"com.coffee.simple-scene-navigator": {
|
||||||
|
"version": "https://github.com/mob-sakai/Coffee.Internal.git?path=Packages/SceneNavigator",
|
||||||
|
"depth": 0,
|
||||||
|
"source": "git",
|
||||||
|
"dependencies": {
|
||||||
|
"com.unity.ugui": "1.0.0"
|
||||||
|
},
|
||||||
|
"hash": "41a1b604af8769b600d9c75db02ff35ec30611dc"
|
||||||
|
},
|
||||||
|
"com.coffee.sub-asset-editor": {
|
||||||
|
"version": "https://github.com/mob-sakai/SubAssetEditor.git",
|
||||||
|
"depth": 0,
|
||||||
|
"source": "git",
|
||||||
|
"dependencies": {},
|
||||||
|
"hash": "01464178eec1e4dbe741c11c9baeb94a151c99ee"
|
||||||
|
},
|
||||||
"com.coffee.ui-particle": {
|
"com.coffee.ui-particle": {
|
||||||
"version": "file:src",
|
"version": "file:src",
|
||||||
"depth": 0,
|
"depth": 0,
|
||||||
@@ -17,7 +49,7 @@
|
|||||||
"url": "https://packages.unity.com"
|
"url": "https://packages.unity.com"
|
||||||
},
|
},
|
||||||
"com.unity.ide.rider": {
|
"com.unity.ide.rider": {
|
||||||
"version": "3.0.31",
|
"version": "3.0.27",
|
||||||
"depth": 0,
|
"depth": 0,
|
||||||
"source": "registry",
|
"source": "registry",
|
||||||
"dependencies": {
|
"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
|
||||||
@@ -1,10 +1,9 @@
|
|||||||
{
|
{
|
||||||
"branches": [
|
"branches": [
|
||||||
"release",
|
"release",
|
||||||
"release-4.x",
|
|
||||||
{
|
{
|
||||||
"name": "release-preview",
|
"name": "preview",
|
||||||
"prerelease": "preview"
|
"prerelease": true
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"plugins": [
|
"plugins": [
|
||||||
|
|||||||
@@ -1,83 +1,3 @@
|
|||||||
## [4.8.1](https://github.com/mob-sakai/ParticleEffectForUGUI/compare/v4.8.0...v4.8.1) (2024-06-27)
|
|
||||||
|
|
||||||
|
|
||||||
### Bug Fixes
|
|
||||||
|
|
||||||
* remove debug code ([669deb4](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/669deb41d4ac589d9db93b29bc8e95383e7f28a5))
|
|
||||||
|
|
||||||
# [4.8.0](https://github.com/mob-sakai/ParticleEffectForUGUI/compare/v4.7.2...v4.8.0) (2024-06-27)
|
|
||||||
|
|
||||||
|
|
||||||
### Bug Fixes
|
|
||||||
|
|
||||||
* generated baking-camera object remains in the prefab or scene (again) ([de35cba](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/de35cba34c6312c1405ed522e9927c620c78e72d))
|
|
||||||
* SetParticleSystemInstance/Prefab APIs destroy generated objects ([ae3f3a8](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/ae3f3a8e62cc733420354d237ab765ac777127c8))
|
|
||||||
|
|
||||||
|
|
||||||
### Features
|
|
||||||
|
|
||||||
* add 'custom view' option. ([a703c29](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/a703c2921ca08c2280d0c8fde01e4c0b33b5c69e))
|
|
||||||
* remove overlay window (editor) ([8358170](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/835817049f4fcf00dd2bf98dbada14f041ad3544))
|
|
||||||
* restore `Transform.localScale` when setting `autoScalingMode` to something other than `Transform` (again) ([88a970d](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/88a970d93a2b69cf011d86bd1807569e90538e0e))
|
|
||||||
* the rendering order list in inspector is now more compact ([be90172](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/be901724e064befacf617f4940b0331e1d31e1ca))
|
|
||||||
|
|
||||||
## [4.7.2](https://github.com/mob-sakai/ParticleEffectForUGUI/compare/v4.7.1...v4.7.2) (2024-06-21)
|
|
||||||
|
|
||||||
|
|
||||||
### Bug Fixes
|
|
||||||
|
|
||||||
* generated baking-camera object remains in the prefab or scene ([0bb8438](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/0bb843830197d8c1252232928becc211c0ada08d))
|
|
||||||
|
|
||||||
## [4.7.1](https://github.com/mob-sakai/ParticleEffectForUGUI/compare/v4.7.0...v4.7.1) (2024-06-20)
|
|
||||||
|
|
||||||
|
|
||||||
### Bug Fixes
|
|
||||||
|
|
||||||
* despite not using the size module, particles become smaller based on their z position ([a8ed6e6](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/a8ed6e68584e1d9e45ed852eefcc03979ea7e0e1)), closes [#316](https://github.com/mob-sakai/ParticleEffectForUGUI/issues/316)
|
|
||||||
|
|
||||||
# [4.7.0](https://github.com/mob-sakai/ParticleEffectForUGUI/compare/v4.6.8...v4.7.0) (2024-06-19)
|
|
||||||
|
|
||||||
|
|
||||||
### Bug Fixes
|
|
||||||
|
|
||||||
* `UIParticle.transform.localScale` does not scale particles ([1d40e24](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/1d40e24c742741e97f03c55468ccb1e505341133)), closes [#313](https://github.com/mob-sakai/ParticleEffectForUGUI/issues/313)
|
|
||||||
* UIParticle is scaled by canvas size even when `AutoScalingMode.None` and `ScalingMode.Local` ([54a4b1c](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/54a4b1cdfd06400c7be89c1ee704bb42a659c7c2)), closes [#313](https://github.com/mob-sakai/ParticleEffectForUGUI/issues/313)
|
|
||||||
* UIParticle is scaled incorrectly with nested canvases ([f26920f](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/f26920f9825547222a4afbb31cc5dc5a002c3e9b)), closes [#313](https://github.com/mob-sakai/ParticleEffectForUGUI/issues/313)
|
|
||||||
|
|
||||||
|
|
||||||
### Features
|
|
||||||
|
|
||||||
* reset previous position on start play for world space simulation ([3880484](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/3880484ce5190c42fc79c81d0b69e3fbeda09dd0)), closes [#303](https://github.com/mob-sakai/ParticleEffectForUGUI/issues/303)
|
|
||||||
* restore `Transform.localScale` when setting `autoScalingMode` to something other than `Transform` ([5505247](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/5505247a94a929ff89635fde512a9b95691e0043))
|
|
||||||
|
|
||||||
## [4.6.8](https://github.com/mob-sakai/ParticleEffectForUGUI/compare/v4.6.7...v4.6.8) (2024-06-14)
|
|
||||||
|
|
||||||
|
|
||||||
### Bug Fixes
|
|
||||||
|
|
||||||
* 'Resource ID out of range in GetResource' error in overlay rendering mode ([05286ce](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/05286cedfd17b1a0cb90a5e918513644f47cd831)), closes [#308](https://github.com/mob-sakai/ParticleEffectForUGUI/issues/308)
|
|
||||||
|
|
||||||
## [4.6.7](https://github.com/mob-sakai/ParticleEffectForUGUI/compare/v4.6.6...v4.6.7) (2024-05-24)
|
|
||||||
|
|
||||||
|
|
||||||
### Bug Fixes
|
|
||||||
|
|
||||||
* the ParticleSystem's localPosition drifts at certain scales due to floating-point precision issues ([e924eb4](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/e924eb45968a112347471cabaeabc274e4c37ce4)), closes [#299](https://github.com/mob-sakai/ParticleEffectForUGUI/issues/299) [#312](https://github.com/mob-sakai/ParticleEffectForUGUI/issues/312)
|
|
||||||
|
|
||||||
## [4.6.6](https://github.com/mob-sakai/ParticleEffectForUGUI/compare/v4.6.5...v4.6.6) (2024-05-23)
|
|
||||||
|
|
||||||
|
|
||||||
### Bug Fixes
|
|
||||||
|
|
||||||
* fix release workflow ([30b0076](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/30b00762f6da166c043587798b1552f27b4cc604))
|
|
||||||
|
|
||||||
## [4.6.5](https://github.com/mob-sakai/ParticleEffectForUGUI/compare/v4.6.4...v4.6.5) (2024-05-23)
|
|
||||||
|
|
||||||
|
|
||||||
### Bug Fixes
|
|
||||||
|
|
||||||
* update workflows (for preview and v4) ([3eab097](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/3eab0979b9b85919b804442ab05735b7120eade5))
|
|
||||||
|
|
||||||
## [4.6.4](https://github.com/mob-sakai/ParticleEffectForUGUI/compare/v4.6.3...v4.6.4) (2024-05-22)
|
## [4.6.4](https://github.com/mob-sakai/ParticleEffectForUGUI/compare/v4.6.3...v4.6.4) (2024-05-22)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -31,35 +31,35 @@ namespace Coffee.UIExtensions
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
result.Aggregate(s_Sb, (a, b) =>
|
result.Aggregate(s_Sb, (a, b) => s_Sb.AppendFormat("{0}, ", b));
|
||||||
{
|
|
||||||
s_Sb.Append(b);
|
|
||||||
return s_Sb.Append(", ");
|
|
||||||
});
|
|
||||||
s_Sb.Length -= 2;
|
s_Sb.Length -= 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
return s_Sb.ToString();
|
return s_Sb.ToString();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void Draw(SerializedProperty sp, List<Material> mats)
|
public static void Draw(SerializedProperty sp, Material[] mats)
|
||||||
{
|
{
|
||||||
var pos = EditorGUILayout.GetControlRect(true);
|
bool isClicked;
|
||||||
var label = new GUIContent(sp.displayName, sp.tooltip);
|
using (new EditorGUILayout.HorizontalScope(GUILayout.ExpandWidth(false)))
|
||||||
var rect = EditorGUI.PrefixLabel(pos, label);
|
{
|
||||||
var text = sp.hasMultipleDifferentValues
|
var pos = EditorGUILayout.GetControlRect(true);
|
||||||
? "-"
|
var label = new GUIContent(sp.displayName, sp.tooltip);
|
||||||
: CollectActiveNames(sp, s_ActiveNames);
|
var rect = EditorGUI.PrefixLabel(pos, label);
|
||||||
|
var text = sp.hasMultipleDifferentValues
|
||||||
|
? "-"
|
||||||
|
: CollectActiveNames(sp, s_ActiveNames);
|
||||||
|
isClicked = GUI.Button(rect, text, EditorStyles.popup);
|
||||||
|
}
|
||||||
|
|
||||||
if (!GUI.Button(rect, text, EditorStyles.popup)) return;
|
if (!isClicked) return;
|
||||||
|
|
||||||
var gm = new GenericMenu();
|
var gm = new GenericMenu();
|
||||||
gm.AddItem(s_ContentNothing, s_ActiveNames.Count == 0, x =>
|
gm.AddItem(s_ContentNothing, s_ActiveNames.Count == 0, () =>
|
||||||
{
|
{
|
||||||
var current = (SerializedProperty)x;
|
sp.ClearArray();
|
||||||
current.ClearArray();
|
sp.serializedObject.ApplyModifiedProperties();
|
||||||
current.serializedObject.ApplyModifiedProperties();
|
});
|
||||||
}, sp);
|
|
||||||
|
|
||||||
if (!sp.hasMultipleDifferentValues)
|
if (!sp.hasMultipleDifferentValues)
|
||||||
{
|
{
|
||||||
@@ -73,7 +73,7 @@ namespace Coffee.UIExtensions
|
|||||||
}
|
}
|
||||||
|
|
||||||
s_Names.Clear();
|
s_Names.Clear();
|
||||||
for (var j = 0; j < mats.Count; j++)
|
for (var j = 0; j < mats.Length; j++)
|
||||||
{
|
{
|
||||||
var mat = mats[j];
|
var mat = mats[j];
|
||||||
if (!mat || !mat.shader) continue;
|
if (!mat || !mat.shader) continue;
|
||||||
@@ -82,7 +82,8 @@ namespace Coffee.UIExtensions
|
|||||||
{
|
{
|
||||||
var name = ShaderUtil.GetPropertyName(mat.shader, i);
|
var name = ShaderUtil.GetPropertyName(mat.shader, i);
|
||||||
var type = (AnimatableProperty.ShaderPropertyType)ShaderUtil.GetPropertyType(mat.shader, i);
|
var type = (AnimatableProperty.ShaderPropertyType)ShaderUtil.GetPropertyType(mat.shader, i);
|
||||||
if (!s_Names.Add(name)) continue;
|
if (s_Names.Contains(name)) continue;
|
||||||
|
s_Names.Add(name);
|
||||||
|
|
||||||
AddMenu(gm, sp, new ShaderProperty(name, type), true);
|
AddMenu(gm, sp, new ShaderProperty(name, type), true);
|
||||||
|
|
||||||
|
|||||||
3
Packages/src/Editor/AssetModification.meta
Normal file
3
Packages/src/Editor/AssetModification.meta
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 1006234332be4f329fc1830319b31aaa
|
||||||
|
timeCreated: 1704502465
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
using Coffee.UIExtensions;
|
||||||
|
using Coffee.UIParticleInternal.AssetModification;
|
||||||
|
using UnityEditor;
|
||||||
|
|
||||||
|
#pragma warning disable CS0612 // Type or member is obsolete
|
||||||
|
|
||||||
|
namespace Coffee.UIParticleInternal
|
||||||
|
{
|
||||||
|
internal class UIParticleComponentModifier_AbsoluteMode : ComponentModifier<UIParticle>
|
||||||
|
{
|
||||||
|
protected override bool ModifyComponent(UIParticle uip, bool dryRun)
|
||||||
|
{
|
||||||
|
if (!uip.m_AbsoluteMode) return false;
|
||||||
|
|
||||||
|
uip.m_AbsoluteMode = false;
|
||||||
|
uip.positionMode = UIParticle.PositionMode.Absolute;
|
||||||
|
|
||||||
|
if (!dryRun)
|
||||||
|
{
|
||||||
|
EditorUtility.SetDirty(uip);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string Report()
|
||||||
|
{
|
||||||
|
return " -> UIParticle.absoluteMode is obsolete. Use UIParticle.positionMode instead.\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
fileFormatVersion: 2
|
fileFormatVersion: 2
|
||||||
guid: b0beae5bb1cb142b9ab90dc0d371f026
|
guid: d3378b5e701274218b04cb5588b8a3bd
|
||||||
MonoImporter:
|
MonoImporter:
|
||||||
externalObjects: {}
|
externalObjects: {}
|
||||||
serializedVersion: 2
|
serializedVersion: 2
|
||||||
@@ -0,0 +1,36 @@
|
|||||||
|
using Coffee.UIExtensions;
|
||||||
|
using Coffee.UIParticleInternal.AssetModification;
|
||||||
|
using UnityEditor;
|
||||||
|
using UnityEngine;
|
||||||
|
|
||||||
|
#pragma warning disable CS0612 // Type or member is obsolete
|
||||||
|
|
||||||
|
namespace Coffee.UIParticleInternal
|
||||||
|
{
|
||||||
|
internal class UIParticleComponentModifier_AutoScaling : ComponentModifier<UIParticle>
|
||||||
|
{
|
||||||
|
protected override bool ModifyComponent(UIParticle uip, bool dryRun)
|
||||||
|
{
|
||||||
|
if (!uip.m_AutoScaling) return false;
|
||||||
|
|
||||||
|
uip.m_AutoScaling = false;
|
||||||
|
uip.autoScalingMode = UIParticle.AutoScalingMode.Transform;
|
||||||
|
uip.transform.localScale = Vector3.one;
|
||||||
|
|
||||||
|
if (!dryRun)
|
||||||
|
{
|
||||||
|
EditorUtility.SetDirty(uip);
|
||||||
|
EditorUtility.SetDirty(uip.transform);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string Report()
|
||||||
|
{
|
||||||
|
return
|
||||||
|
" -> UIParticle.ignoreCanvasScaler and UIParticle.autoScaling are obsolete." +
|
||||||
|
" Use UIParticle.autoScalingMode instead.\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
fileFormatVersion: 2
|
fileFormatVersion: 2
|
||||||
guid: d188d31b140094ebc84a9caafbc7ac71
|
guid: 3d6d0ca7ae8c641aa98b66fd91c05264
|
||||||
MonoImporter:
|
MonoImporter:
|
||||||
externalObjects: {}
|
externalObjects: {}
|
||||||
serializedVersion: 2
|
serializedVersion: 2
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
using Coffee.UIExtensions;
|
||||||
|
using Coffee.UIParticleInternal.AssetModification;
|
||||||
|
using UnityEditor;
|
||||||
|
using UnityEngine;
|
||||||
|
|
||||||
|
#pragma warning disable CS0612 // Type or member is obsolete
|
||||||
|
|
||||||
|
namespace Coffee.UIParticleInternal
|
||||||
|
{
|
||||||
|
internal class UIParticleComponentModifier_IsTrail : ComponentModifier<UIParticle>
|
||||||
|
{
|
||||||
|
protected override bool ModifyComponent(UIParticle uip, bool dryRun)
|
||||||
|
{
|
||||||
|
if (!uip.m_IsTrail) return false;
|
||||||
|
|
||||||
|
if (!dryRun)
|
||||||
|
{
|
||||||
|
var go = uip.gameObject;
|
||||||
|
Object.DestroyImmediate(uip);
|
||||||
|
EditorUtility.SetDirty(go);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string Report()
|
||||||
|
{
|
||||||
|
return " -> UIParticle for trail is no longer needed. Removed.";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: dfbc9e244a2a040179e7f5b58ec0b978
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
@@ -0,0 +1,45 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using Coffee.UIParticleInternal.AssetModification;
|
||||||
|
using UnityEditor;
|
||||||
|
|
||||||
|
namespace Coffee.UIParticleInternal
|
||||||
|
{
|
||||||
|
internal class UIParticleModifierRunner : Runner
|
||||||
|
{
|
||||||
|
public UIParticleModifierRunner()
|
||||||
|
: base("UIParticle v5", new List<(string, Func<string, Modifier>)>
|
||||||
|
{
|
||||||
|
(".unity", x => new SceneModifier
|
||||||
|
{
|
||||||
|
path = x,
|
||||||
|
componentModifiers = new IComponentModifier[]
|
||||||
|
{
|
||||||
|
new UIParticleRendererComponentModifier(),
|
||||||
|
new UIParticleComponentModifier_AutoScaling(),
|
||||||
|
new UIParticleComponentModifier_AbsoluteMode(),
|
||||||
|
new UIParticleComponentModifier_IsTrail()
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
(".prefab", x => new PrefabModifier
|
||||||
|
{
|
||||||
|
path = x,
|
||||||
|
componentModifiers = new IComponentModifier[]
|
||||||
|
{
|
||||||
|
new UIParticleRendererComponentModifier(),
|
||||||
|
new UIParticleComponentModifier_AutoScaling(),
|
||||||
|
new UIParticleComponentModifier_AbsoluteMode(),
|
||||||
|
new UIParticleComponentModifier_IsTrail()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
[MenuItem("UIParticleModifierRunner/Run")]
|
||||||
|
private static void Run()
|
||||||
|
{
|
||||||
|
new UIParticleModifierRunner().RunIfUserWantsTo();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: edd678db452e49869caeca7e7d269e5d
|
||||||
|
timeCreated: 1704502476
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
using Coffee.UIExtensions;
|
||||||
|
using Coffee.UIParticleInternal.AssetModification;
|
||||||
|
using UnityEditor;
|
||||||
|
using UnityEngine;
|
||||||
|
|
||||||
|
namespace Coffee.UIParticleInternal
|
||||||
|
{
|
||||||
|
internal class UIParticleRendererComponentModifier : ComponentModifier<UIParticleRenderer>
|
||||||
|
{
|
||||||
|
protected override bool ModifyComponent(UIParticleRenderer c, bool dryRun)
|
||||||
|
{
|
||||||
|
if (c.hideFlags.HasFlag(HideFlags.DontSave | HideFlags.NotEditable)) return false;
|
||||||
|
|
||||||
|
if (!dryRun)
|
||||||
|
{
|
||||||
|
var go = c.gameObject;
|
||||||
|
Object.DestroyImmediate(c);
|
||||||
|
EditorUtility.SetDirty(go);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string Report()
|
||||||
|
{
|
||||||
|
return " -> UIParticleRenderer component is now auto-generated object. Remove them.\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: b2a025408e4a7486a941102775d2c73b
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
fileFormatVersion: 2
|
fileFormatVersion: 2
|
||||||
guid: 157d70e6cb69d4581b4ed450c7ffd33d
|
guid: 3e440931f761e4e888510a4e6045287a
|
||||||
folderAsset: yes
|
folderAsset: yes
|
||||||
DefaultImporter:
|
DefaultImporter:
|
||||||
externalObjects: {}
|
externalObjects: {}
|
||||||
@@ -1,5 +1,6 @@
|
|||||||
fileFormatVersion: 2
|
fileFormatVersion: 2
|
||||||
guid: dfba9a6f2258941f5b4429fba806d8e9
|
guid: 269bcefd175184eebbfa31421171fadf
|
||||||
|
folderAsset: yes
|
||||||
DefaultImporter:
|
DefaultImporter:
|
||||||
externalObjects: {}
|
externalObjects: {}
|
||||||
userData:
|
userData:
|
||||||
@@ -0,0 +1,33 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
|
using UnityEditor;
|
||||||
|
using UnityEngine;
|
||||||
|
|
||||||
|
namespace Coffee.UIParticleInternal.AssetModification
|
||||||
|
{
|
||||||
|
internal abstract class ComponentModifier<T> : IComponentModifier where T : Component
|
||||||
|
{
|
||||||
|
private static readonly List<T> s_Components = new List<T>();
|
||||||
|
|
||||||
|
public bool isModified { get; private set; }
|
||||||
|
|
||||||
|
public bool ModifyComponent(GameObject root, bool dryRun)
|
||||||
|
{
|
||||||
|
root.GetComponentsInChildren(true, s_Components);
|
||||||
|
foreach (var c in s_Components)
|
||||||
|
{
|
||||||
|
if (PrefabUtility.IsPartOfAnyPrefab(c.gameObject)) continue;
|
||||||
|
|
||||||
|
if (ModifyComponent(c, dryRun))
|
||||||
|
{
|
||||||
|
isModified = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return isModified;
|
||||||
|
}
|
||||||
|
|
||||||
|
public abstract string Report();
|
||||||
|
|
||||||
|
protected abstract bool ModifyComponent(T component, bool dryRun);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 338da2d8cec784add924489fc4a7bb01
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
@@ -0,0 +1,43 @@
|
|||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using UnityEngine;
|
||||||
|
|
||||||
|
namespace Coffee.UIParticleInternal.AssetModification
|
||||||
|
{
|
||||||
|
internal abstract class GameObjectModifier : Modifier
|
||||||
|
{
|
||||||
|
private static readonly StringBuilder s_ReportLog = new StringBuilder();
|
||||||
|
public IComponentModifier[] componentModifiers;
|
||||||
|
|
||||||
|
protected bool ModifyGameObject(GameObject root, bool dryRun)
|
||||||
|
{
|
||||||
|
foreach (var modifier in componentModifiers)
|
||||||
|
{
|
||||||
|
modifier.ModifyComponent(root, dryRun);
|
||||||
|
}
|
||||||
|
|
||||||
|
return componentModifiers.Any(x => x.isModified);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override string ModificationReport()
|
||||||
|
{
|
||||||
|
if (!hasUpgraded) return string.Empty;
|
||||||
|
|
||||||
|
s_ReportLog.Length = 0;
|
||||||
|
foreach (var componentModifier in componentModifiers)
|
||||||
|
{
|
||||||
|
if (componentModifier.isModified)
|
||||||
|
{
|
||||||
|
s_ReportLog.Append(componentModifier.Report());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (0 < s_ReportLog.Length)
|
||||||
|
{
|
||||||
|
s_ReportLog.Length--;
|
||||||
|
}
|
||||||
|
|
||||||
|
return s_ReportLog.ToString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: f16bc447ca4934ca3b9329d1d870440a
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
using UnityEngine;
|
||||||
|
|
||||||
|
namespace Coffee.UIParticleInternal.AssetModification
|
||||||
|
{
|
||||||
|
internal interface IComponentModifier
|
||||||
|
{
|
||||||
|
bool isModified { get; }
|
||||||
|
bool ModifyComponent(GameObject root, bool dryRun);
|
||||||
|
string Report();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 1e50323d0799f4daf8ef476f7bf403a4
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace Coffee.UIParticleInternal.AssetModification
|
||||||
|
{
|
||||||
|
internal interface ITextModifier
|
||||||
|
{
|
||||||
|
bool ModifyText(StringBuilder sb, string text);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 2ad967b4f039b4deba09ed0c1401cf83
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
41
Packages/src/Editor/Internal/AssetModification/Modifier.cs
Normal file
41
Packages/src/Editor/Internal/AssetModification/Modifier.cs
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
using System;
|
||||||
|
|
||||||
|
namespace Coffee.UIParticleInternal.AssetModification
|
||||||
|
{
|
||||||
|
internal abstract class Modifier
|
||||||
|
{
|
||||||
|
private string _error;
|
||||||
|
public string path;
|
||||||
|
|
||||||
|
protected abstract string id { get; }
|
||||||
|
protected bool hasUpgraded { private set; get; }
|
||||||
|
|
||||||
|
public void Modify(bool dryRun)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
hasUpgraded = RunModify(dryRun);
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
_error = e.Message;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public string GetModificationReport()
|
||||||
|
{
|
||||||
|
return !string.IsNullOrEmpty(_error)
|
||||||
|
? $"<b><color=red>[{id} (Error)]</color> {path}</b> {_error}\n"
|
||||||
|
: hasUpgraded
|
||||||
|
? $"<b><color=green>[{id}]</color> {path}</b> {ModificationReport()}\n"
|
||||||
|
: string.Empty;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected abstract bool RunModify(bool dryRun);
|
||||||
|
|
||||||
|
protected virtual string ModificationReport()
|
||||||
|
{
|
||||||
|
return string.Empty;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: c716fe53d75054d309923c577f5059a4
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
@@ -0,0 +1,48 @@
|
|||||||
|
using System;
|
||||||
|
using UnityEditor;
|
||||||
|
using UnityEngine;
|
||||||
|
|
||||||
|
namespace Coffee.UIParticleInternal.AssetModification
|
||||||
|
{
|
||||||
|
internal class PrefabModifier : GameObjectModifier
|
||||||
|
{
|
||||||
|
protected override string id => "Prefab";
|
||||||
|
|
||||||
|
protected override bool RunModify(bool dryRun)
|
||||||
|
{
|
||||||
|
using (var scope = new EditScope(path))
|
||||||
|
{
|
||||||
|
var changed = ModifyGameObject(scope.root, dryRun);
|
||||||
|
|
||||||
|
if (!dryRun && changed)
|
||||||
|
{
|
||||||
|
scope.Save();
|
||||||
|
}
|
||||||
|
|
||||||
|
return changed;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private readonly struct EditScope : IDisposable
|
||||||
|
{
|
||||||
|
private readonly string _path;
|
||||||
|
public readonly GameObject root;
|
||||||
|
|
||||||
|
public EditScope(string path)
|
||||||
|
{
|
||||||
|
_path = path;
|
||||||
|
root = PrefabUtility.LoadPrefabContents(path);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
PrefabUtility.UnloadPrefabContents(root);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Save()
|
||||||
|
{
|
||||||
|
PrefabUtility.SaveAsPrefabAsset(root, _path);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: a50643d4fde75458cae1f0d4ef9549ad
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
97
Packages/src/Editor/Internal/AssetModification/Runner.cs
Normal file
97
Packages/src/Editor/Internal/AssetModification/Runner.cs
Normal file
@@ -0,0 +1,97 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using UnityEditor;
|
||||||
|
using UnityEditor.SceneManagement;
|
||||||
|
using UnityEngine;
|
||||||
|
|
||||||
|
namespace Coffee.UIParticleInternal.AssetModification
|
||||||
|
{
|
||||||
|
internal class Runner
|
||||||
|
{
|
||||||
|
private readonly List<(string ext, Func<string, Modifier> create)> _factory;
|
||||||
|
private readonly string _name;
|
||||||
|
|
||||||
|
protected Runner(string name, List<(string ext, Func<string, Modifier> create)> factory)
|
||||||
|
{
|
||||||
|
_name = name;
|
||||||
|
_factory = factory;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Modifier CreateFromPath(string assetPath)
|
||||||
|
{
|
||||||
|
var ext = Path.GetExtension(assetPath);
|
||||||
|
return _factory
|
||||||
|
.FirstOrDefault(x => x.ext == ext)
|
||||||
|
.create?.Invoke(assetPath);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Modifier[] GetModifiers(string[] assetPaths)
|
||||||
|
{
|
||||||
|
return assetPaths
|
||||||
|
.Where(x => x.StartsWith("Assets/", StringComparison.Ordinal))
|
||||||
|
.Select(CreateFromPath)
|
||||||
|
.Where(x => x != null)
|
||||||
|
.OrderBy(x => Path.GetExtension(x.path))
|
||||||
|
.ToArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void RunIfUserWantsTo()
|
||||||
|
{
|
||||||
|
var select = EditorUtility.DisplayDialogComplex($"Upgrade {_name}",
|
||||||
|
"Upgrade all assets in this project?\n\n" +
|
||||||
|
"'Go Ahead': Upgrades all assets in this project using the old APIs. You should make a backup before proceeding.\n\n" +
|
||||||
|
"'Dry Run': Outputs the upgrade summary to the console without changing.", "I Made a Backup. Go Ahead!",
|
||||||
|
"No Thanks", "Dry Run");
|
||||||
|
if (select == 1) return;
|
||||||
|
|
||||||
|
if (!EditorSceneManager.SaveCurrentModifiedScenesIfUserWantsTo()) return;
|
||||||
|
|
||||||
|
var assetPaths = AssetDatabase.GetAllAssetPaths();
|
||||||
|
var dryRun = select == 2;
|
||||||
|
Run(assetPaths, dryRun);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Run(string[] assetPaths, bool dryRun)
|
||||||
|
{
|
||||||
|
var modifiers = GetModifiers(assetPaths);
|
||||||
|
var canceled = false;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
AssetDatabase.StartAssetEditing();
|
||||||
|
EditorSceneManager.NewScene(NewSceneSetup.EmptyScene, NewSceneMode.Single);
|
||||||
|
|
||||||
|
for (var i = 0; i < modifiers.Length; i++)
|
||||||
|
{
|
||||||
|
var percentage = (float)i / modifiers.Length;
|
||||||
|
var m = modifiers[i];
|
||||||
|
if (EditorUtility.DisplayCancelableProgressBar("Upgrading...", m.path, percentage))
|
||||||
|
{
|
||||||
|
canceled = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
m.Modify(dryRun);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
Debug.LogException(e);
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
var sb = new StringBuilder();
|
||||||
|
sb.Append(dryRun ? "<b>[DryRun]</b> " : "");
|
||||||
|
sb.AppendLine($"<b>Modify '{_name}' is {(canceled ? "canceled" : "completed")}.</b>");
|
||||||
|
sb.AppendLine("==== Modifications ====");
|
||||||
|
Debug.Log(modifiers.Aggregate(sb, (x, m) => x.Append(m.GetModificationReport())));
|
||||||
|
EditorUtility.ClearProgressBar();
|
||||||
|
AssetDatabase.StopAssetEditing();
|
||||||
|
AssetDatabase.Refresh();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: f28067cf4bfca4d92bd5262ac5c7a652
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
@@ -0,0 +1,53 @@
|
|||||||
|
using System;
|
||||||
|
using UnityEditor.SceneManagement;
|
||||||
|
using UnityEngine.SceneManagement;
|
||||||
|
|
||||||
|
namespace Coffee.UIParticleInternal.AssetModification
|
||||||
|
{
|
||||||
|
internal class SceneModifier : GameObjectModifier
|
||||||
|
{
|
||||||
|
protected override string id => "Scene";
|
||||||
|
|
||||||
|
protected override bool RunModify(bool dryRun)
|
||||||
|
{
|
||||||
|
using (var scope = new EditScope(path))
|
||||||
|
{
|
||||||
|
var changed = false;
|
||||||
|
foreach (var root in scope.scene.GetRootGameObjects())
|
||||||
|
{
|
||||||
|
if (ModifyGameObject(root, dryRun))
|
||||||
|
{
|
||||||
|
changed = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!dryRun && changed)
|
||||||
|
{
|
||||||
|
scope.Save();
|
||||||
|
}
|
||||||
|
|
||||||
|
return changed;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private readonly struct EditScope : IDisposable
|
||||||
|
{
|
||||||
|
public readonly Scene scene;
|
||||||
|
|
||||||
|
public EditScope(string path)
|
||||||
|
{
|
||||||
|
scene = EditorSceneManager.OpenScene(path, OpenSceneMode.Additive);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
EditorSceneManager.CloseScene(scene, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Save()
|
||||||
|
{
|
||||||
|
EditorSceneManager.SaveScene(scene);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 6764c0c6fd61a4f66a8b0e3467be420d
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
@@ -0,0 +1,78 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace Coffee.UIParticleInternal.AssetModification
|
||||||
|
{
|
||||||
|
internal class TextAssetModifier : Modifier
|
||||||
|
{
|
||||||
|
public ITextModifier[] textModifiers;
|
||||||
|
protected override string id => "Text";
|
||||||
|
protected virtual string savePath => path;
|
||||||
|
|
||||||
|
protected override bool RunModify(bool dryRun)
|
||||||
|
{
|
||||||
|
var changed = false;
|
||||||
|
using (var scope = new EditScope(path, savePath))
|
||||||
|
{
|
||||||
|
foreach (var line in scope.lines)
|
||||||
|
{
|
||||||
|
if (ModifyLine(scope.sb, line))
|
||||||
|
{
|
||||||
|
changed = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
scope.sb.AppendLine(line);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!dryRun && changed)
|
||||||
|
{
|
||||||
|
scope.Save();
|
||||||
|
}
|
||||||
|
|
||||||
|
return changed;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool ModifyLine(StringBuilder sb, string line)
|
||||||
|
{
|
||||||
|
foreach (var modifier in textModifiers)
|
||||||
|
{
|
||||||
|
if (modifier.ModifyText(sb, line))
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private readonly struct EditScope : IDisposable
|
||||||
|
{
|
||||||
|
private static readonly StringBuilder s_File = new StringBuilder();
|
||||||
|
private readonly string _path;
|
||||||
|
private readonly string _savePath;
|
||||||
|
public IEnumerable<string> lines => File.ReadLines(_path);
|
||||||
|
public StringBuilder sb => s_File;
|
||||||
|
|
||||||
|
public EditScope(string path, string savePath)
|
||||||
|
{
|
||||||
|
s_File.Length = 0;
|
||||||
|
_path = path;
|
||||||
|
_savePath = savePath;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Save()
|
||||||
|
{
|
||||||
|
File.WriteAllText(_savePath, sb.ToString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 431e5b95f2f5c4f19926a7fc5342e118
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
using System.Text;
|
||||||
|
using System.Text.RegularExpressions;
|
||||||
|
|
||||||
|
namespace Coffee.UIParticleInternal.AssetModification
|
||||||
|
{
|
||||||
|
internal class TextReplaceModifier : ITextModifier
|
||||||
|
{
|
||||||
|
private readonly Regex _pattern;
|
||||||
|
private readonly string _replace;
|
||||||
|
|
||||||
|
public TextReplaceModifier(string pattern, string replace)
|
||||||
|
{
|
||||||
|
_pattern = new Regex(pattern);
|
||||||
|
_replace = replace;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool ModifyText(StringBuilder sb, string text)
|
||||||
|
{
|
||||||
|
if (!_pattern.IsMatch(text)) return false;
|
||||||
|
|
||||||
|
sb.AppendLine(_pattern.Replace(text, _replace));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: afc6ba9550e5e4c25951b03db43a4fd0
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
@@ -5,9 +5,7 @@ using UnityEditor;
|
|||||||
using UnityEditor.UI;
|
using UnityEditor.UI;
|
||||||
using UnityEditorInternal;
|
using UnityEditorInternal;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
using UnityEngine.Profiling;
|
|
||||||
using UnityEngine.UI;
|
using UnityEngine.UI;
|
||||||
using Coffee.UIParticleExtensions;
|
|
||||||
#if UNITY_2021_2_OR_NEWER
|
#if UNITY_2021_2_OR_NEWER
|
||||||
using UnityEditor.Overlays;
|
using UnityEditor.Overlays;
|
||||||
#else
|
#else
|
||||||
@@ -27,24 +25,41 @@ namespace Coffee.UIExtensions
|
|||||||
[CanEditMultipleObjects]
|
[CanEditMultipleObjects]
|
||||||
internal class UIParticleEditor : GraphicEditor
|
internal class UIParticleEditor : GraphicEditor
|
||||||
{
|
{
|
||||||
|
#if UNITY_2021_2_OR_NEWER
|
||||||
|
#if UNITY_2022_1_OR_NEWER
|
||||||
|
[Overlay(typeof(SceneView), "Scene View/UI Particles", "UI Particles", true,
|
||||||
|
defaultDockPosition = DockPosition.Bottom,
|
||||||
|
defaultDockZone = DockZone.Floating,
|
||||||
|
defaultLayout = Layout.Panel)]
|
||||||
|
#else
|
||||||
|
[Overlay(typeof(SceneView), "Scene View/UI Particles", "UI Particles", true)]
|
||||||
|
#endif
|
||||||
|
private class UIParticleOverlay : IMGUIOverlay, ITransientOverlay
|
||||||
|
{
|
||||||
|
public bool visible => s_SerializedObject != null;
|
||||||
|
|
||||||
|
public override void OnGUI()
|
||||||
|
{
|
||||||
|
if (visible)
|
||||||
|
{
|
||||||
|
WindowFunction();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
//################################
|
//################################
|
||||||
// Constant or Static Members.
|
// Constant or Static Members.
|
||||||
//################################
|
//################################
|
||||||
private static readonly GUIContent[] s_ContentMaterials = new[]
|
|
||||||
{
|
|
||||||
new GUIContent("Material"),
|
|
||||||
new GUIContent("Trail Material")
|
|
||||||
};
|
|
||||||
|
|
||||||
private static readonly GUIContent s_ContentRenderingOrder = new GUIContent("Rendering Order");
|
private static readonly GUIContent s_ContentRenderingOrder = new GUIContent("Rendering Order");
|
||||||
private static readonly GUIContent s_ContentRefresh = new GUIContent("Refresh");
|
private static readonly GUIContent s_ContentRefresh = new GUIContent("Refresh");
|
||||||
private static readonly GUIContent s_ContentFix = new GUIContent("Fix");
|
private static readonly GUIContent s_ContentFix = new GUIContent("Fix");
|
||||||
|
private static readonly GUIContent s_ContentMaterial = new GUIContent("Material");
|
||||||
|
private static readonly GUIContent s_ContentTrailMaterial = new GUIContent("Trail Material");
|
||||||
private static readonly GUIContent s_Content3D = new GUIContent("3D");
|
private static readonly GUIContent s_Content3D = new GUIContent("3D");
|
||||||
private static readonly GUIContent s_ContentRandom = new GUIContent("Random");
|
private static readonly GUIContent s_ContentRandom = new GUIContent("Random");
|
||||||
private static readonly GUIContent s_ContentScale = new GUIContent("Scale");
|
private static readonly GUIContent s_ContentScale = new GUIContent("Scale");
|
||||||
private static readonly GUIContent s_ContentPrimary = new GUIContent("Primary");
|
private static SerializedObject s_SerializedObject;
|
||||||
private static readonly Regex s_RegexBuiltInGuid = new Regex(@"^0{16}.0{15}$", RegexOptions.Compiled);
|
|
||||||
private static readonly List<Material> s_TempMaterials = new List<Material>();
|
|
||||||
private static bool s_XYZMode;
|
private static bool s_XYZMode;
|
||||||
|
|
||||||
private SerializedProperty _maskable;
|
private SerializedProperty _maskable;
|
||||||
@@ -55,8 +70,6 @@ namespace Coffee.UIExtensions
|
|||||||
private SerializedProperty _groupMaxId;
|
private SerializedProperty _groupMaxId;
|
||||||
private SerializedProperty _positionMode;
|
private SerializedProperty _positionMode;
|
||||||
private SerializedProperty _autoScalingMode;
|
private SerializedProperty _autoScalingMode;
|
||||||
private SerializedProperty _useCustomView;
|
|
||||||
private SerializedProperty _customViewSize;
|
|
||||||
private ReorderableList _ro;
|
private ReorderableList _ro;
|
||||||
private bool _showMax;
|
private bool _showMax;
|
||||||
|
|
||||||
@@ -74,6 +87,56 @@ namespace Coffee.UIExtensions
|
|||||||
"_ColorMask"
|
"_ColorMask"
|
||||||
};
|
};
|
||||||
|
|
||||||
|
[InitializeOnLoadMethod]
|
||||||
|
private static void Init()
|
||||||
|
{
|
||||||
|
#if !UNITY_2021_2_OR_NEWER
|
||||||
|
var miSceneViewOverlayWindow = Type.GetType("UnityEditor.SceneViewOverlay, UnityEditor")
|
||||||
|
?.GetMethods(BindingFlags.Public | BindingFlags.Static)
|
||||||
|
.First(x => x.Name == "Window" && 5 <= x.GetParameters().Length);
|
||||||
|
var windowFunction = (Action<Object, SceneView>)WindowFunction;
|
||||||
|
var windowFunctionType = Type.GetType("UnityEditor.SceneViewOverlay+WindowFunction, UnityEditor");
|
||||||
|
var windowFunctionDelegate = Delegate.CreateDelegate(windowFunctionType, windowFunction.Method);
|
||||||
|
var windowTitle = new GUIContent(ObjectNames.NicifyVariableName(nameof(UIParticle)));
|
||||||
|
#if UNITY_2019_2_OR_NEWER
|
||||||
|
//public static void Window(GUIContent title, WindowFunction sceneViewFunc, int order, Object target, WindowDisplayOption option, EditorWindow window = null)
|
||||||
|
var sceneViewArgs = new object[] { windowTitle, windowFunctionDelegate, 599, null, 2, null };
|
||||||
|
#else
|
||||||
|
//public static void Window(GUIContent title, WindowFunction sceneViewFunc, int order, Object target, WindowDisplayOption option)
|
||||||
|
var sceneViewArgs = new object[] { windowTitle, windowFunctionDelegate, 599, null, 2 };
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if UNITY_2019_1_OR_NEWER
|
||||||
|
SceneView.duringSceneGui += _ =>
|
||||||
|
#else
|
||||||
|
SceneView.onSceneGUIDelegate += _ =>
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
if (s_SerializedObject != null)
|
||||||
|
{
|
||||||
|
miSceneViewOverlayWindow.Invoke(null, sceneViewArgs);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
|
SerializedObject CreateSerializeObject()
|
||||||
|
{
|
||||||
|
var uiParticles = Selection.gameObjects.Select(x => x.GetComponent<ParticleSystem>())
|
||||||
|
.Where(x => x)
|
||||||
|
.Select(x => x.GetComponentInParent<UIParticle>(true))
|
||||||
|
.Where(x => x && x.canvas)
|
||||||
|
.Concat(Selection.gameObjects.Select(x => x.GetComponent<UIParticle>())
|
||||||
|
.Where(x => x && x.canvas))
|
||||||
|
.Distinct()
|
||||||
|
.OfType<Object>()
|
||||||
|
.ToArray();
|
||||||
|
return 0 < uiParticles.Length ? new SerializedObject(uiParticles) : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
s_SerializedObject = CreateSerializeObject();
|
||||||
|
Selection.selectionChanged += () => s_SerializedObject = CreateSerializeObject();
|
||||||
|
}
|
||||||
|
|
||||||
//################################
|
//################################
|
||||||
// Public/Protected Members.
|
// Public/Protected Members.
|
||||||
//################################
|
//################################
|
||||||
@@ -92,43 +155,31 @@ namespace Coffee.UIExtensions
|
|||||||
_groupMaxId = serializedObject.FindProperty("m_GroupMaxId");
|
_groupMaxId = serializedObject.FindProperty("m_GroupMaxId");
|
||||||
_positionMode = serializedObject.FindProperty("m_PositionMode");
|
_positionMode = serializedObject.FindProperty("m_PositionMode");
|
||||||
_autoScalingMode = serializedObject.FindProperty("m_AutoScalingMode");
|
_autoScalingMode = serializedObject.FindProperty("m_AutoScalingMode");
|
||||||
_useCustomView = serializedObject.FindProperty("m_UseCustomView");
|
|
||||||
_customViewSize = serializedObject.FindProperty("m_CustomViewSize");
|
|
||||||
|
|
||||||
var sp = serializedObject.FindProperty("m_Particles");
|
var sp = serializedObject.FindProperty("m_Particles");
|
||||||
_ro = new ReorderableList(sp.serializedObject, sp, true, true, true, true)
|
_ro = new ReorderableList(sp.serializedObject, sp, true, true, true, true)
|
||||||
{
|
{
|
||||||
elementHeightCallback = index =>
|
elementHeight = EditorGUIUtility.singleLineHeight * 3 + 4,
|
||||||
{
|
elementHeightCallback = _ => 3 * (EditorGUIUtility.singleLineHeight + 2),
|
||||||
var ps = sp.GetArrayElementAtIndex(index).objectReferenceValue as ParticleSystem;
|
|
||||||
var materialCount = 0;
|
|
||||||
if (ps && ps.TryGetComponent<ParticleSystemRenderer>(out var psr))
|
|
||||||
{
|
|
||||||
materialCount = psr.sharedMaterials.Length;
|
|
||||||
}
|
|
||||||
|
|
||||||
return (materialCount + 1) * (EditorGUIUtility.singleLineHeight + 2);
|
|
||||||
},
|
|
||||||
drawElementCallback = (rect, index, _, __) =>
|
drawElementCallback = (rect, index, _, __) =>
|
||||||
{
|
{
|
||||||
rect.y += 2;
|
EditorGUI.BeginDisabledGroup(sp.hasMultipleDifferentValues);
|
||||||
|
rect.y += 1;
|
||||||
rect.height = EditorGUIUtility.singleLineHeight;
|
rect.height = EditorGUIUtility.singleLineHeight;
|
||||||
var p = sp.GetArrayElementAtIndex(index);
|
var p = sp.GetArrayElementAtIndex(index);
|
||||||
EditorGUI.ObjectField(rect, p, GUIContent.none);
|
EditorGUI.ObjectField(rect, p, GUIContent.none);
|
||||||
var ps = p.objectReferenceValue as ParticleSystem;
|
|
||||||
if (!ps || !ps.TryGetComponent<ParticleSystemRenderer>(out var psr)) return;
|
|
||||||
|
|
||||||
rect.x += 15;
|
rect.x += 15;
|
||||||
rect.width -= 15;
|
rect.width -= 15;
|
||||||
var materials = new SerializedObject(psr).FindProperty("m_Materials");
|
var ps = p.objectReferenceValue as ParticleSystem;
|
||||||
var count = Mathf.Min(materials.arraySize, 2);
|
var materials = ps
|
||||||
for (var i = 0; i < count; i++)
|
? new SerializedObject(ps.GetComponent<ParticleSystemRenderer>()).FindProperty("m_Materials")
|
||||||
{
|
: null;
|
||||||
rect.y += rect.height + 2;
|
rect.y += rect.height + 1;
|
||||||
EditorGUI.PropertyField(rect, materials.GetArrayElementAtIndex(i), s_ContentMaterials[i]);
|
MaterialField(rect, s_ContentMaterial, materials, 0);
|
||||||
}
|
rect.y += rect.height + 1;
|
||||||
|
MaterialField(rect, s_ContentTrailMaterial, materials, 1);
|
||||||
if (materials.serializedObject.hasModifiedProperties)
|
EditorGUI.EndDisabledGroup();
|
||||||
|
if (materials != null && materials.serializedObject.hasModifiedProperties)
|
||||||
{
|
{
|
||||||
materials.serializedObject.ApplyModifiedProperties();
|
materials.serializedObject.ApplyModifiedProperties();
|
||||||
}
|
}
|
||||||
@@ -164,6 +215,20 @@ namespace Coffee.UIExtensions
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static void MaterialField(Rect rect, GUIContent label, SerializedProperty sp, int index)
|
||||||
|
{
|
||||||
|
if (sp == null || sp.arraySize <= index)
|
||||||
|
{
|
||||||
|
EditorGUI.BeginDisabledGroup(true);
|
||||||
|
EditorGUI.ObjectField(rect, label, null, typeof(Material), true);
|
||||||
|
EditorGUI.EndDisabledGroup();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
EditorGUI.PropertyField(rect, sp.GetArrayElementAtIndex(index), label);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Implement this function to make a custom inspector.
|
/// Implement this function to make a custom inspector.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -172,7 +237,6 @@ namespace Coffee.UIExtensions
|
|||||||
var current = target as UIParticle;
|
var current = target as UIParticle;
|
||||||
if (!current) return;
|
if (!current) return;
|
||||||
|
|
||||||
Profiler.BeginSample("(UIP:E) OnInspectorGUI");
|
|
||||||
serializedObject.Update();
|
serializedObject.Update();
|
||||||
|
|
||||||
// Maskable
|
// Maskable
|
||||||
@@ -184,8 +248,13 @@ namespace Coffee.UIExtensions
|
|||||||
EditorGUI.EndDisabledGroup();
|
EditorGUI.EndDisabledGroup();
|
||||||
|
|
||||||
// AnimatableProperties
|
// AnimatableProperties
|
||||||
current.GetMaterials(s_TempMaterials);
|
var mats = current.particles
|
||||||
AnimatablePropertyEditor.Draw(_animatableProperties, s_TempMaterials);
|
.Where(x => x)
|
||||||
|
.Select(x => x.GetComponent<ParticleSystemRenderer>().sharedMaterial)
|
||||||
|
.Where(x => x)
|
||||||
|
.ToArray();
|
||||||
|
|
||||||
|
AnimatablePropertyEditor.Draw(_animatableProperties, mats);
|
||||||
|
|
||||||
// Mesh sharing
|
// Mesh sharing
|
||||||
EditorGUI.BeginChangeCheck();
|
EditorGUI.BeginChangeCheck();
|
||||||
@@ -193,12 +262,9 @@ namespace Coffee.UIExtensions
|
|||||||
if (EditorGUI.EndChangeCheck())
|
if (EditorGUI.EndChangeCheck())
|
||||||
{
|
{
|
||||||
serializedObject.ApplyModifiedProperties();
|
serializedObject.ApplyModifiedProperties();
|
||||||
foreach (var t in targets)
|
foreach (var uip in targets.OfType<UIParticle>())
|
||||||
{
|
{
|
||||||
if (t is UIParticle uip)
|
uip.ResetGroupId();
|
||||||
{
|
|
||||||
uip.ResetGroupId();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -206,29 +272,16 @@ namespace Coffee.UIExtensions
|
|||||||
EditorGUILayout.PropertyField(_positionMode);
|
EditorGUILayout.PropertyField(_positionMode);
|
||||||
|
|
||||||
// Auto Scaling
|
// Auto Scaling
|
||||||
EditorGUILayout.PropertyField(_autoScalingMode);
|
DrawAutoScaling(_autoScalingMode, targets.OfType<UIParticle>());
|
||||||
|
|
||||||
// Custom View Size
|
|
||||||
EditorGUILayout.PropertyField(_useCustomView);
|
|
||||||
EditorGUI.BeginChangeCheck();
|
|
||||||
EditorGUI.BeginDisabledGroup(!_useCustomView.boolValue);
|
|
||||||
EditorGUI.indentLevel++;
|
|
||||||
EditorGUILayout.PropertyField(_customViewSize);
|
|
||||||
EditorGUI.indentLevel--;
|
|
||||||
EditorGUI.EndDisabledGroup();
|
|
||||||
if (EditorGUI.EndChangeCheck())
|
|
||||||
{
|
|
||||||
_customViewSize.floatValue = Mathf.Max(0.1f, _customViewSize.floatValue);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Target ParticleSystems.
|
// Target ParticleSystems.
|
||||||
EditorGUI.BeginChangeCheck();
|
EditorGUI.BeginChangeCheck();
|
||||||
|
EditorGUI.BeginDisabledGroup(targets.OfType<UIParticle>().Any(x => !x.canvas));
|
||||||
_ro.DoLayoutList();
|
_ro.DoLayoutList();
|
||||||
|
EditorGUI.EndDisabledGroup();
|
||||||
serializedObject.ApplyModifiedProperties();
|
serializedObject.ApplyModifiedProperties();
|
||||||
|
|
||||||
if (EditorGUI.EndChangeCheck())
|
if (EditorGUI.EndChangeCheck())
|
||||||
{
|
{
|
||||||
EditorApplication.QueuePlayerLoopUpdate();
|
|
||||||
foreach (var uip in targets.OfType<UIParticle>())
|
foreach (var uip in targets.OfType<UIParticle>())
|
||||||
{
|
{
|
||||||
uip.RefreshParticles(uip.particles);
|
uip.RefreshParticles(uip.particles);
|
||||||
@@ -236,8 +289,7 @@ namespace Coffee.UIExtensions
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Non-UI built-in shader is not supported.
|
// Non-UI built-in shader is not supported.
|
||||||
Profiler.BeginSample("(UIP:E) Non-UI built-in shader is not supported.");
|
foreach (var mat in current.materials)
|
||||||
foreach (var mat in s_TempMaterials)
|
|
||||||
{
|
{
|
||||||
if (!mat || !mat.shader) continue;
|
if (!mat || !mat.shader) continue;
|
||||||
var shader = mat.shader;
|
var shader = mat.shader;
|
||||||
@@ -250,18 +302,15 @@ namespace Coffee.UIExtensions
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Profiler.EndSample();
|
|
||||||
|
|
||||||
// Does the shader support UI masks?
|
// Does the shader support UI masks?
|
||||||
Profiler.BeginSample("(UIP:E) Does the shader support UI masks?");
|
|
||||||
if (current.maskable && current.GetComponentInParent<Mask>(false))
|
if (current.maskable && current.GetComponentInParent<Mask>(false))
|
||||||
{
|
{
|
||||||
foreach (var mat in s_TempMaterials)
|
foreach (var mat in current.materials)
|
||||||
{
|
{
|
||||||
if (!mat || !mat.shader) continue;
|
if (!mat || !mat.shader) continue;
|
||||||
var shader = mat.shader;
|
var shader = mat.shader;
|
||||||
if (!s_Shaders.Add(shader)) continue;
|
if (s_Shaders.Contains(shader)) continue;
|
||||||
|
s_Shaders.Add(shader);
|
||||||
foreach (var propName in s_MaskablePropertyNames)
|
foreach (var propName in s_MaskablePropertyNames)
|
||||||
{
|
{
|
||||||
if (mat.HasProperty(propName)) continue;
|
if (mat.HasProperty(propName)) continue;
|
||||||
@@ -275,9 +324,7 @@ namespace Coffee.UIExtensions
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
s_TempMaterials.Clear();
|
|
||||||
s_Shaders.Clear();
|
s_Shaders.Clear();
|
||||||
Profiler.EndSample();
|
|
||||||
|
|
||||||
// UIParticle for trail should be removed.
|
// UIParticle for trail should be removed.
|
||||||
var label = "This UIParticle component should be removed. The UIParticle for trails is no longer needed.";
|
var label = "This UIParticle component should be removed. The UIParticle for trails is no longer needed.";
|
||||||
@@ -316,14 +363,12 @@ namespace Coffee.UIExtensions
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
Profiler.EndSample();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static bool IsBuiltInObject(Object obj)
|
private bool IsBuiltInObject(Object obj)
|
||||||
{
|
{
|
||||||
return AssetDatabase.IsMainAsset(obj)
|
return AssetDatabase.TryGetGUIDAndLocalFileIdentifier(obj, out var guid, out long _)
|
||||||
&& AssetDatabase.TryGetGUIDAndLocalFileIdentifier(obj, out var guid, out long _)
|
&& Regex.IsMatch(guid, "^0{16}.0{15}$", RegexOptions.Compiled);
|
||||||
&& s_RegexBuiltInGuid.IsMatch(guid);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#if UNITY_2018 || UNITY_2019
|
#if UNITY_2018 || UNITY_2019
|
||||||
@@ -417,7 +462,7 @@ namespace Coffee.UIExtensions
|
|||||||
{
|
{
|
||||||
EditorGUI.BeginDisabledGroup(true);
|
EditorGUI.BeginDisabledGroup(true);
|
||||||
var obj = UIParticleUpdater.GetPrimary(spGroupId.intValue);
|
var obj = UIParticleUpdater.GetPrimary(spGroupId.intValue);
|
||||||
EditorGUILayout.ObjectField(s_ContentPrimary, obj, typeof(UIParticle), false);
|
EditorGUILayout.ObjectField("Primary", obj, typeof(UIParticle), false);
|
||||||
EditorGUI.EndDisabledGroup();
|
EditorGUI.EndDisabledGroup();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -427,9 +472,54 @@ namespace Coffee.UIExtensions
|
|||||||
return showMax;
|
return showMax;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void DrawAutoScaling(SerializedProperty prop)
|
private static void DrawAutoScaling(SerializedProperty prop, IEnumerable<UIParticle> uiParticles)
|
||||||
{
|
{
|
||||||
|
var isTransformMode = prop.intValue == (int)UIParticle.AutoScalingMode.Transform;
|
||||||
|
EditorGUI.BeginChangeCheck();
|
||||||
EditorGUILayout.PropertyField(prop);
|
EditorGUILayout.PropertyField(prop);
|
||||||
|
if (!EditorGUI.EndChangeCheck() || !isTransformMode) return;
|
||||||
|
|
||||||
|
// on changed true->false, reset scale.
|
||||||
|
EditorApplication.delayCall += () =>
|
||||||
|
{
|
||||||
|
foreach (var uip in uiParticles)
|
||||||
|
{
|
||||||
|
if (!uip) continue;
|
||||||
|
uip.transform.localScale = Vector3.one;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#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)
|
private void DestroyUIParticle(UIParticle p, bool ignoreCurrent = false)
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
Copyright 2018-2024 mob-sakai
|
Copyright 2018-2023 mob-sakai
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
# <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)
|
# Particle Effect For UGUI (UI Particle)
|
||||||
|
|
||||||
This package provides a component to render particle effects for uGUI in Unity 2018.2 or later.
|
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.
|
The particle rendering is maskable and sortable, without the need for an extra Camera, RenderTexture, or Canvas.
|
||||||
@@ -17,36 +17,45 @@ The particle rendering is maskable and sortable, without the need for an extra C
|
|||||||
|
|
||||||
## 📝 Description
|
## 📝 Description
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
This package uses the new APIs `MeshBake/MeshTrailBake` (introduced in Unity 2018.2) to render particles through CanvasRenderer.
|
This package utilizes the new APIs `MeshBake/MashTrailBake` (introduced with Unity 2018.2) to render particles through
|
||||||
You can render, mask, and sort your ParticleSystems for UI without the need for an additional Camera, RenderTexture, or Canvas.
|
CanvasRenderer.
|
||||||
|
You can render, mask, and sort your ParticleSystems for UI without the necessity of an additional Camera, RenderTexture,
|
||||||
|
or Canvas.
|
||||||
|
|
||||||
### Key Features
|
### Features
|
||||||
|
|
||||||
* **Easy to use:** The package is ready to use out of the box.
|
* Easy to use: The package is ready to use out of the box.
|
||||||
* **Sortable:** Sort particle effects and other UI elements by sibling index.
|
* Sort particle effects and other UI by sibling index.
|
||||||
* **Maskable:** Supports `Mask` or `RectMask2D`.
|
* No extra Camera, RenderTexture, or Canvas required.
|
||||||
* **No extra components required:** No need for an additional `Camera`, `RenderTexture`, or `Canvas`.
|
* Masking options for Mask or RectMask2D.
|
||||||
* **Trail module support:** Fully supports the Trail module.
|
* Support for the Trail module.
|
||||||
* **CanvasGroup alpha support:** Integrates with `CanvasGroup` alpha.
|
* Support for CanvasGroup alpha.
|
||||||
* **No allocations:** Efficiently renders particles without allocations.
|
* No allocations needed to render particles.
|
||||||
* **Any canvas render mode support:** Works with overlay, camera space, and world space.
|
* Compatibility with overlay, camera space, and world space.
|
||||||
* **Any Render pipeline support:** Compatible with Universal Render Pipeline (URP) and High Definition Render Pipeline (HDRP).
|
* Support for Universal Render Pipeline (URP) and High Definition Render Pipeline (HDRP).
|
||||||
* **Disabling domain reload support:** Supports disabling `Enter Play Mode Options > Reload Domain`.
|
* Support for disabling `Enter Play Mode Options > Reload Domain`.
|
||||||
* **Animatable material properties:** Supports changing material properties with AnimationClip (AnimatableProperty).
|
* Support for changing material property with AnimationClip (AnimatableProperty).
|
||||||

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

|
|
||||||
|
[AnimatableProperty.gif]: https://user-images.githubusercontent.com/12690315/53286323-2d94a980-37b0-11e9-8afb-c4a207805ff2.gif
|
||||||
|
|
||||||
|
[MeshSharing.gif]: https://user-images.githubusercontent.com/12690315/174311048-c882df81-6c34-4eba-b0aa-5645457692f1.gif
|
||||||
|
|
||||||
|
[ParticleAttractor.gif]: https://user-images.githubusercontent.com/12690315/174311027-462929a4-13f0-4ec4-86ea-9c832f2eecf1.gif
|
||||||
|
|
||||||
|
[AbsolutePosition.gif]: https://user-images.githubusercontent.com/12690315/175751579-5a2357e8-2ecf-4afd-83c8-66e9771bde39.gif
|
||||||
|
|
||||||
<br><br>
|
<br><br>
|
||||||
|
|
||||||
@@ -67,55 +76,44 @@ You can render, mask, and sort your ParticleSystems for UI without the need for
|
|||||||
|
|
||||||
[JMO]: https://assetstore.unity.com/publishers/1669
|
[JMO]: https://assetstore.unity.com/publishers/1669
|
||||||
|
|
||||||
|
|
||||||
<br><br>
|
<br><br>
|
||||||
|
|
||||||
## ⚙ Installation
|
## ⚙ Installation
|
||||||
|
|
||||||
_This package requires **Unity 2018.3 or later**._
|
_This package requires Unity 2018.3 or later._
|
||||||
|
|
||||||
#### Install via OpenUPM
|
#### Install via OpenUPM
|
||||||
|
|
||||||
- This package is available on [OpenUPM](https://openupm.com) package registry.
|
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 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.8.0
|
|
||||||
```
|
|
||||||
|
|
||||||
#### Install via UPM (with Package Manager UI)
|
If you have [openupm-cli](https://github.com/openupm/openupm-cli) installed, then run the following command in your
|
||||||
|
project's directory:
|
||||||
|
|
||||||
- Click `Window > Package Manager` to open Package Manager UI.
|
```sh
|
||||||
- Click `+ > Add package from git URL...` and input the repository URL: `https://github.com/mob-sakai/ParticleEffectForUGUI.git`
|
openupm add com.coffee.ui-particle
|
||||||

|
```
|
||||||
- To update the package, change suffix `#{version}` to the target version.
|
|
||||||
- e.g. `https://github.com/mob-sakai/ParticleEffectForUGUI.git#4.8.0`
|
|
||||||
|
|
||||||
#### Install via UPM (Manually)
|
#### Install via UPM (using Git URL)
|
||||||
|
|
||||||
- Open the `Packages/manifest.json` file in your project. Then add this package somewhere in the `dependencies` block:
|
Navigate to your project's Packages folder and open the `manifest.json` file. Then add this package somewhere in
|
||||||
```json
|
the `dependencies` block:
|
||||||
{
|
|
||||||
"dependencies": {
|
```json
|
||||||
"com.coffee.ui-particle": "https://github.com/mob-sakai/ParticleEffectForUGUI.git",
|
{
|
||||||
...
|
"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.8.0",`
|
|
||||||
|
|
||||||
#### Install as Embedded Package
|
* e.g. `"com.coffee.ui-particle": "https://github.com/mob-sakai/ParticleEffectForUGUI.git#4.6.0",`
|
||||||
|
|
||||||
1. Download a source code zip file from [Releases](https://github.com/mob-sakai/ParticleEffectForUGUI.git/releases) and extract it.
|
Or, use [UpmGitExtension](https://github.com/mob-sakai/UpmGitExtension) to install and update the package.
|
||||||
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>
|
<br><br>
|
||||||
|
|
||||||
@@ -125,28 +123,19 @@ _This package requires **Unity 2018.3 or later**._
|
|||||||
|
|
||||||
`UIParticle` controls the ParticleSystems that are attached to its own game objects and child game objects.
|
`UIParticle` controls the ParticleSystems that are attached to its own game objects and child game objects.
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
- **Maskable**: Does this graphic allow maskable.
|
- **Maskable**: Does this graphic allow masking.
|
||||||
- **Scale**: Scale the rendering particles. When the `3D` toggle is enabled, 3D scale (x, y, z) is supported.
|
- **Scale**: Scale the rendering. When the `3D` toggle is enabled, 3D scale (x, y, z) is supported.
|
||||||
- **Animatable Properties**: If you want to update material properties (e.g., `_MainTex_ST`, `_Color`) in AnimationClip,
|
- **Animatable Properties**: If you want to update material properties (e.g., `_MainTex_ST`, `_Color`) in AnimationClip,
|
||||||
use this to mark as animatable.
|
use this to mark the changes.
|
||||||
- **Mesh Sharing**: Particle simulation results are shared within the same group. A large number of the same effects can
|
- **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.
|
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.
|
- **Position Mode**: Emission position mode.
|
||||||
- **Absolute:** The particles will be emitted from the world position.
|
- **Absolute:** Emit from the world position of the `ParticleSystem`.
|
||||||
- **Relative:** The particles will be emitted from the scaled position.
|
- **Relative:** Emit from the scaled position of the `ParticleSystem`.
|
||||||
- **Auto Scaling Mode**: How to automatically adjust when the Canvas scale is changed by the screen size or reference resolution.
|
- **Auto Scaling**: `Transform.lossyScale` (=world scale) will be set to `(1, 1, 1)` on update. It prevents the
|
||||||
- **None:** Do nothing.
|
root-Canvas scale from affecting the hierarchy-scaled `ParticleSystem`.
|
||||||
- **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.
|
- **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
|
**NOTE:** Press the `Refresh` button to reconstruct the rendering order based on children ParticleSystem's sorting order
|
||||||
@@ -187,10 +176,9 @@ section.
|
|||||||
### Script usage
|
### Script usage
|
||||||
|
|
||||||
```cs
|
```cs
|
||||||
// Instantiate ParticleSystem prefab with UIParticle on runtime.
|
// Instant ParticleSystem prefab with UIParticle on runtime.
|
||||||
var go = GameObject.Instantiate(prefab);
|
var go = GameObject.Instantiate(prefab);
|
||||||
var uiParticle = go.AddComponent<UIParticle>();
|
var uiParticle = go.AddComponent<UIParticle>();
|
||||||
uiParticle.scale = 100;
|
|
||||||
|
|
||||||
// Control by ParticleSystem.
|
// Control by ParticleSystem.
|
||||||
particleSystem.Play();
|
particleSystem.Play();
|
||||||
@@ -207,7 +195,7 @@ uiParticle.Stop();
|
|||||||
|
|
||||||
`UIParticleAttractor` attracts particles generated by the specified ParticleSystem.
|
`UIParticleAttractor` attracts particles generated by the specified ParticleSystem.
|
||||||
|
|
||||||

|

|
||||||

|

|
||||||
|
|
||||||
- **Particle System**: Attracts particles generated by the specified particle system.
|
- **Particle System**: Attracts particles generated by the specified particle system.
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
fileFormatVersion: 2
|
fileFormatVersion: 2
|
||||||
guid: 607b55fe0d4534a56902644d3797abed
|
guid: 53aa3f36032944b3fb1455e774c52396
|
||||||
NativeFormatImporter:
|
folderAsset: yes
|
||||||
|
DefaultImporter:
|
||||||
externalObjects: {}
|
externalObjects: {}
|
||||||
mainObjectFileID: 2100000
|
|
||||||
userData:
|
userData:
|
||||||
assetBundleName:
|
assetBundleName:
|
||||||
assetBundleVariant:
|
assetBundleVariant:
|
||||||
@@ -1,8 +1,8 @@
|
|||||||
fileFormatVersion: 2
|
fileFormatVersion: 2
|
||||||
guid: e4d32268c77b14dd99f0e99fcfcd3a46
|
guid: 8cf8018dee45a4c42a19eec890eaa5b1
|
||||||
NativeFormatImporter:
|
folderAsset: yes
|
||||||
|
DefaultImporter:
|
||||||
externalObjects: {}
|
externalObjects: {}
|
||||||
mainObjectFileID: 2100000
|
|
||||||
userData:
|
userData:
|
||||||
assetBundleName:
|
assetBundleName:
|
||||||
assetBundleVariant:
|
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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 9dd767b8c0f95478386e7d5079cd44df
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
@@ -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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 0ef431b9df32c410ea5fa46be81def6b
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
155
Packages/src/Runtime/Internal/Extensions/ComponentExtensions.cs
Normal file
155
Packages/src/Runtime/Internal/Extensions/ComponentExtensions.cs
Normal file
@@ -0,0 +1,155 @@
|
|||||||
|
using System;
|
||||||
|
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 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();
|
||||||
|
}
|
||||||
|
|
||||||
|
#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:
|
||||||
19
Packages/src/Runtime/Internal/Extensions/ListExtensions.cs
Normal file
19
Packages/src/Runtime/Internal/Extensions/ListExtensions.cs
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
namespace Coffee.UIParticleInternal
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Extension methods for Component class.
|
||||||
|
/// </summary>
|
||||||
|
internal static class ListExtensions
|
||||||
|
{
|
||||||
|
public static void RemoveAtFast<T>(this List<T> self, int index)
|
||||||
|
{
|
||||||
|
if (self == null) return;
|
||||||
|
|
||||||
|
var lastIndex = self.Count - 1;
|
||||||
|
self[index] = self[lastIndex];
|
||||||
|
self.RemoveAt(lastIndex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 833553390099d40c9b212823f0852c46
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
48
Packages/src/Runtime/Internal/Extensions/Misc.cs
Normal file
48
Packages/src/Runtime/Internal/Extensions/Misc.cs
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
using System.Diagnostics;
|
||||||
|
using UnityEditor;
|
||||||
|
using UnityEngine;
|
||||||
|
|
||||||
|
namespace Coffee.UIParticleInternal
|
||||||
|
{
|
||||||
|
internal static class Misc
|
||||||
|
{
|
||||||
|
public static void Destroy(Object obj)
|
||||||
|
{
|
||||||
|
if (!obj) return;
|
||||||
|
#if UNITY_EDITOR
|
||||||
|
if (!Application.isPlaying)
|
||||||
|
{
|
||||||
|
Object.DestroyImmediate(obj);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
Object.Destroy(obj);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void DestroyImmediate(Object obj)
|
||||||
|
{
|
||||||
|
if (!obj) return;
|
||||||
|
#if UNITY_EDITOR
|
||||||
|
if (Application.isEditor)
|
||||||
|
{
|
||||||
|
Object.DestroyImmediate(obj);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
Object.Destroy(obj);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[Conditional("UNITY_EDITOR")]
|
||||||
|
public static void SetDirty(Object obj)
|
||||||
|
{
|
||||||
|
#if UNITY_EDITOR
|
||||||
|
if (!obj) return;
|
||||||
|
EditorUtility.SetDirty(obj);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
11
Packages/src/Runtime/Internal/Extensions/Misc.cs.meta
Normal file
11
Packages/src/Runtime/Internal/Extensions/Misc.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 39ed6a6b0a72e482488bd298b2ae762e
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
58
Packages/src/Runtime/Internal/Extensions/SpriteExtensions.cs
Normal file
58
Packages/src/Runtime/Internal/Extensions/SpriteExtensions.cs
Normal file
@@ -0,0 +1,58 @@
|
|||||||
|
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 MethodInfo s_GetActiveAtlasTextureMethod = s_SpriteEditorExtensionType
|
||||||
|
.GetMethod("GetActiveAtlasTexture", BindingFlags.Static | BindingFlags.NonPublic);
|
||||||
|
|
||||||
|
private static readonly MethodInfo s_GetActiveAtlasMethod = 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;
|
||||||
|
|
||||||
|
if (Application.isPlaying) return self.texture;
|
||||||
|
|
||||||
|
var ret = s_GetActiveAtlasTextureMethod.Invoke(null, new object[] { self }) as Texture2D;
|
||||||
|
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.Invoke(null, new object[] { self }) as SpriteAtlas;
|
||||||
|
}
|
||||||
|
#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,217 @@
|
|||||||
|
using System;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Reflection;
|
||||||
|
using UnityEngine;
|
||||||
|
using Object = UnityEngine.Object;
|
||||||
|
#if UNITY_EDITOR
|
||||||
|
using UnityEditor;
|
||||||
|
using UnityEditor.Build;
|
||||||
|
using UnityEditor.Build.Reporting;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
namespace Coffee.UIParticleInternal
|
||||||
|
{
|
||||||
|
public abstract class PreloadedProjectSettings : ScriptableObject
|
||||||
|
#if UNITY_EDITOR
|
||||||
|
, IPreprocessBuildWithReport
|
||||||
|
{
|
||||||
|
int IOrderedCallback.callbackOrder => 0;
|
||||||
|
|
||||||
|
void IPreprocessBuildWithReport.OnPreprocessBuild(BuildReport report)
|
||||||
|
{
|
||||||
|
Initialize();
|
||||||
|
}
|
||||||
|
|
||||||
|
[InitializeOnLoadMethod]
|
||||||
|
[InitializeOnEnterPlayMode]
|
||||||
|
private static void Initialize()
|
||||||
|
{
|
||||||
|
const BindingFlags flags = BindingFlags.Public | BindingFlags.Static | BindingFlags.FlattenHierarchy;
|
||||||
|
foreach (var t in TypeCache.GetTypesDerivedFrom(typeof(PreloadedProjectSettings<>)))
|
||||||
|
{
|
||||||
|
var defaultSettings = GetDefaultSettings(t);
|
||||||
|
if (!defaultSettings)
|
||||||
|
{
|
||||||
|
defaultSettings = t.GetProperty("instance", flags)
|
||||||
|
?.GetValue(null, null) as PreloadedProjectSettings;
|
||||||
|
SetDefaultSettings(defaultSettings);
|
||||||
|
}
|
||||||
|
else if (GetPreloadedSettings(t).Length != 1)
|
||||||
|
{
|
||||||
|
SetDefaultSettings(defaultSettings);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
EditorApplication.QueuePlayerLoopUpdate();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected static string GetDefaultName(Type type, bool nicify)
|
||||||
|
{
|
||||||
|
var typeName = type.Name.Replace("ProjectSettings", "");
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
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);
|
||||||
|
AssetDatabase.CreateAsset(asset, assetPath);
|
||||||
|
}
|
||||||
|
|
||||||
|
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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#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 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:
|
||||||
81
Packages/src/Runtime/Internal/Utilities/FastAction.cs
Executable file
81
Packages/src/Runtime/Internal/Utilities/FastAction.cs
Executable file
@@ -0,0 +1,81 @@
|
|||||||
|
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 ObjectPool<LinkedListNode<T>> s_NodePool =
|
||||||
|
new ObjectPool<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)
|
||||||
|
{
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <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:
|
||||||
102
Packages/src/Runtime/Internal/Utilities/FrameCache.cs
Normal file
102
Packages/src/Runtime/Internal/Utilities/FrameCache.cs
Normal file
@@ -0,0 +1,102 @@
|
|||||||
|
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:
|
||||||
257
Packages/src/Runtime/Internal/Utilities/Logging.cs
Normal file
257
Packages/src/Runtime/Internal/Utilities/Logging.cs
Normal file
@@ -0,0 +1,257 @@
|
|||||||
|
using System;
|
||||||
|
using System.Text;
|
||||||
|
using UnityEngine;
|
||||||
|
using Conditional = System.Diagnostics.ConditionalAttribute;
|
||||||
|
using Object = UnityEngine.Object;
|
||||||
|
#if ENABLE_COFFEE_LOGGER
|
||||||
|
using System.Reflection;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
#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 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,65 @@
|
|||||||
|
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)]
|
||||||
|
private 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<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:
|
||||||
85
Packages/src/Runtime/Internal/Utilities/ObjectPool.cs
Normal file
85
Packages/src/Runtime/Internal/Utilities/ObjectPool.cs
Normal file
@@ -0,0 +1,85 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
namespace Coffee.UIParticleInternal
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Object pool.
|
||||||
|
/// </summary>
|
||||||
|
internal class ObjectPool<T>
|
||||||
|
{
|
||||||
|
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 ObjectPool(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.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Object pool for <see cref="List{T}" />.
|
||||||
|
/// </summary>
|
||||||
|
internal static class ListPool<T>
|
||||||
|
{
|
||||||
|
private static readonly ObjectPool<List<T>> s_ListPool =
|
||||||
|
new ObjectPool<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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
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:
|
||||||
218
Packages/src/Runtime/Internal/Utilities/ObjectRepository.cs
Normal file
218
Packages/src/Runtime/Internal/Utilities/ObjectRepository.cs
Normal file
@@ -0,0 +1,218 @@
|
|||||||
|
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 List<Entry> _cache = new List<Entry>();
|
||||||
|
private readonly string _name;
|
||||||
|
private readonly Action<T> _onRelease;
|
||||||
|
private readonly Stack<Entry> _pool = new Stack<Entry>();
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public int count => _cache.Count;
|
||||||
|
|
||||||
|
public void Clear()
|
||||||
|
{
|
||||||
|
for (var i = 0; i < _cache.Count; i++)
|
||||||
|
{
|
||||||
|
var entry = _cache[i];
|
||||||
|
if (entry == null) continue;
|
||||||
|
|
||||||
|
entry.Release(_onRelease);
|
||||||
|
}
|
||||||
|
|
||||||
|
_cache.Clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool Valid(Hash128 hash, T obj)
|
||||||
|
{
|
||||||
|
// Find existing entry.
|
||||||
|
Profiler.BeginSample("(COF)[ObjectRepository] Valid > Find existing entry");
|
||||||
|
for (var i = 0; i < _cache.Count; ++i)
|
||||||
|
{
|
||||||
|
var entry = _cache[i];
|
||||||
|
if (entry.hash != hash) continue;
|
||||||
|
Profiler.EndSample();
|
||||||
|
|
||||||
|
// Existing entry found.
|
||||||
|
return entry.storedObject == obj;
|
||||||
|
}
|
||||||
|
|
||||||
|
Profiler.EndSample();
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Adds or retrieves a cached object based on the hash.
|
||||||
|
/// </summary>
|
||||||
|
public void Get(Hash128 hash, ref T obj, Func<T> onCreate)
|
||||||
|
{
|
||||||
|
// Find existing entry.
|
||||||
|
Profiler.BeginSample("(COF)[ObjectRepository] Get > Find existing entry");
|
||||||
|
for (var i = 0; i < _cache.Count; ++i)
|
||||||
|
{
|
||||||
|
var entry = _cache[i];
|
||||||
|
if (entry.hash != hash) continue;
|
||||||
|
|
||||||
|
// Existing entry found.
|
||||||
|
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(#{count}): {entry}");
|
||||||
|
}
|
||||||
|
|
||||||
|
Profiler.EndSample();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Profiler.EndSample();
|
||||||
|
|
||||||
|
// Create new entry.
|
||||||
|
Profiler.BeginSample("(COF)[ObjectRepository] Get > Create new entry");
|
||||||
|
var newEntry = 0 < _pool.Count ? _pool.Pop() : new Entry();
|
||||||
|
newEntry.storedObject = onCreate();
|
||||||
|
newEntry.hash = hash;
|
||||||
|
newEntry.reference = 1;
|
||||||
|
_cache.Add(newEntry);
|
||||||
|
Logging.Log(_name, $"Get(#{count}): {newEntry}");
|
||||||
|
|
||||||
|
Release(ref obj);
|
||||||
|
obj = newEntry.storedObject;
|
||||||
|
Profiler.EndSample();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <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)
|
||||||
|
{
|
||||||
|
// Find existing entry.
|
||||||
|
Profiler.BeginSample("(COF)[ObjectRepository] Get > Find existing entry");
|
||||||
|
for (var i = 0; i < _cache.Count; ++i)
|
||||||
|
{
|
||||||
|
var entry = _cache[i];
|
||||||
|
if (entry.hash != hash) continue;
|
||||||
|
|
||||||
|
// Existing entry found.
|
||||||
|
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(#{count}): {entry}");
|
||||||
|
}
|
||||||
|
|
||||||
|
Profiler.EndSample();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Profiler.EndSample();
|
||||||
|
|
||||||
|
// Create new entry.
|
||||||
|
Profiler.BeginSample("(COF)[ObjectRepository] Get > Create new entry");
|
||||||
|
var newEntry = 0 < _pool.Count ? _pool.Pop() : new Entry();
|
||||||
|
newEntry.storedObject = onCreate(source);
|
||||||
|
newEntry.hash = hash;
|
||||||
|
newEntry.reference = 1;
|
||||||
|
_cache.Add(newEntry);
|
||||||
|
Logging.Log(_name, $"Get(#{count}): {newEntry}");
|
||||||
|
|
||||||
|
Release(ref obj);
|
||||||
|
obj = newEntry.storedObject;
|
||||||
|
Profiler.EndSample();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Release a object.
|
||||||
|
/// </summary>
|
||||||
|
public void Release(ref T obj)
|
||||||
|
{
|
||||||
|
if (ReferenceEquals(obj, null)) return;
|
||||||
|
|
||||||
|
Profiler.BeginSample("(COF)[ObjectRepository] Release");
|
||||||
|
for (var i = 0; i < _cache.Count; i++)
|
||||||
|
{
|
||||||
|
var entry = _cache[i];
|
||||||
|
|
||||||
|
if (entry.storedObject != obj)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (--entry.reference <= 0)
|
||||||
|
{
|
||||||
|
Profiler.BeginSample("(COF)[ObjectRepository] Release > RemoveAt");
|
||||||
|
_cache.RemoveAtFast(i);
|
||||||
|
Logging.Log(_name, $"Release(#{_cache.Count}): {entry}");
|
||||||
|
entry.Release(_onRelease);
|
||||||
|
_pool.Push(entry);
|
||||||
|
Profiler.EndSample();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
Logging.Log(_name, $"Release(#{count}): {entry}");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
obj = null;
|
||||||
|
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()} (#{reference}), {storedObject}";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: a713d67bdb31e45e296e5f18460717e2
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
92
Packages/src/Runtime/Internal/Utilities/UIExtraCallbacks.cs
Executable file
92
Packages/src/Runtime/Internal/Utilities/UIExtraCallbacks.cs
Executable file
@@ -0,0 +1,92 @@
|
|||||||
|
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();
|
||||||
|
|
||||||
|
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>
|
||||||
|
/// 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]
|
||||||
|
#else
|
||||||
|
[RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.BeforeSceneLoad)]
|
||||||
|
#endif
|
||||||
|
private static void InitializeOnLoad()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Callback method called before canvas rebuilds.
|
||||||
|
/// </summary>
|
||||||
|
private static void OnBeforeCanvasRebuild()
|
||||||
|
{
|
||||||
|
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,8 +1,9 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Runtime.CompilerServices;
|
using System.Runtime.CompilerServices;
|
||||||
using Coffee.UIParticleExtensions;
|
using Coffee.UIParticleInternal;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
|
using UnityEngine.EventSystems;
|
||||||
using UnityEngine.Rendering;
|
using UnityEngine.Rendering;
|
||||||
using UnityEngine.Serialization;
|
using UnityEngine.Serialization;
|
||||||
using UnityEngine.UI;
|
using UnityEngine.UI;
|
||||||
@@ -44,26 +45,23 @@ namespace Coffee.UIExtensions
|
|||||||
|
|
||||||
[HideInInspector]
|
[HideInInspector]
|
||||||
[SerializeField]
|
[SerializeField]
|
||||||
[Obsolete]
|
|
||||||
internal bool m_IsTrail;
|
internal bool m_IsTrail;
|
||||||
|
|
||||||
[HideInInspector]
|
[HideInInspector]
|
||||||
[FormerlySerializedAs("m_IgnoreParent")]
|
[FormerlySerializedAs("m_IgnoreParent")]
|
||||||
[SerializeField]
|
[SerializeField]
|
||||||
[Obsolete]
|
|
||||||
private bool m_IgnoreCanvasScaler;
|
private bool m_IgnoreCanvasScaler;
|
||||||
|
|
||||||
[HideInInspector]
|
[HideInInspector]
|
||||||
[SerializeField]
|
[SerializeField]
|
||||||
[Obsolete]
|
private bool m_AbsoluteMode;
|
||||||
internal bool m_AbsoluteMode;
|
|
||||||
|
|
||||||
[Tooltip("Scale the rendering particles. When the `3D` toggle is enabled, 3D scale (x, y, z) is supported.")]
|
[Tooltip("Particle effect scale")]
|
||||||
[SerializeField]
|
[SerializeField]
|
||||||
private Vector3 m_Scale3D = new Vector3(10, 10, 10);
|
private Vector3 m_Scale3D = new Vector3(10, 10, 10);
|
||||||
|
|
||||||
[Tooltip("If you want to update material properties (e.g. _MainTex_ST, _Color) in AnimationClip, " +
|
[Tooltip("Animatable material properties.\n" +
|
||||||
"use this to mark as animatable.")]
|
"If you want to change the material properties of the ParticleSystem in Animation, enable it.")]
|
||||||
[SerializeField]
|
[SerializeField]
|
||||||
internal AnimatableProperty[] m_AnimatableProperties = new AnimatableProperty[0];
|
internal AnimatableProperty[] m_AnimatableProperties = new AnimatableProperty[0];
|
||||||
|
|
||||||
@@ -71,13 +69,12 @@ namespace Coffee.UIExtensions
|
|||||||
[SerializeField]
|
[SerializeField]
|
||||||
private List<ParticleSystem> m_Particles = new List<ParticleSystem>();
|
private List<ParticleSystem> m_Particles = new List<ParticleSystem>();
|
||||||
|
|
||||||
[Tooltip("Particle simulation results are shared within the same group. " +
|
[Tooltip("Mesh sharing.\n" +
|
||||||
"A large number of the same effects can be displayed with a small load.\n" +
|
"None: disable mesh sharing.\n" +
|
||||||
"None: Disable mesh sharing.\n" +
|
"Auto: automatically select Primary/Replica.\n" +
|
||||||
"Auto: Automatically select Primary/Replica.\n" +
|
"Primary: provides particle simulation results to the same group.\n" +
|
||||||
"Primary: Provides particle simulation results to the same group.\n" +
|
|
||||||
"Primary Simulator: Primary, but do not render the particle (simulation only).\n" +
|
"Primary Simulator: Primary, but do not render the particle (simulation only).\n" +
|
||||||
"Replica: Render simulation results provided by the primary.")]
|
"Replica: render simulation results provided by the primary.")]
|
||||||
[SerializeField]
|
[SerializeField]
|
||||||
private MeshSharing m_MeshSharing = MeshSharing.None;
|
private MeshSharing m_MeshSharing = MeshSharing.None;
|
||||||
|
|
||||||
@@ -89,40 +86,23 @@ namespace Coffee.UIExtensions
|
|||||||
[SerializeField]
|
[SerializeField]
|
||||||
private int m_GroupMaxId;
|
private int m_GroupMaxId;
|
||||||
|
|
||||||
[Tooltip("Emission position mode.\n" +
|
[Tooltip("Relative: The particles will be emitted from the scaled position of ParticleSystem.\n" +
|
||||||
"Relative: The particles will be emitted from the scaled position.\n" +
|
"Absolute: The particles will be emitted from the world position of ParticleSystem.")]
|
||||||
"Absolute: The particles will be emitted from the world position.")]
|
|
||||||
[SerializeField]
|
[SerializeField]
|
||||||
private PositionMode m_PositionMode = PositionMode.Relative;
|
private PositionMode m_PositionMode = PositionMode.Relative;
|
||||||
|
|
||||||
[SerializeField]
|
[SerializeField]
|
||||||
[Obsolete]
|
[Tooltip("Prevent the root-Canvas scale from affecting the hierarchy-scaled ParticleSystem.")]
|
||||||
internal bool m_AutoScaling;
|
private bool m_AutoScaling = true;
|
||||||
|
|
||||||
[SerializeField]
|
[SerializeField]
|
||||||
[Tooltip(
|
[Tooltip("Transform: Transform.lossyScale (=world scale) will be set to (1, 1, 1)." +
|
||||||
"How to automatically adjust when the Canvas scale is changed by the screen size or reference resolution.\n" +
|
"UIParticle: UIParticle.scale will be adjusted.")]
|
||||||
"None: Do nothing.\n" +
|
|
||||||
"Transform: Transform.lossyScale (=world scale) will be set to (1, 1, 1).\n" +
|
|
||||||
"UIParticle: UIParticle.scale will be adjusted.")]
|
|
||||||
private AutoScalingMode m_AutoScalingMode = AutoScalingMode.Transform;
|
private AutoScalingMode m_AutoScalingMode = AutoScalingMode.Transform;
|
||||||
|
|
||||||
[SerializeField]
|
|
||||||
[Tooltip("Use a custom view.\n" +
|
|
||||||
"Use this if the particles are not displayed correctly due to min/max particle size.")]
|
|
||||||
private bool m_UseCustomView;
|
|
||||||
|
|
||||||
[SerializeField]
|
|
||||||
[Tooltip("Custom view size.\n" +
|
|
||||||
"Change the bake view size.")]
|
|
||||||
private float m_CustomViewSize = 10;
|
|
||||||
|
|
||||||
private readonly List<UIParticleRenderer> _renderers = new List<UIParticleRenderer>();
|
private readonly List<UIParticleRenderer> _renderers = new List<UIParticleRenderer>();
|
||||||
private Camera _bakeCamera;
|
|
||||||
private Canvas _canvas;
|
|
||||||
private int _groupId;
|
private int _groupId;
|
||||||
private bool _isScaleStored;
|
private Camera _orthoCamera;
|
||||||
private Vector3 _storedScale;
|
|
||||||
private DrivenRectTransformTracker _tracker;
|
private DrivenRectTransformTracker _tracker;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -135,8 +115,7 @@ namespace Coffee.UIExtensions
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Particle simulation results are shared within the same group.
|
/// Mesh sharing.
|
||||||
/// A large number of the same effects can be displayed with a small load.
|
|
||||||
/// None: disable mesh sharing.
|
/// None: disable mesh sharing.
|
||||||
/// Auto: automatically select Primary/Replica.
|
/// Auto: automatically select Primary/Replica.
|
||||||
/// Primary: provides particle simulation results to the same group.
|
/// Primary: provides particle simulation results to the same group.
|
||||||
@@ -179,9 +158,9 @@ namespace Coffee.UIExtensions
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Emission position mode.
|
/// Particle position mode.
|
||||||
/// Relative: The particles will be emitted from the scaled position.
|
/// Relative: The particles will be emitted from the scaled position of the ParticleSystem.
|
||||||
/// Absolute: The particles will be emitted from the world position.
|
/// Absolute: The particles will be emitted from the world position of the ParticleSystem.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public PositionMode positionMode
|
public PositionMode positionMode
|
||||||
{
|
{
|
||||||
@@ -194,7 +173,6 @@ namespace Coffee.UIExtensions
|
|||||||
/// Relative: The particles will be emitted from the scaled position of the ParticleSystem.
|
/// Relative: The particles will be emitted from the scaled position of the ParticleSystem.
|
||||||
/// Absolute: The particles will be emitted from the world position of the ParticleSystem.
|
/// Absolute: The particles will be emitted from the world position of the ParticleSystem.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[Obsolete("The absoluteMode is now obsolete. Please use the autoScalingMode instead.", false)]
|
|
||||||
public bool absoluteMode
|
public bool absoluteMode
|
||||||
{
|
{
|
||||||
get => m_PositionMode == PositionMode.Absolute;
|
get => m_PositionMode == PositionMode.Absolute;
|
||||||
@@ -212,12 +190,8 @@ namespace Coffee.UIExtensions
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// How to automatically adjust when the Canvas scale is changed by the screen size or reference resolution.
|
/// Auto scaling mode.
|
||||||
/// <para/>
|
|
||||||
/// None: Do nothing.
|
|
||||||
/// <para/>
|
|
||||||
/// Transform: Transform.lossyScale (=world scale) will be set to (1, 1, 1).
|
/// Transform: Transform.lossyScale (=world scale) will be set to (1, 1, 1).
|
||||||
/// <para/>
|
|
||||||
/// UIParticle: UIParticle.scale will be adjusted.
|
/// UIParticle: UIParticle.scale will be adjusted.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public AutoScalingMode autoScalingMode
|
public AutoScalingMode autoScalingMode
|
||||||
@@ -227,35 +201,10 @@ namespace Coffee.UIExtensions
|
|||||||
{
|
{
|
||||||
if (m_AutoScalingMode == value) return;
|
if (m_AutoScalingMode == value) return;
|
||||||
m_AutoScalingMode = value;
|
m_AutoScalingMode = value;
|
||||||
|
UpdateTracker();
|
||||||
if (autoScalingMode != AutoScalingMode.Transform && _isScaleStored)
|
|
||||||
{
|
|
||||||
transform.localScale = _storedScale;
|
|
||||||
_isScaleStored = false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <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 useMeshSharing => m_MeshSharing != MeshSharing.None;
|
||||||
|
|
||||||
internal bool isPrimary =>
|
internal bool isPrimary =>
|
||||||
@@ -295,12 +244,30 @@ namespace Coffee.UIExtensions
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Particle effect scale.
|
/// Particle effect scale.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public Vector3 scale3DForCalc => autoScalingMode == AutoScalingMode.Transform
|
public Vector3 scale3DForCalc => autoScalingMode == AutoScalingMode.UIParticle
|
||||||
? m_Scale3D
|
? m_Scale3D.GetScaled(canvasScale)
|
||||||
: m_Scale3D.GetScaled(canvasScale, transform.localScale);
|
: m_Scale3D;
|
||||||
|
|
||||||
public List<ParticleSystem> particles => m_Particles;
|
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>
|
/// <summary>
|
||||||
/// Paused.
|
/// Paused.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -312,8 +279,8 @@ namespace Coffee.UIExtensions
|
|||||||
|
|
||||||
protected override void OnEnable()
|
protected override void OnEnable()
|
||||||
{
|
{
|
||||||
_isScaleStored = false;
|
|
||||||
ResetGroupId();
|
ResetGroupId();
|
||||||
|
UpdateTracker();
|
||||||
UIParticleUpdater.Register(this);
|
UIParticleUpdater.Register(this);
|
||||||
RegisterDirtyMaterialCallback(UpdateRendererMaterial);
|
RegisterDirtyMaterialCallback(UpdateRendererMaterial);
|
||||||
|
|
||||||
@@ -334,13 +301,7 @@ namespace Coffee.UIExtensions
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
protected override void OnDisable()
|
protected override void OnDisable()
|
||||||
{
|
{
|
||||||
_tracker.Clear();
|
UpdateTracker();
|
||||||
if (autoScalingMode == AutoScalingMode.Transform && _isScaleStored)
|
|
||||||
{
|
|
||||||
transform.localScale = _storedScale;
|
|
||||||
}
|
|
||||||
|
|
||||||
_isScaleStored = false;
|
|
||||||
UIParticleUpdater.Unregister(this);
|
UIParticleUpdater.Unregister(this);
|
||||||
_renderers.ForEach(r => r.Reset());
|
_renderers.ForEach(r => r.Reset());
|
||||||
UnregisterDirtyMaterialCallback(UpdateRendererMaterial);
|
UnregisterDirtyMaterialCallback(UpdateRendererMaterial);
|
||||||
@@ -355,12 +316,13 @@ namespace Coffee.UIExtensions
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
#if UNITY_EDITOR
|
||||||
/// This function is called when a direct or indirect parent of the transform of the GameObject has changed.
|
protected override void OnValidate()
|
||||||
/// </summary>
|
|
||||||
protected override void OnTransformParentChanged()
|
|
||||||
{
|
{
|
||||||
|
base.OnValidate();
|
||||||
|
UpdateTracker();
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
void ISerializationCallbackReceiver.OnBeforeSerialize()
|
void ISerializationCallbackReceiver.OnBeforeSerialize()
|
||||||
{
|
{
|
||||||
@@ -368,7 +330,6 @@ namespace Coffee.UIExtensions
|
|||||||
|
|
||||||
void ISerializationCallbackReceiver.OnAfterDeserialize()
|
void ISerializationCallbackReceiver.OnAfterDeserialize()
|
||||||
{
|
{
|
||||||
#pragma warning disable CS0612 // Type or member is obsolete
|
|
||||||
if (m_IgnoreCanvasScaler || m_AutoScaling)
|
if (m_IgnoreCanvasScaler || m_AutoScaling)
|
||||||
{
|
{
|
||||||
m_IgnoreCanvasScaler = false;
|
m_IgnoreCanvasScaler = false;
|
||||||
@@ -381,47 +342,31 @@ namespace Coffee.UIExtensions
|
|||||||
m_AbsoluteMode = false;
|
m_AbsoluteMode = false;
|
||||||
m_PositionMode = PositionMode.Absolute;
|
m_PositionMode = PositionMode.Absolute;
|
||||||
}
|
}
|
||||||
#pragma warning restore CS0612 // Type or member is obsolete
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Play the ParticleSystems.
|
|
||||||
/// </summary>
|
|
||||||
public void Play()
|
public void Play()
|
||||||
{
|
{
|
||||||
particles.Exec(p => p.Simulate(0, false, true));
|
particles.Exec(p => p.Simulate(0, false, true));
|
||||||
isPaused = false;
|
isPaused = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Pause the ParticleSystems.
|
|
||||||
/// </summary>
|
|
||||||
public void Pause()
|
public void Pause()
|
||||||
{
|
{
|
||||||
particles.Exec(p => p.Pause());
|
particles.Exec(p => p.Pause());
|
||||||
isPaused = true;
|
isPaused = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Unpause the ParticleSystems.
|
|
||||||
/// </summary>
|
|
||||||
public void Resume()
|
public void Resume()
|
||||||
{
|
{
|
||||||
isPaused = false;
|
isPaused = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Stop the ParticleSystems.
|
|
||||||
/// </summary>
|
|
||||||
public void Stop()
|
public void Stop()
|
||||||
{
|
{
|
||||||
particles.Exec(p => p.Stop());
|
particles.Exec(p => p.Stop());
|
||||||
isPaused = true;
|
isPaused = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Start emission of the ParticleSystems.
|
|
||||||
/// </summary>
|
|
||||||
public void StartEmission()
|
public void StartEmission()
|
||||||
{
|
{
|
||||||
particles.Exec(p =>
|
particles.Exec(p =>
|
||||||
@@ -431,9 +376,6 @@ namespace Coffee.UIExtensions
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Stop emission of the ParticleSystems.
|
|
||||||
/// </summary>
|
|
||||||
public void StopEmission()
|
public void StopEmission()
|
||||||
{
|
{
|
||||||
particles.Exec(p =>
|
particles.Exec(p =>
|
||||||
@@ -443,52 +385,24 @@ namespace Coffee.UIExtensions
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Clear the particles of the ParticleSystems.
|
|
||||||
/// </summary>
|
|
||||||
public void Clear()
|
public void Clear()
|
||||||
{
|
{
|
||||||
particles.Exec(p => p.Clear());
|
particles.Exec(p => p.Clear());
|
||||||
isPaused = true;
|
isPaused = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Get all base materials to render.
|
|
||||||
/// </summary>
|
|
||||||
public void GetMaterials(List<Material> result)
|
|
||||||
{
|
|
||||||
if (result == null) return;
|
|
||||||
|
|
||||||
for (var i = 0; i < _renderers.Count; i++)
|
|
||||||
{
|
|
||||||
var r = _renderers[i];
|
|
||||||
if (!r || !r.material) continue;
|
|
||||||
result.Add(r.material);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Refresh UIParticle using the ParticleSystem instance.
|
|
||||||
/// </summary>
|
|
||||||
public void SetParticleSystemInstance(GameObject instance)
|
public void SetParticleSystemInstance(GameObject instance)
|
||||||
{
|
{
|
||||||
SetParticleSystemInstance(instance, true);
|
SetParticleSystemInstance(instance, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Refresh UIParticle using the ParticleSystem instance.
|
|
||||||
/// </summary>
|
|
||||||
public void SetParticleSystemInstance(GameObject instance, bool destroyOldParticles)
|
public void SetParticleSystemInstance(GameObject instance, bool destroyOldParticles)
|
||||||
{
|
{
|
||||||
if (!instance) return;
|
if (!instance) return;
|
||||||
|
|
||||||
var childCount = transform.childCount;
|
foreach (Transform child in transform)
|
||||||
for (var i = 0; i < childCount; i++)
|
|
||||||
{
|
{
|
||||||
var go = transform.GetChild(i).gameObject;
|
var go = child.gameObject;
|
||||||
if (go.TryGetComponent<Camera>(out var cam) && cam == _bakeCamera) continue;
|
|
||||||
if (go.TryGetComponent<UIParticleRenderer>(out var _)) continue;
|
|
||||||
|
|
||||||
go.SetActive(false);
|
go.SetActive(false);
|
||||||
if (destroyOldParticles)
|
if (destroyOldParticles)
|
||||||
{
|
{
|
||||||
@@ -503,10 +417,6 @@ namespace Coffee.UIExtensions
|
|||||||
RefreshParticles(instance);
|
RefreshParticles(instance);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Refresh UIParticle using the prefab.
|
|
||||||
/// The prefab is automatically instantiated.
|
|
||||||
/// </summary>
|
|
||||||
public void SetParticleSystemPrefab(GameObject prefab)
|
public void SetParticleSystemPrefab(GameObject prefab)
|
||||||
{
|
{
|
||||||
if (!prefab) return;
|
if (!prefab) return;
|
||||||
@@ -514,31 +424,16 @@ namespace Coffee.UIExtensions
|
|||||||
SetParticleSystemInstance(Instantiate(prefab.gameObject), true);
|
SetParticleSystemInstance(Instantiate(prefab.gameObject), true);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Refresh UIParticle.
|
|
||||||
/// Collect ParticleSystems under the GameObject and refresh the UIParticle.
|
|
||||||
/// </summary>
|
|
||||||
public void RefreshParticles()
|
public void RefreshParticles()
|
||||||
{
|
{
|
||||||
RefreshParticles(gameObject);
|
RefreshParticles(gameObject);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Refresh UIParticle.
|
|
||||||
/// Collect ParticleSystems under the GameObject and refresh the UIParticle.
|
|
||||||
/// </summary>
|
|
||||||
private void RefreshParticles(GameObject root)
|
private void RefreshParticles(GameObject root)
|
||||||
{
|
{
|
||||||
if (!root) return;
|
if (!root) return;
|
||||||
root.GetComponentsInChildren(true, particles);
|
root.GetComponentsInChildren(true, particles);
|
||||||
for (var i = particles.Count - 1; 0 <= i; i--)
|
particles.RemoveAll(x => x.GetComponentInParent<UIParticle>(true) != this);
|
||||||
{
|
|
||||||
var ps = particles[i];
|
|
||||||
if (!ps || ps.GetComponentInParent<UIParticle>(true) != this)
|
|
||||||
{
|
|
||||||
particles.RemoveAt(i);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (var i = 0; i < particles.Count; i++)
|
for (var i = 0; i < particles.Count; i++)
|
||||||
{
|
{
|
||||||
@@ -553,39 +448,31 @@ namespace Coffee.UIExtensions
|
|||||||
RefreshParticles(particles);
|
RefreshParticles(particles);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
public void RefreshParticles(List<ParticleSystem> particles)
|
||||||
/// Refresh UIParticle using a list of ParticleSystems.
|
|
||||||
/// </summary>
|
|
||||||
public void RefreshParticles(List<ParticleSystem> particleSystems)
|
|
||||||
{
|
{
|
||||||
// Collect children UIParticleRenderer components.
|
|
||||||
// #246: Nullptr exceptions when using nested UIParticle components in hierarchy
|
// #246: Nullptr exceptions when using nested UIParticle components in hierarchy
|
||||||
_renderers.Clear();
|
_renderers.Clear();
|
||||||
var childCount = transform.childCount;
|
foreach (Transform child in transform)
|
||||||
for (var i = 0; i < childCount; i++)
|
|
||||||
{
|
{
|
||||||
var child = transform.GetChild(i);
|
var uiParticleRenderer = child.GetComponent<UIParticleRenderer>();
|
||||||
if (child.TryGetComponent(out UIParticleRenderer uiParticleRenderer))
|
|
||||||
|
if (uiParticleRenderer != null)
|
||||||
{
|
{
|
||||||
_renderers.Add(uiParticleRenderer);
|
_renderers.Add(uiParticleRenderer);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Reset the UIParticleRenderer components.
|
|
||||||
for (var i = 0; i < _renderers.Count; i++)
|
for (var i = 0; i < _renderers.Count; i++)
|
||||||
{
|
{
|
||||||
_renderers[i].Reset(i);
|
_renderers[i].Reset(i);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set the ParticleSystem to the UIParticleRenderer. If the trail is enabled, set it additionally.
|
|
||||||
var j = 0;
|
var j = 0;
|
||||||
for (var i = 0; i < particleSystems.Count; i++)
|
for (var i = 0; i < particles.Count; i++)
|
||||||
{
|
{
|
||||||
var ps = particleSystems[i];
|
var ps = particles[i];
|
||||||
if (!ps) continue;
|
if (!ps) continue;
|
||||||
GetRenderer(j++).Set(this, ps, false);
|
GetRenderer(j++).Set(this, ps, false);
|
||||||
|
|
||||||
// If the trail is enabled, set it additionally.
|
|
||||||
if (ps.trails.enabled)
|
if (ps.trails.enabled)
|
||||||
{
|
{
|
||||||
GetRenderer(j++).Set(this, ps, true);
|
GetRenderer(j++).Set(this, ps, true);
|
||||||
@@ -595,30 +482,12 @@ namespace Coffee.UIExtensions
|
|||||||
|
|
||||||
internal void UpdateTransformScale()
|
internal void UpdateTransformScale()
|
||||||
{
|
{
|
||||||
_tracker.Clear();
|
|
||||||
canvasScale = canvas.rootCanvas.transform.localScale.Inverse();
|
canvasScale = canvas.rootCanvas.transform.localScale.Inverse();
|
||||||
parentScale = transform.parent.lossyScale;
|
parentScale = transform.parent.lossyScale;
|
||||||
if (autoScalingMode != AutoScalingMode.Transform)
|
if (autoScalingMode != AutoScalingMode.Transform) return;
|
||||||
{
|
|
||||||
if (_isScaleStored)
|
|
||||||
{
|
|
||||||
transform.localScale = _storedScale;
|
|
||||||
}
|
|
||||||
|
|
||||||
_isScaleStored = false;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
var currentScale = transform.localScale;
|
|
||||||
if (!_isScaleStored)
|
|
||||||
{
|
|
||||||
_storedScale = currentScale.IsVisible() ? currentScale : Vector3.one;
|
|
||||||
_isScaleStored = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
_tracker.Add(this, rectTransform, DrivenTransformProperties.Scale);
|
|
||||||
var newScale = parentScale.Inverse();
|
var newScale = parentScale.Inverse();
|
||||||
if (currentScale != newScale)
|
if (transform.localScale != newScale)
|
||||||
{
|
{
|
||||||
transform.localScale = newScale;
|
transform.localScale = newScale;
|
||||||
}
|
}
|
||||||
@@ -631,10 +500,11 @@ namespace Coffee.UIExtensions
|
|||||||
for (var i = 0; i < _renderers.Count; i++)
|
for (var i = 0; i < _renderers.Count; i++)
|
||||||
{
|
{
|
||||||
var r = _renderers[i];
|
var r = _renderers[i];
|
||||||
if (r) continue;
|
if (!r)
|
||||||
|
{
|
||||||
RefreshParticles(particles);
|
RefreshParticles(particles);
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var bakeCamera = GetBakeCamera();
|
var bakeCamera = GetBakeCamera();
|
||||||
@@ -642,7 +512,6 @@ namespace Coffee.UIExtensions
|
|||||||
{
|
{
|
||||||
var r = _renderers[i];
|
var r = _renderers[i];
|
||||||
if (!r) continue;
|
if (!r) continue;
|
||||||
|
|
||||||
r.UpdateMesh(bakeCamera);
|
r.UpdateMesh(bakeCamera);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -694,55 +563,64 @@ namespace Coffee.UIExtensions
|
|||||||
private Camera GetBakeCamera()
|
private Camera GetBakeCamera()
|
||||||
{
|
{
|
||||||
if (!canvas) return Camera.main;
|
if (!canvas) return Camera.main;
|
||||||
if (!useCustomView && canvas.renderMode != RenderMode.ScreenSpaceOverlay && canvas.rootCanvas.worldCamera)
|
|
||||||
|
// When render mode is ScreenSpaceCamera or WorldSpace, use world camera.
|
||||||
|
var root = canvas.rootCanvas;
|
||||||
|
if (root.renderMode != RenderMode.ScreenSpaceOverlay)
|
||||||
{
|
{
|
||||||
return canvas.rootCanvas.worldCamera;
|
return root.worldCamera ? root.worldCamera : Camera.main;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_bakeCamera)
|
// When render mode is ScreenSpaceOverlay, use ortho-camera.
|
||||||
|
if (!_orthoCamera)
|
||||||
{
|
{
|
||||||
_bakeCamera.orthographicSize = useCustomView ? customViewSize : 10;
|
// Find existing ortho-camera.
|
||||||
return _bakeCamera;
|
foreach (Transform child in transform)
|
||||||
}
|
|
||||||
|
|
||||||
// Find existing baking camera.
|
|
||||||
var childCount = transform.childCount;
|
|
||||||
for (var i = 0; i < childCount; i++)
|
|
||||||
{
|
|
||||||
if (transform.GetChild(i).TryGetComponent<Camera>(out var cam)
|
|
||||||
&& cam.name == "[generated] UIParticle BakingCamera")
|
|
||||||
{
|
{
|
||||||
_bakeCamera = cam;
|
var cam = child.GetComponent<Camera>();
|
||||||
break;
|
if (cam && cam.name == "[generated] UIParticleOverlayCamera")
|
||||||
|
{
|
||||||
|
_orthoCamera = cam;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create ortho-camera.
|
||||||
|
if (!_orthoCamera)
|
||||||
|
{
|
||||||
|
var go = new GameObject("[generated] UIParticleOverlayCamera")
|
||||||
|
{
|
||||||
|
hideFlags = HideFlags.HideAndDontSave
|
||||||
|
};
|
||||||
|
go.SetActive(false);
|
||||||
|
go.transform.SetParent(transform, false);
|
||||||
|
_orthoCamera = go.AddComponent<Camera>();
|
||||||
|
_orthoCamera.enabled = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create baking camera.
|
//
|
||||||
if (!_bakeCamera)
|
var size = ((RectTransform)root.transform).rect.size;
|
||||||
|
_orthoCamera.orthographicSize = Mathf.Max(size.x, size.y) * root.scaleFactor;
|
||||||
|
_orthoCamera.transform.SetPositionAndRotation(new Vector3(0, 0, -1000), Quaternion.identity);
|
||||||
|
_orthoCamera.orthographic = true;
|
||||||
|
_orthoCamera.farClipPlane = 2000f;
|
||||||
|
|
||||||
|
return _orthoCamera;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void UpdateTracker()
|
||||||
|
{
|
||||||
|
#pragma warning disable CS0618 // Type or member is obsolete
|
||||||
|
if (!enabled || !autoScaling || autoScalingMode != AutoScalingMode.Transform)
|
||||||
|
#pragma warning restore CS0618 // Type or member is obsolete
|
||||||
{
|
{
|
||||||
var go = new GameObject("[generated] UIParticle BakingCamera");
|
_tracker.Clear();
|
||||||
go.SetActive(false);
|
}
|
||||||
go.transform.SetParent(transform, false);
|
else
|
||||||
_bakeCamera = go.AddComponent<Camera>();
|
{
|
||||||
|
_tracker.Add(this, rectTransform, DrivenTransformProperties.Scale);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Setup baking camera.
|
|
||||||
_bakeCamera.enabled = false;
|
|
||||||
_bakeCamera.orthographicSize = useCustomView ? customViewSize : 10;
|
|
||||||
_bakeCamera.transform.SetPositionAndRotation(new Vector3(0, 0, -1000), Quaternion.identity);
|
|
||||||
_bakeCamera.orthographic = true;
|
|
||||||
_bakeCamera.farClipPlane = 2000f;
|
|
||||||
_bakeCamera.clearFlags = CameraClearFlags.Nothing;
|
|
||||||
_bakeCamera.cullingMask = 0; // Nothing
|
|
||||||
_bakeCamera.allowHDR = false;
|
|
||||||
_bakeCamera.allowMSAA = false;
|
|
||||||
_bakeCamera.renderingPath = RenderingPath.Forward;
|
|
||||||
_bakeCamera.useOcclusionCulling = false;
|
|
||||||
|
|
||||||
_bakeCamera.gameObject.SetActive(false);
|
|
||||||
_bakeCamera.gameObject.hideFlags = HideFlags.HideAndDontSave;
|
|
||||||
|
|
||||||
return _bakeCamera;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
using System;
|
using System;
|
||||||
using Coffee.UIParticleExtensions;
|
using Coffee.UIParticleInternal;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
using UnityEngine.Events;
|
using UnityEngine.Events;
|
||||||
|
|
||||||
|
|||||||
@@ -4,9 +4,10 @@
|
|||||||
#elif UNITY_2022_3_OR_NEWER
|
#elif UNITY_2022_3_OR_NEWER
|
||||||
#define PS_BAKE_API_V2
|
#define PS_BAKE_API_V2
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using Coffee.UIParticleExtensions;
|
using Coffee.UIParticleInternal;
|
||||||
using UnityEditor;
|
using UnityEditor;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
using UnityEngine.Profiling;
|
using UnityEngine.Profiling;
|
||||||
@@ -28,10 +29,8 @@ namespace Coffee.UIExtensions
|
|||||||
private static readonly List<UIParticleRenderer> s_Renderers = new List<UIParticleRenderer>();
|
private static readonly List<UIParticleRenderer> s_Renderers = new List<UIParticleRenderer>();
|
||||||
private static readonly List<Color32> s_Colors = new List<Color32>();
|
private static readonly List<Color32> s_Colors = new List<Color32>();
|
||||||
private static readonly Vector3[] s_Corners = new Vector3[4];
|
private static readonly Vector3[] s_Corners = new Vector3[4];
|
||||||
private Material _currentMaterialForRendering;
|
|
||||||
private bool _delay;
|
private bool _delay;
|
||||||
private int _index;
|
private int _index;
|
||||||
private bool _isPrevStored;
|
|
||||||
private bool _isTrail;
|
private bool _isTrail;
|
||||||
private Bounds _lastBounds;
|
private Bounds _lastBounds;
|
||||||
private Material _modifiedMaterial;
|
private Material _modifiedMaterial;
|
||||||
@@ -41,7 +40,7 @@ namespace Coffee.UIExtensions
|
|||||||
private Vector3 _prevPsPos;
|
private Vector3 _prevPsPos;
|
||||||
private Vector3 _prevScale;
|
private Vector3 _prevScale;
|
||||||
private Vector2Int _prevScreenSize;
|
private Vector2Int _prevScreenSize;
|
||||||
private bool _preWarm;
|
private bool _prewarm;
|
||||||
private ParticleSystemRenderer _renderer;
|
private ParticleSystemRenderer _renderer;
|
||||||
|
|
||||||
public override Texture mainTexture => _isTrail ? null : _particleSystem.GetTextureForSprite();
|
public override Texture mainTexture => _isTrail ? null : _particleSystem.GetTextureForSprite();
|
||||||
@@ -111,15 +110,15 @@ namespace Coffee.UIExtensions
|
|||||||
if (this && isActiveAndEnabled)
|
if (this && isActiveAndEnabled)
|
||||||
{
|
{
|
||||||
material = null;
|
material = null;
|
||||||
canvasRenderer.Clear();
|
workerMesh.Clear();
|
||||||
|
canvasRenderer.SetMesh(workerMesh);
|
||||||
_lastBounds = new Bounds();
|
_lastBounds = new Bounds();
|
||||||
enabled = false;
|
enabled = false;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
ModifiedMaterial.Remove(_modifiedMaterial);
|
MaterialRepository.Release(ref _modifiedMaterial);
|
||||||
_modifiedMaterial = null;
|
_materialForRendering = null;
|
||||||
_currentMaterialForRendering = null;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -135,18 +134,14 @@ namespace Coffee.UIExtensions
|
|||||||
hideFlags = HideFlags.HideAndDontSave
|
hideFlags = HideFlags.HideAndDontSave
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
_currentMaterialForRendering = null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void OnDisable()
|
protected override void OnDisable()
|
||||||
{
|
{
|
||||||
base.OnDisable();
|
base.OnDisable();
|
||||||
|
|
||||||
ModifiedMaterial.Remove(_modifiedMaterial);
|
MaterialRepository.Release(ref _modifiedMaterial);
|
||||||
_modifiedMaterial = null;
|
_materialForRendering = null;
|
||||||
_currentMaterialForRendering = null;
|
|
||||||
_isPrevStored = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static UIParticleRenderer AddRenderer(UIParticle parent, int index)
|
public static UIParticleRenderer AddRenderer(UIParticle parent, int index)
|
||||||
@@ -178,12 +173,9 @@ namespace Coffee.UIExtensions
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public override Material GetModifiedMaterial(Material baseMaterial)
|
public override Material GetModifiedMaterial(Material baseMaterial)
|
||||||
{
|
{
|
||||||
_currentMaterialForRendering = null;
|
|
||||||
|
|
||||||
if (!IsActive() || !_parent)
|
if (!IsActive() || !_parent)
|
||||||
{
|
{
|
||||||
ModifiedMaterial.Remove(_modifiedMaterial);
|
MaterialRepository.Release(ref _modifiedMaterial);
|
||||||
_modifiedMaterial = null;
|
|
||||||
return baseMaterial;
|
return baseMaterial;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -193,23 +185,30 @@ namespace Coffee.UIExtensions
|
|||||||
var texture = mainTexture;
|
var texture = mainTexture;
|
||||||
if (texture == null && _parent.m_AnimatableProperties.Length == 0)
|
if (texture == null && _parent.m_AnimatableProperties.Length == 0)
|
||||||
{
|
{
|
||||||
ModifiedMaterial.Remove(_modifiedMaterial);
|
MaterialRepository.Release(ref _modifiedMaterial);
|
||||||
_modifiedMaterial = null;
|
|
||||||
return 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
|
#if UNITY_EDITOR
|
||||||
var props = EditorJsonUtility.ToJson(modifiedMaterial).GetHashCode();
|
(uint)EditorJsonUtility.ToJson(modifiedMaterial).GetHashCode()
|
||||||
#else
|
#else
|
||||||
var props = 0;
|
0
|
||||||
#endif
|
#endif
|
||||||
modifiedMaterial = ModifiedMaterial.Add(modifiedMaterial, texture, id, props);
|
);
|
||||||
ModifiedMaterial.Remove(_modifiedMaterial);
|
if (!MaterialRepository.Valid(hash, _modifiedMaterial))
|
||||||
_modifiedMaterial = modifiedMaterial;
|
{
|
||||||
|
MaterialRepository.Get(hash, ref _modifiedMaterial, () => new Material(modifiedMaterial)
|
||||||
|
{
|
||||||
|
hideFlags = HideFlags.HideAndDontSave
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
return modifiedMaterial;
|
return _modifiedMaterial;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Set(UIParticle parent, ParticleSystem ps, bool isTrail)
|
public void Set(UIParticle parent, ParticleSystem ps, bool isTrail)
|
||||||
@@ -220,20 +219,20 @@ namespace Coffee.UIExtensions
|
|||||||
gameObject.layer = parent.gameObject.layer;
|
gameObject.layer = parent.gameObject.layer;
|
||||||
|
|
||||||
_particleSystem = ps;
|
_particleSystem = ps;
|
||||||
_preWarm = _particleSystem.main.prewarm;
|
_prewarm = _particleSystem.main.prewarm;
|
||||||
|
|
||||||
#if UNITY_EDITOR
|
#if UNITY_EDITOR
|
||||||
if (Application.isPlaying)
|
if (Application.isPlaying)
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
if (_particleSystem.isPlaying || _preWarm)
|
if (_particleSystem.isPlaying || _prewarm)
|
||||||
{
|
{
|
||||||
_particleSystem.Clear();
|
_particleSystem.Clear();
|
||||||
_particleSystem.Pause();
|
_particleSystem.Pause();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ps.TryGetComponent(out _renderer);
|
_renderer = ps.GetComponent<ParticleSystemRenderer>();
|
||||||
_renderer.enabled = false;
|
_renderer.enabled = false;
|
||||||
|
|
||||||
//_emitter = emitter;
|
//_emitter = emitter;
|
||||||
@@ -405,33 +404,22 @@ namespace Coffee.UIExtensions
|
|||||||
_lastBounds = bounds;
|
_lastBounds = bounds;
|
||||||
|
|
||||||
// Convert linear color to gamma color.
|
// Convert linear color to gamma color.
|
||||||
if (QualitySettings.activeColorSpace == ColorSpace.Linear)
|
if (canvas.ShouldGammaToLinearInMesh())
|
||||||
{
|
{
|
||||||
Profiler.BeginSample("[UIParticleRenderer] Convert Linear to Gamma");
|
workerMesh.LinearToGamma();
|
||||||
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();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
GetComponents(typeof(IMeshModifier), s_Components);
|
var components = ListPool<Component>.Rent();
|
||||||
for (var i = 0; i < s_Components.Count; i++)
|
GetComponents(typeof(IMeshModifier), components);
|
||||||
{
|
|
||||||
#pragma warning disable CS0618 // Type or member is obsolete
|
#pragma warning disable CS0618 // Type or member is obsolete
|
||||||
((IMeshModifier)s_Components[i]).ModifyMesh(workerMesh);
|
for (var i = 0; i < components.Count; i++)
|
||||||
#pragma warning restore CS0618 // Type or member is obsolete
|
{
|
||||||
|
((IMeshModifier)components[i]).ModifyMesh(workerMesh);
|
||||||
}
|
}
|
||||||
|
#pragma warning restore CS0618 // Type or member is obsolete
|
||||||
|
|
||||||
s_Components.Clear();
|
ListPool<Component>.Return(ref components);
|
||||||
}
|
}
|
||||||
|
|
||||||
Profiler.EndSample();
|
Profiler.EndSample();
|
||||||
@@ -525,7 +513,7 @@ namespace Coffee.UIExtensions
|
|||||||
&& _particleSystem.main.scalingMode == ParticleSystemScalingMode.Local
|
&& _particleSystem.main.scalingMode == ParticleSystemScalingMode.Local
|
||||||
&& _parent.canvas)
|
&& _parent.canvas)
|
||||||
{
|
{
|
||||||
scale = scale.GetScaled(_parent.canvas.rootCanvas.transform.localScale);
|
scale = scale.GetScaled(_parent.canvas.transform.localScale);
|
||||||
}
|
}
|
||||||
|
|
||||||
Profiler.EndSample();
|
Profiler.EndSample();
|
||||||
@@ -562,7 +550,10 @@ namespace Coffee.UIExtensions
|
|||||||
return Matrix4x4.Scale(scale);
|
return Matrix4x4.Scale(scale);
|
||||||
case ParticleSystemSimulationSpace.Custom:
|
case ParticleSystemSimulationSpace.Custom:
|
||||||
return Matrix4x4.Translate(_particleSystem.main.customSimulationSpace.position.GetScaled(scale))
|
return Matrix4x4.Translate(_particleSystem.main.customSimulationSpace.position.GetScaled(scale))
|
||||||
* Matrix4x4.Scale(scale);
|
//* Matrix4x4.Translate(wpos)
|
||||||
|
* Matrix4x4.Scale(scale)
|
||||||
|
//* Matrix4x4.Translate(-wpos)
|
||||||
|
;
|
||||||
default:
|
default:
|
||||||
throw new NotSupportedException();
|
throw new NotSupportedException();
|
||||||
}
|
}
|
||||||
@@ -578,16 +569,15 @@ namespace Coffee.UIExtensions
|
|||||||
var screenSize = new Vector2Int(Screen.width, Screen.height);
|
var screenSize = new Vector2Int(Screen.width, Screen.height);
|
||||||
var isWorldSpace = _particleSystem.IsWorldSpace();
|
var isWorldSpace = _particleSystem.IsWorldSpace();
|
||||||
var canvasScale = _parent.canvas ? _parent.canvas.scaleFactor : 1f;
|
var canvasScale = _parent.canvas ? _parent.canvas.scaleFactor : 1f;
|
||||||
var resolutionChanged = _prevScreenSize != screenSize
|
var resolutionChanged = _prevScreenSize != screenSize || _prevCanvasScale != canvasScale;
|
||||||
|| !Mathf.Approximately(_prevCanvasScale, canvasScale);
|
if (resolutionChanged && isWorldSpace)
|
||||||
if (resolutionChanged && isWorldSpace && _isPrevStored)
|
|
||||||
{
|
{
|
||||||
// Update particle array size and get particles.
|
// Update particle array size and get particles.
|
||||||
var size = _particleSystem.particleCount;
|
var size = _particleSystem.particleCount;
|
||||||
var particles = ParticleSystemExtensions.GetParticleArray(size);
|
var particles = ParticleSystemExtensions.GetParticleArray(size);
|
||||||
_particleSystem.GetParticles(particles, size);
|
_particleSystem.GetParticles(particles, size);
|
||||||
|
|
||||||
// Resolution resolver:
|
// Resolusion resolver:
|
||||||
// (psPos / scale) / (prevPsPos / prevScale) -> psPos * scale.inv * prevPsPos.inv * prevScale
|
// (psPos / scale) / (prevPsPos / prevScale) -> psPos * scale.inv * prevPsPos.inv * prevScale
|
||||||
var modifier = psPos.GetScaled(
|
var modifier = psPos.GetScaled(
|
||||||
scale.Inverse(),
|
scale.Inverse(),
|
||||||
@@ -606,7 +596,6 @@ namespace Coffee.UIExtensions
|
|||||||
_delay = true;
|
_delay = true;
|
||||||
_prevScale = scale;
|
_prevScale = scale;
|
||||||
_prevPsPos = psPos;
|
_prevPsPos = psPos;
|
||||||
_isPrevStored = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
_prevCanvasScale = canvas ? canvas.scaleFactor : 1f;
|
_prevCanvasScale = canvas ? canvas.scaleFactor : 1f;
|
||||||
@@ -622,25 +611,23 @@ namespace Coffee.UIExtensions
|
|||||||
? Time.unscaledDeltaTime
|
? Time.unscaledDeltaTime
|
||||||
: Time.deltaTime;
|
: Time.deltaTime;
|
||||||
|
|
||||||
// Pre-warm:
|
// Prewarm:
|
||||||
if (0 < deltaTime && _preWarm)
|
if (0 < deltaTime && _prewarm)
|
||||||
{
|
{
|
||||||
deltaTime += main.duration;
|
deltaTime += main.duration;
|
||||||
_preWarm = false;
|
_prewarm = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// get world position.
|
// get world position.
|
||||||
var isLocalSpace = _particleSystem.IsLocalSpace();
|
var isLocalSpace = _particleSystem.IsLocalSpace();
|
||||||
var psTransform = _particleSystem.transform;
|
var psTransform = _particleSystem.transform;
|
||||||
var originLocalPosition = psTransform.localPosition;
|
|
||||||
var originLocalRotation = psTransform.localRotation;
|
|
||||||
var originWorldPosition = psTransform.position;
|
var originWorldPosition = psTransform.position;
|
||||||
var originWorldRotation = psTransform.rotation;
|
var originWorldRotation = psTransform.rotation;
|
||||||
var emission = _particleSystem.emission;
|
var emission = _particleSystem.emission;
|
||||||
var rateOverDistance = emission.enabled
|
var rateOverDistance = emission.enabled
|
||||||
&& 0 < emission.rateOverDistance.constant
|
&& 0 < emission.rateOverDistance.constant
|
||||||
&& 0 < emission.rateOverDistanceMultiplier;
|
&& 0 < emission.rateOverDistanceMultiplier;
|
||||||
if (rateOverDistance && !paused && _isPrevStored)
|
if (rateOverDistance && !paused)
|
||||||
{
|
{
|
||||||
// (For rate-over-distance emission,) Move to previous scaled position, simulate (delta = 0).
|
// (For rate-over-distance emission,) Move to previous scaled position, simulate (delta = 0).
|
||||||
var prevScaledPos = isLocalSpace
|
var prevScaledPos = isLocalSpace
|
||||||
@@ -656,8 +643,7 @@ namespace Coffee.UIExtensions
|
|||||||
: originWorldPosition.GetScaled(scale.Inverse());
|
: originWorldPosition.GetScaled(scale.Inverse());
|
||||||
psTransform.SetPositionAndRotation(scaledPos, originWorldRotation);
|
psTransform.SetPositionAndRotation(scaledPos, originWorldRotation);
|
||||||
_particleSystem.Simulate(deltaTime, false, false, false);
|
_particleSystem.Simulate(deltaTime, false, false, false);
|
||||||
psTransform.localPosition = originLocalPosition;
|
psTransform.SetPositionAndRotation(originWorldPosition, originWorldRotation);
|
||||||
psTransform.localRotation = originLocalRotation;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#if UNITY_EDITOR
|
#if UNITY_EDITOR
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using Coffee.UIParticleInternal;
|
||||||
using UnityEditor;
|
using UnityEditor;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
|
|
||||||
@@ -44,8 +45,7 @@ namespace Coffee.UIExtensions
|
|||||||
#endif
|
#endif
|
||||||
private static void InitializeOnLoad()
|
private static void InitializeOnLoad()
|
||||||
{
|
{
|
||||||
Canvas.willRenderCanvases -= Refresh;
|
UIExtraCallbacks.onAfterCanvasRebuild += Refresh;
|
||||||
Canvas.willRenderCanvases += Refresh;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void Refresh()
|
private static void Refresh()
|
||||||
@@ -58,8 +58,9 @@ namespace Coffee.UIExtensions
|
|||||||
for (var i = 0; i < s_ActiveParticles.Count; i++)
|
for (var i = 0; i < s_ActiveParticles.Count; i++)
|
||||||
{
|
{
|
||||||
var uip = s_ActiveParticles[i];
|
var uip = s_ActiveParticles[i];
|
||||||
if (!uip || !uip.canvas || !uip.isPrimary || !s_UpdatedGroupIds.Add(uip.groupId)) continue;
|
if (!uip || !uip.canvas || !uip.isPrimary || s_UpdatedGroupIds.Contains(uip.groupId)) continue;
|
||||||
|
|
||||||
|
s_UpdatedGroupIds.Add(uip.groupId);
|
||||||
uip.UpdateTransformScale();
|
uip.UpdateTransformScale();
|
||||||
uip.UpdateRenderers();
|
uip.UpdateRenderers();
|
||||||
}
|
}
|
||||||
@@ -76,8 +77,9 @@ namespace Coffee.UIExtensions
|
|||||||
{
|
{
|
||||||
uip.UpdateRenderers();
|
uip.UpdateRenderers();
|
||||||
}
|
}
|
||||||
else if (s_UpdatedGroupIds.Add(uip.groupId))
|
else if (!s_UpdatedGroupIds.Contains(uip.groupId))
|
||||||
{
|
{
|
||||||
|
s_UpdatedGroupIds.Add(uip.groupId);
|
||||||
uip.UpdateRenderers();
|
uip.UpdateRenderers();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user