Compare commits

..

3 Commits

Author SHA1 Message Date
mob-sakai
36ab069eba feat: add asset update system from v4 to v5 2024-05-23 13:05:23 +09:00
mob-sakai
66c76fb92b refactor: using Coffee.Internal 2024-05-23 13:04:15 +09:00
mob-sakai
b3a49514b5 chore: update test workflow 2024-05-23 13:04:15 +09:00
117 changed files with 3786 additions and 29986 deletions

View File

@@ -25,7 +25,6 @@ indent_size = 4
trim_trailing_whitespace = true
insert_final_newline = true
csharp_style_namespace_declarations = block_scoped
csharp_style_implicit_object_creation_when_type_is_apparent = false
resharper_object_creation_when_type_evident = explicitly_typed
@@ -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_member_access = true:suggestion
#
resharper_keep_existing_embedded_arrangement = true
# Arguments
csharp_arguments_literal = named:suggestion
csharp_arguments_string_literal = named:suggestion
@@ -138,7 +134,7 @@ dotnet_naming_style._camel_case.capitalization = camel_case
# Code style defaults
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_simple_using_statement = false:none
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_semicolon_in_for_statement = true
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_comma = false
csharp_space_before_dot = false

6
.github/CODEOWNERS vendored
View File

@@ -1,6 +0,0 @@
# This is a comment.
# Each line is a file pattern followed by one or more owners.
# https://docs.github.com/ja/repositories/managing-your-repositorys-settings-and-features/customizing-your-repository/about-code-owners
# Default owners
* @mob-sakai

12
.github/FUNDING.yml vendored
View File

@@ -1,12 +0,0 @@
# These are supported funding model platforms
github: mob-sakai # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2]
patreon: mob_sakai # Replace with a single Patreon username
open_collective: # Replace with a single Open Collective username
ko_fi: # Replace with a single Ko-fi username
tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel
community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry
liberapay: # Replace with a single Liberapay username
issuehunt: # Replace with a single IssueHunt username
otechie: # Replace with a single Otechie username
custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2']

View File

@@ -1,35 +0,0 @@
---
name: Bug report
about: Create a report to help us improve
title: ''
labels: bug
assignees: mob-sakai
---
NOTE: Your issue may already be reported! Please search on the [issue tracker](../) before creating one.
**Describe the bug**
A clear and concise description of what the bug is.
**To Reproduce**
Steps to reproduce the behavior:
1. Go to '...'
2. Click on '....'
3. Scroll down to '....'
4. See error
**Expected behavior**
A clear and concise description of what you expected to happen.
**Screenshots**
If applicable, add screenshots to help explain your problem.
**Environment (please complete the following information):**
- Version [e.g. 1.0.0]
- Platform: [e.g. Editor(Windows/Mac), Standalone(Windows/Mac), iOS, Android, WebGL]
- Unity version: [e.g. 2018.2.8f1]
- Build options: [e.g. IL2CPP, .Net 4.x, LWRP]
**Additional context**
Add any other context about the problem here.

View File

@@ -1,22 +0,0 @@
---
name: Feature request
about: Suggest an idea for this project
title: ''
labels: enhancement
assignees: mob-sakai
---
NOTE: Your issue may already be reported! Please search on the [issue tracker](../) before creating one.
**Is your feature request related to a problem? Please describe.**
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
**Describe the solution you'd like**
A clear and concise description of what you want to happen.
**Describe alternatives you've considered**
A clear and concise description of any alternative solutions or features you've considered.
**Additional context**
Add any other context or screenshots about the feature request here.

View File

@@ -1,16 +0,0 @@
---
name: Question
about: Ask a question about this project
title: ''
labels: question
assignees: mob-sakai
---
NOTE: Your issue may already be reported! Please search on the [issue tracker](../) before creating one.
**Describe what help do you need**
A description of the question.
**Additional context**
Add any other context or screenshots about the question here.

View File

@@ -1,37 +0,0 @@
# Pull Request Template
## Description
- Please include a summary of the change and which issue is fixed.
- Please also include relevant motivation and context.
- List any dependencies that are required for this change.
Fixes #{issue_number}
## Type of change
Please write the commit message in the format corresponding to the change type.
Please see [Conventional Commits](https://www.conventionalcommits.org/en/v1.0.0/) for more information.
- [ ] Bug fix (non-breaking change which fixes an issue)
- [ ] New feature (non-breaking change which adds functionality)
- [ ] Breaking change (fix or feature that would cause existing functionality to not work as expected)
- [ ] Update documentations
- [ ] Others (refactoring, style changes, etc.)
## Test environment
- Platform: [e.g. Editor(Windows/Mac), Standalone(Windows/Mac), iOS, Android, WebGL]
- Unity version: [e.g. 2022.2.0f1]
- Build options: [e.g. IL2CPP, .Net 4.x, URP/HDRP]
## Checklist
- [ ] This pull request is for merging into the `develop` branch
- [ ] My code follows the style guidelines of this project
- [ ] I have performed a self-review of my own code
- [ ] I have commented my code, particularly in hard-to-understand areas
- [ ] I have made corresponding changes to the documentation
- [ ] My changes generate no new warnings
- [ ] I have checked my code and corrected any misspellings

View File

@@ -1,28 +0,0 @@
name: 🚀 Deploy with Zip
on:
workflow_dispatch:
inputs:
zip:
description: "The url to the zip file"
required: true
jobs:
deploy:
name: 🚀 Deploy
runs-on: ubuntu-latest
permissions:
pages: write
id-token: write
steps:
- name: 📦 Download zip file To '_site'
run: |
curl -L ${{ github.event.inputs.zip }} -o _site.zip
unzip _site.zip -d _site
find _site -name __MACOSX | xargs rm -rf
- name: 📦 Upload '_site'
uses: actions/upload-pages-artifact@v3
- name: 🚀 Deploy To GitHub Pages
uses: actions/deploy-pages@v4

View File

@@ -1,13 +1,11 @@
name: 🔖 Release
run-name: 🔖 Release (${{ github.ref_name }})
on:
workflow_dispatch:
push:
branches:
- preview
- main
- v*.x
- release
tags-ignore:
- "**"
@@ -23,6 +21,8 @@ jobs:
channel: ${{ steps.release.outputs.new_release_channel }}
released: ${{ steps.release.outputs.new_release_published }}
tag: ${{ steps.release.outputs.new_release_git_tag }}
version: ${{ steps.release.outputs.new_release_version }}
notes: ${{ steps.release.outputs.new_release_notes }}
steps:
- name: 🚚 Checkout (${{ github.ref_name }})
uses: actions/checkout@v4
@@ -36,9 +36,51 @@ jobs:
@semantic-release/changelog
@semantic-release/git
env:
GITHUB_TOKEN: ${{ secrets.GH_TOKEN }}
GITHUB_TOKEN: ${{ github.token }}
- run: |
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 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
merge-to-develop:
if: needs.release.outputs.released == 'true'
needs: release
name: 🔀 Merge to develop
runs-on: ubuntu-latest
permissions:
contents: write
steps:
- name: 🚚 Checkout (develop)
uses: actions/checkout@v4
with:
ref: develop
fetch-depth: 0
- name: 🔀 Merge '${{ needs.release.outputs.tag }}' into 'develop'
run: |
git config --local user.email "github-actions[bot]@users.noreply.github.com"
git config --local user.name "github-actions[bot]"
git merge ${{ needs.release.outputs.tag }}
git push origin develop
split-to-main:
if: needs.release.outputs.released == 'true'
needs: release
name: 🔀 Split package
runs-on: ubuntu-latest
permissions:
contents: write
steps:
- name: 🚚 Checkout (${{ needs.release.outputs.tag }})
uses: actions/checkout@v4
with:
ref: ${{ needs.release.outputs.tag }}
fetch-depth: 0
- name: 🔀 Split subtree 'Packages/src' to 'main'
run: |
git branch main origin/main
git subtree split --prefix=Packages/src --branch main
git tag ${{ needs.release.outputs.version }} main
git push origin ${{ needs.release.outputs.version }} main:main

View File

@@ -3,36 +3,27 @@
# UNITY_EMAIL: Unity user email to login
# UNITY_PASSWORD: Unity user password to login
name: 🧪 Test
run-name: 🧪 Test (${{ github.event.pull_request.title || github.ref_name }})
env:
# MINIMUM_VERSION: The minimum version of Unity.
MINIMUM_VERSION: 2019.4
# EXCLUDE_FILTER: The excluded versions of Unity.
EXCLUDE_FILTER: "(2020.2.0|2021.1|2023.3)"
EXCLUDE_FILTER: '(2020.2.0)'
on:
workflow_dispatch:
inputs:
usePeriodVersions:
description: "Use the period versions (.0f1, .10f1, 20f1, ...)."
required: false
default: "true"
push:
branches:
- develop
- develop-preview
- develop_v5
tags:
- "!*"
paths-ignore:
- "**.md"
pull_request_target:
- "*.md"
pull_request:
types:
- opened
- reopened
- synchronize
paths-ignore:
- "**.md"
jobs:
setup:
@@ -45,12 +36,9 @@ jobs:
id: setup
run: |
echo "==== Target Unity Versions ===="
LATEST_VERSIONS=`npx unity-changeset@latest list --versions --latest-patch --min ${MINIMUM_VERSION} --json --all`
if [ "${{ inputs.usePeriodVersions }}" = "true" ]; then
ADDITIONAL_VERSIONS=`npx unity-changeset list --versions --grep '0f' --min ${MINIMUM_VERSION} --json`
else
ADDITIONAL_VERSIONS=[]
fi
LATEST_VERSIONS=`npx unity-changeset list --versions --latest-patch --min ${MINIMUM_VERSION} --json --all`
# ADDITIONAL_VERSIONS=`npx unity-changeset list --versions --grep '0f' --min ${MINIMUM_VERSION} --json`
ADDITIONAL_VERSIONS=[]
VERSIONS=`echo "[${LATEST_VERSIONS}, ${ADDITIONAL_VERSIONS}]" \
| jq -c '[ flatten | sort | unique | .[] | select( test("${{ env.EXCLUDE_FILTER }}") | not ) ]'`
@@ -59,44 +47,33 @@ jobs:
test:
name: 🧪 Run tests
runs-on: ubuntu-latest
env:
UNITY_EMAIL: ${{ secrets.UNITY_EMAIL }}
UNITY_PASSWORD: ${{ secrets.UNITY_PASSWORD }}
UNITY_LICENSE: ${{ secrets.UNITY_LICENSE }}
permissions:
checks: write
contents: read
needs: setup
strategy:
fail-fast: false
max-parallel: 6
max-parallel: 4
matrix:
unityVersion: ${{ fromJson(needs.setup.outputs.unityVersions) }}
steps:
- name: 🚚 Checkout ($${{ github.ref }})
if: github.event_name == 'push'
- name: 🚚 Checkout
uses: actions/checkout@v4
- name: 🚚 Checkout pull request (pull_request_target)
if: github.event_name == 'pull_request_target'
uses: actions/checkout@v4
with:
ref: ${{ github.event.pull_request.head.sha }}
fetch-depth: 0
- name: 🚚 Marge pull request (pull_request_target)
if: github.event_name == 'pull_request_target'
run: |
git config user.name "GitHub Actions"
git config user.email "actions@github.com"
git merge origin/${{ github.event.pull_request.base.ref }} --no-edit
- name: 📥 Cache library
uses: actions/cache@v4
with:
path: Library
key: Library-${{ matrix.unityVersion }}-${{ github.event.pull_request.head.sha || github.sha }}
key: Library-${{ matrix.unityVersion }}-${{ github.sha }}
restore-keys: |
Library-${{ matrix.unityVersion }}-
Library-
- name: 🛠️ Build Unity Project (Test)
- name: 🛠️ Build Unity Project
uses: game-ci/unity-builder@v4
timeout-minutes: 45
with:
@@ -104,10 +81,6 @@ jobs:
targetPlatform: StandaloneLinux64
allowDirtyBuild: true
customParameters: -nographics
env:
UNITY_EMAIL: ${{ secrets.UNITY_EMAIL }}
UNITY_PASSWORD: ${{ secrets.UNITY_PASSWORD }}
UNITY_LICENSE: ${{ secrets.UNITY_LICENSE }}
- name: 🧪 Run tests
uses: game-ci/unity-test-runner@v4
@@ -118,7 +91,4 @@ jobs:
customParameters: -nographics
checkName: ${{ matrix.unityVersion }} Test Results
githubToken: ${{ github.token }}
env:
UNITY_EMAIL: ${{ secrets.UNITY_EMAIL }}
UNITY_PASSWORD: ${{ secrets.UNITY_PASSWORD }}
UNITY_LICENSE: ${{ secrets.UNITY_LICENSE }}
coverageOptions: "dontClear;generateHtmlReport;generateBadgeReport;pathFilters:+**/Packages/src/**;assemblyFilters:+<packages>,-*.Editor,-*.Test"

1
.gitignore vendored
View File

@@ -28,4 +28,3 @@ Assets/Plugins/
obj/
bin/
UserSettings/
*.app

File diff suppressed because it is too large Load Diff

View File

@@ -1,4 +0,0 @@
fileFormatVersion: 2
guid: e34a092899a9547189add96707de1b5a
DefaultImporter:
userData:

View File

@@ -80,11 +80,7 @@ namespace Coffee.UIExtensions.Demo
.SelectMany(x => x.GetTypes())
.FirstOrDefault(x => x.Name == typeName);
#if UNITY_2023_2_OR_NEWER
return type == null ? null : FindFirstObjectByType(type);
#else
return type == null ? null : FindObjectOfType(type);
#endif
}
public void SetCanvasWidth(int width)

File diff suppressed because it is too large Load Diff

View File

@@ -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

View File

@@ -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:

View File

@@ -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
}
}
}

View File

@@ -1,10 +0,0 @@
fileFormatVersion: 2
guid: 6b5e4f608f0684d10a4673a7e1cee0f3
ShaderImporter:
externalObjects: {}
defaultTextures: []
nonModifiableTextures: []
preprocessorOverride: 0
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -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: []

View File

@@ -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: []

View File

@@ -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

View File

@@ -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:

View File

@@ -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: []

View File

@@ -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

View File

@@ -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:

View File

@@ -1,4 +1,3 @@
using Coffee.UIParticleInternal;
using UnityEngine;
using UnityEngine.Serialization;
@@ -47,7 +46,7 @@ namespace Coffee.UIExtensions.Demo
if (!flag)
{
foreach (var ps in Misc.FindObjectsOfType<ParticleSystem>())
foreach (var ps in FindObjectsOfType<ParticleSystem>())
{
ps.Play(false);
}
@@ -76,7 +75,7 @@ namespace Coffee.UIExtensions.Demo
public void ParticleSystem_SetScale(float scale)
{
foreach (var ps in Misc.FindObjectsOfType<ParticleSystem>())
foreach (var ps in FindObjectsOfType<ParticleSystem>())
{
ps.transform.localScale = new Vector3(scale, scale, scale);
}

View File

@@ -14,16 +14,15 @@ MonoBehaviour:
m_EditorClassIdentifier:
m_NanoMonitorEnabled: 1
m_BootSceneNameRegex: .*
m_DevelopmentBuildOnly: 0
m_DevelopmentBuildOnly: 1
m_EnabledInEditor: 1
m_AlwaysIncludeAssembly: 1
m_InstantiateOnLoad: 1
m_Prefab: {fileID: 4567906826058368312, guid: 7cebff2d255b9433cbe23b243c193329,
m_Prefab: {fileID: 7211429669315726685, guid: b73940fc30a2f4eb9a73783e9c1f8da6,
type: 3}
m_Opened: 1
m_Interval: 0.5
m_Anchor: 0
m_Width: 750
m_HelpUrl: https://github.com/mob-sakai/ParticleEffectForUGUI
m_Anchor: 1
m_CustomMonitorItems:
- m_Format: Screen:{0}x{1}
m_Arg0:
@@ -32,10 +31,3 @@ MonoBehaviour:
m_Path: UnityEngine.Screen, UnityEngine.CoreModule;height
m_Arg2:
m_Path:
- m_Format: UIParticles:{0} Materials:{1}
m_Arg0:
m_Path: Coffee.UIExtensions.UIParticleUpdater, Coffee.UIParticle;uiParticleCount
m_Arg1:
m_Path: Coffee.UIParticleInternal.MaterialRepository, Coffee.UIParticle;count
m_Arg2:
m_Path:

File diff suppressed because it is too large Load Diff

View File

@@ -1,8 +1,7 @@
fileFormatVersion: 2
guid: e4d32268c77b14dd99f0e99fcfcd3a46
NativeFormatImporter:
guid: b73940fc30a2f4eb9a73783e9c1f8da6
PrefabImporter:
externalObjects: {}
mainObjectFileID: 2100000
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,20 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!114 &11400000
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 0}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 94e8c16a26d334eafa227ee444387432, type: 3}
m_Name: SimpleSceneNavigator
m_EditorClassIdentifier:
m_NavigatorEnabled: 1
m_EnabledInEditor: 1
m_AlwaysIncludeAssembly: 1
m_InstantiateOnLoad: 1
m_Prefab: {fileID: 7211429669315726685, guid: 46deb9632f6a14713b8460bd01e879c9,
type: 3}

View File

@@ -1,5 +1,5 @@
fileFormatVersion: 2
guid: a5b9278dfbd194d04b1c6ae7031928c1
guid: be3e05903ef7041d39b3ef8ecdd47f08
NativeFormatImporter:
externalObjects: {}
mainObjectFileID: 11400000

View File

@@ -0,0 +1,513 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!1 &3877588430955763108
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 3877588430955763111}
- component: {fileID: 3877588430955763105}
- component: {fileID: 3877588430955763110}
m_Layer: 5
m_Name: Text
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!224 &3877588430955763111
RectTransform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 3877588430955763108}
m_LocalRotation: {x: -0, y: -0, z: -0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_Children: []
m_Father: {fileID: 3877588431231610297}
m_RootOrder: 0
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0, y: 0}
m_AnchorMax: {x: 1, y: 1}
m_AnchoredPosition: {x: 0, y: 0}
m_SizeDelta: {x: 0, y: 0}
m_Pivot: {x: 0.5, y: 0.5}
--- !u!222 &3877588430955763105
CanvasRenderer:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 3877588430955763108}
m_CullTransparentMesh: 0
--- !u!114 &3877588430955763110
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 3877588430955763108}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 5f7201a12d95ffc409449d95f23cf332, type: 3}
m_Name:
m_EditorClassIdentifier:
m_Material: {fileID: 0}
m_Color: {r: 0.19607843, g: 0.19607843, b: 0.19607843, a: 1}
m_RaycastTarget: 1
m_Maskable: 1
m_OnCullStateChanged:
m_PersistentCalls:
m_Calls: []
m_FontData:
m_Font: {fileID: 10102, guid: 0000000000000000e000000000000000, type: 0}
m_FontSize: 14
m_FontStyle: 0
m_BestFit: 0
m_MinSize: 10
m_MaxSize: 40
m_Alignment: 4
m_AlignByGeometry: 0
m_RichText: 1
m_HorizontalOverflow: 1
m_VerticalOverflow: 1
m_LineSpacing: 1
m_Text: '>>'
--- !u!1 &3877588431231610301
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 3877588431231610297}
- component: {fileID: 3877588431231610302}
- component: {fileID: 3877588431231610303}
- component: {fileID: 3877588431231610300}
m_Layer: 5
m_Name: Button - >>
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!224 &3877588431231610297
RectTransform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 3877588431231610301}
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_Children:
- {fileID: 3877588430955763111}
m_Father: {fileID: 7211429669315725985}
m_RootOrder: 1
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 1, y: 1}
m_AnchorMax: {x: 1, y: 1}
m_AnchoredPosition: {x: 0, y: 0}
m_SizeDelta: {x: 30, y: 30}
m_Pivot: {x: 1, y: 1}
--- !u!222 &3877588431231610302
CanvasRenderer:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 3877588431231610301}
m_CullTransparentMesh: 0
--- !u!114 &3877588431231610303
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 3877588431231610301}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3}
m_Name:
m_EditorClassIdentifier:
m_Material: {fileID: 0}
m_Color: {r: 1, g: 1, b: 1, a: 1}
m_RaycastTarget: 1
m_Maskable: 1
m_OnCullStateChanged:
m_PersistentCalls:
m_Calls: []
m_Sprite: {fileID: 10905, guid: 0000000000000000f000000000000000, type: 0}
m_Type: 1
m_PreserveAspect: 0
m_FillCenter: 1
m_FillMethod: 4
m_FillAmount: 1
m_FillClockwise: 1
m_FillOrigin: 0
m_UseSpriteMesh: 0
m_PixelsPerUnitMultiplier: 1
--- !u!114 &3877588431231610300
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 3877588431231610301}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 4e29b1a8efbd4b44bb3f3716e73f07ff, type: 3}
m_Name:
m_EditorClassIdentifier:
m_Navigation:
m_Mode: 3
m_SelectOnUp: {fileID: 0}
m_SelectOnDown: {fileID: 0}
m_SelectOnLeft: {fileID: 0}
m_SelectOnRight: {fileID: 0}
m_Transition: 1
m_Colors:
m_NormalColor: {r: 1, g: 1, b: 1, a: 1}
m_HighlightedColor: {r: 0.9607843, g: 0.9607843, b: 0.9607843, a: 1}
m_PressedColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 1}
m_SelectedColor: {r: 0.9607843, g: 0.9607843, b: 0.9607843, a: 1}
m_DisabledColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 0.5019608}
m_ColorMultiplier: 1
m_FadeDuration: 0.1
m_SpriteState:
m_HighlightedSprite: {fileID: 0}
m_PressedSprite: {fileID: 0}
m_SelectedSprite: {fileID: 0}
m_DisabledSprite: {fileID: 0}
m_AnimationTriggers:
m_NormalTrigger: Normal
m_HighlightedTrigger: Highlighted
m_PressedTrigger: Pressed
m_SelectedTrigger: Selected
m_DisabledTrigger: Disabled
m_Interactable: 1
m_TargetGraphic: {fileID: 3877588431231610303}
m_OnClick:
m_PersistentCalls:
m_Calls: []
--- !u!1 &3877588432219069602
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 3877588432219069614}
- component: {fileID: 3877588432219069615}
- component: {fileID: 3877588432219069612}
- component: {fileID: 3877588432219069613}
m_Layer: 5
m_Name: Button - <<
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!224 &3877588432219069614
RectTransform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 3877588432219069602}
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_Children:
- {fileID: 1738594088889562266}
m_Father: {fileID: 7211429669315725985}
m_RootOrder: 0
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0, y: 1}
m_AnchorMax: {x: 0, y: 1}
m_AnchoredPosition: {x: 0, y: 0}
m_SizeDelta: {x: 30, y: 30}
m_Pivot: {x: 0, y: 1}
--- !u!222 &3877588432219069615
CanvasRenderer:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 3877588432219069602}
m_CullTransparentMesh: 0
--- !u!114 &3877588432219069612
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 3877588432219069602}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3}
m_Name:
m_EditorClassIdentifier:
m_Material: {fileID: 0}
m_Color: {r: 1, g: 1, b: 1, a: 1}
m_RaycastTarget: 1
m_Maskable: 1
m_OnCullStateChanged:
m_PersistentCalls:
m_Calls: []
m_Sprite: {fileID: 10905, guid: 0000000000000000f000000000000000, type: 0}
m_Type: 1
m_PreserveAspect: 0
m_FillCenter: 1
m_FillMethod: 4
m_FillAmount: 1
m_FillClockwise: 1
m_FillOrigin: 0
m_UseSpriteMesh: 0
m_PixelsPerUnitMultiplier: 1
--- !u!114 &3877588432219069613
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 3877588432219069602}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 4e29b1a8efbd4b44bb3f3716e73f07ff, type: 3}
m_Name:
m_EditorClassIdentifier:
m_Navigation:
m_Mode: 3
m_SelectOnUp: {fileID: 0}
m_SelectOnDown: {fileID: 0}
m_SelectOnLeft: {fileID: 0}
m_SelectOnRight: {fileID: 0}
m_Transition: 1
m_Colors:
m_NormalColor: {r: 1, g: 1, b: 1, a: 1}
m_HighlightedColor: {r: 0.9607843, g: 0.9607843, b: 0.9607843, a: 1}
m_PressedColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 1}
m_SelectedColor: {r: 0.9607843, g: 0.9607843, b: 0.9607843, a: 1}
m_DisabledColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 0.5019608}
m_ColorMultiplier: 1
m_FadeDuration: 0.1
m_SpriteState:
m_HighlightedSprite: {fileID: 0}
m_PressedSprite: {fileID: 0}
m_SelectedSprite: {fileID: 0}
m_DisabledSprite: {fileID: 0}
m_AnimationTriggers:
m_NormalTrigger: Normal
m_HighlightedTrigger: Highlighted
m_PressedTrigger: Pressed
m_SelectedTrigger: Selected
m_DisabledTrigger: Disabled
m_Interactable: 1
m_TargetGraphic: {fileID: 3877588432219069612}
m_OnClick:
m_PersistentCalls:
m_Calls: []
--- !u!1 &7211429669315726685
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 7211429669315725985}
- component: {fileID: 7211429669315726686}
- component: {fileID: 7211429669315726687}
- component: {fileID: 7143702096253919615}
- component: {fileID: 3330778306119167604}
m_Layer: 5
m_Name: SimpleSceneNavigator
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!224 &7211429669315725985
RectTransform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 7211429669315726685}
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 0, y: 0, z: 0}
m_Children:
- {fileID: 3877588432219069614}
- {fileID: 3877588431231610297}
m_Father: {fileID: 0}
m_RootOrder: 0
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0, y: 0}
m_AnchorMax: {x: 0, y: 0}
m_AnchoredPosition: {x: 0, y: 0}
m_SizeDelta: {x: 0, y: 0}
m_Pivot: {x: 0, y: 0}
--- !u!223 &7211429669315726686
Canvas:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 7211429669315726685}
m_Enabled: 1
serializedVersion: 3
m_RenderMode: 0
m_Camera: {fileID: 0}
m_PlaneDistance: 100
m_PixelPerfect: 0
m_ReceivesEvents: 1
m_OverrideSorting: 0
m_OverridePixelPerfect: 0
m_SortingBucketNormalizedSize: 0
m_AdditionalShaderChannelsFlag: 0
m_SortingLayerID: 0
m_SortingOrder: 32000
m_TargetDisplay: 0
--- !u!114 &7211429669315726687
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 7211429669315726685}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 0cd44c1031e13a943bb63640046fad76, type: 3}
m_Name:
m_EditorClassIdentifier:
m_UiScaleMode: 1
m_ReferencePixelsPerUnit: 100
m_ScaleFactor: 1
m_ReferenceResolution: {x: 600, y: 40}
m_ScreenMatchMode: 0
m_MatchWidthOrHeight: 0
m_PhysicalUnit: 3
m_FallbackScreenDPI: 96
m_DefaultSpriteDPI: 96
m_DynamicPixelsPerUnit: 1
--- !u!114 &7143702096253919615
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 7211429669315726685}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: dc42784cf147c0c48a680349fa168899, type: 3}
m_Name:
m_EditorClassIdentifier:
m_IgnoreReversedGraphics: 1
m_BlockingObjects: 0
m_BlockingMask:
serializedVersion: 2
m_Bits: 4294967295
--- !u!114 &3330778306119167604
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 7211429669315726685}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: e7db36469bd2a46658ff432d65cb62ca, type: 3}
m_Name:
m_EditorClassIdentifier:
m_PrevButton: {fileID: 3877588432219069613}
m_NextButton: {fileID: 3877588431231610300}
m_PrevName: {fileID: 0}
m_NextName: {fileID: 0}
--- !u!1 &8570858711609111474
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 1738594088889562266}
- component: {fileID: 5485386222362727379}
- component: {fileID: 3877588430751452752}
m_Layer: 5
m_Name: Text
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!224 &1738594088889562266
RectTransform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 8570858711609111474}
m_LocalRotation: {x: -0, y: -0, z: -0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_Children: []
m_Father: {fileID: 3877588432219069614}
m_RootOrder: 0
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0, y: 0}
m_AnchorMax: {x: 1, y: 1}
m_AnchoredPosition: {x: 0, y: 0}
m_SizeDelta: {x: 0, y: 0}
m_Pivot: {x: 0.5, y: 0.5}
--- !u!222 &5485386222362727379
CanvasRenderer:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 8570858711609111474}
m_CullTransparentMesh: 0
--- !u!114 &3877588430751452752
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 8570858711609111474}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 5f7201a12d95ffc409449d95f23cf332, type: 3}
m_Name:
m_EditorClassIdentifier:
m_Material: {fileID: 0}
m_Color: {r: 0.19607843, g: 0.19607843, b: 0.19607843, a: 1}
m_RaycastTarget: 1
m_Maskable: 1
m_OnCullStateChanged:
m_PersistentCalls:
m_Calls: []
m_FontData:
m_Font: {fileID: 10102, guid: 0000000000000000e000000000000000, type: 0}
m_FontSize: 14
m_FontStyle: 0
m_BestFit: 0
m_MinSize: 10
m_MaxSize: 40
m_Alignment: 4
m_AlignByGeometry: 0
m_RichText: 1
m_HorizontalOverflow: 1
m_VerticalOverflow: 1
m_LineSpacing: 1
m_Text: <<

View File

@@ -1,8 +1,7 @@
fileFormatVersion: 2
guid: 607b55fe0d4534a56902644d3797abed
NativeFormatImporter:
guid: 46deb9632f6a14713b8460bd01e879c9
PrefabImporter:
externalObjects: {}
mainObjectFileID: 2100000
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -1,16 +0,0 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!114 &11400000
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 0}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: f22a23b9d98e440478697f4adf30e61c, type: 3}
m_Name: UIParticleProjectSettings
m_EditorClassIdentifier:
m_EnableLinearToGamma: 1
m_HideGeneratedObjects: 1

View File

@@ -1,9 +1,10 @@
{
"dependencies": {
"com.unity.ide.rider": "3.0.27",
"com.coffee.development": "https://github.com/mob-sakai/Coffee.Internal.git?path=Packages/Development",
"com.coffee.minimal-resource": "https://github.com/mob-sakai/Coffee.Internal.git?path=Packages/MinimalResource",
"com.coffee.nano-monitor": "https://github.com/mob-sakai/Coffee.Internal.git?path=Packages/NanoMonitor",
"com.unity.ide.rider": "3.0.31",
"com.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.modules.animation": "1.0.0",
"com.unity.modules.physics": "1.0.0"

View File

@@ -5,14 +5,7 @@
"depth": 0,
"source": "git",
"dependencies": {},
"hash": "3c280f1a8f4db5038b881ff07f270efd9638fa31"
},
"com.coffee.minimal-resource": {
"version": "https://github.com/mob-sakai/Coffee.Internal.git?path=Packages/MinimalResource",
"depth": 0,
"source": "git",
"dependencies": {},
"hash": "3c280f1a8f4db5038b881ff07f270efd9638fa31"
"hash": "41a1b604af8769b600d9c75db02ff35ec30611dc"
},
"com.coffee.nano-monitor": {
"version": "https://github.com/mob-sakai/Coffee.Internal.git?path=Packages/NanoMonitor",
@@ -21,7 +14,23 @@
"dependencies": {
"com.unity.ugui": "1.0.0"
},
"hash": "3c280f1a8f4db5038b881ff07f270efd9638fa31"
"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": {
"version": "file:src",
@@ -40,7 +49,7 @@
"url": "https://packages.unity.com"
},
"com.unity.ide.rider": {
"version": "3.0.31",
"version": "3.0.27",
"depth": 0,
"source": "registry",
"dependencies": {

View File

@@ -1,13 +1,11 @@
{
"branches": [
"main",
"[0-9]+.x",
"release",
{
"name": "preview",
"prerelease": true
}
],
"tagFormat": "${version}",
"plugins": [
"@semantic-release/commit-analyzer",
"@semantic-release/release-notes-generator",

View File

@@ -1,186 +1,3 @@
# [5.0.0-preview.16](https://github.com/mob-sakai/ParticleEffectForUGUI/compare/5.0.0-preview.15...5.0.0-preview.16) (2025-03-15)
### Bug Fixes
* IL2CPP build fails on older versions of Unity ([0da6525](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/0da652520cd165b43de7404c0b0ab1fbcf9349d1))
* NRE on enable ([0cff50e](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/0cff50ef696aa53fb7c46a9a737b7cf3a05b7b9b)), closes [#359](https://github.com/mob-sakai/ParticleEffectForUGUI/issues/359)
# [5.0.0-preview.15](https://github.com/mob-sakai/ParticleEffectForUGUI/compare/5.0.0-preview.14...5.0.0-preview.15) (2025-02-21)
### Bug Fixes
* component icons will no longer be displayed in the scene view ([6dfbdae](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/6dfbdae38d3822ab9c2c6f0e4ca1ca32ee98a239))
* editor crashed on exit play mode (editor, windows) ([47ee45c](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/47ee45cbbe651a8f87ca2b8a3948f8b88db8211e)), closes [#351](https://github.com/mob-sakai/ParticleEffectForUGUI/issues/351)
### Features
* add 'TimeScaleMultiplier' option ([925af0b](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/925af0b6046f65f23a778f67cefa8ff9cbedb513))
# [5.0.0-preview.14](https://github.com/mob-sakai/ParticleEffectForUGUI/compare/5.0.0-preview.13...5.0.0-preview.14) (2025-01-03)
### Bug Fixes
* sub-emitter particles may not render correctly in certain scenarios ([8276684](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/8276684c3b1646f0490ed64557547ba15281664a)), closes [#348](https://github.com/mob-sakai/ParticleEffectForUGUI/issues/348)
* sub-emitter's `inherit velocity` module doubles at runtime ([67de3d1](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/67de3d1bd3e16dc9b564625cb990c53d75769506)), closes [#349](https://github.com/mob-sakai/ParticleEffectForUGUI/issues/349)
# [5.0.0-preview.13](https://github.com/mob-sakai/ParticleEffectForUGUI/compare/5.0.0-preview.12...5.0.0-preview.13) (2025-01-03)
### Features
* change the default value of `UIParticle.scale` from `10` to `1` ([9955eef](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/9955eefdc22cf565502f85c87cd2efd3a25fbe50))
* UIParticle no longer inherits from MaskableGraphic ([c09bfb8](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/c09bfb81abc9179bf5fc49d29eaf7fc4ed01a4dc))
### BREAKING CHANGES
* Some members inherited from MaskableGraphic will no longer be available.
## [4.10.5](https://github.com/mob-sakai/ParticleEffectForUGUI/compare/v4.10.4...v4.10.5) (2024-12-23)
### Bug Fixes
* '3D' scale toggle in the inspector does not keep on reload ([934f4b8](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/934f4b8f1c61f8ff20228d0ebcea9f636a3758ed)), closes [#346](https://github.com/mob-sakai/ParticleEffectForUGUI/issues/346)
## [4.10.4](https://github.com/mob-sakai/ParticleEffectForUGUI/compare/v4.10.3...v4.10.4) (2024-12-19)
### Bug Fixes
* rendering issues when playing with opening a prefab stage ([95235a9](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/95235a929b82cf681365ed6eba837d857f83e3d2)), closes [#345](https://github.com/mob-sakai/ParticleEffectForUGUI/issues/345)
## [4.10.3](https://github.com/mob-sakai/ParticleEffectForUGUI/compare/v4.10.2...v4.10.3) (2024-11-20)
### Bug Fixes
* if not configured as a preloaded asset, the project settings asset will be regenerated ([abe0948](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/abe09485f65dd4efd18e74675e752e0213bdf3be)), closes [#342](https://github.com/mob-sakai/ParticleEffectForUGUI/issues/342)
## [4.10.2](https://github.com/mob-sakai/ParticleEffectForUGUI/compare/v4.10.1...v4.10.2) (2024-11-01)
### Bug Fixes
* trail incorrect offset ([afe00a1](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/afe00a1dde80eb1c0a7bb668b75f4c3733d3fa43)), closes [#335](https://github.com/mob-sakai/ParticleEffectForUGUI/issues/335)
## [4.10.1](https://github.com/mob-sakai/ParticleEffectForUGUI/compare/v4.10.0...v4.10.1) (2024-09-29)
### Bug Fixes
* mainTex will be ignored ([2ee69d0](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/2ee69d04245fabce185f67dc9bd68c870e556564))
# [4.10.0](https://github.com/mob-sakai/ParticleEffectForUGUI/compare/v4.9.1...v4.10.0) (2024-09-29)
### Bug Fixes
* component icon is not set ([5ff6ec8](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/5ff6ec815a174de5d3f16d424f1204c60912a8d8))
### Features
* add project settings ([1ce4e31](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/1ce4e31a9681bf1a201d2723c8d97e07ecc16592))
## [4.9.1](https://github.com/mob-sakai/ParticleEffectForUGUI/compare/v4.9.0...v4.9.1) (2024-08-07)
### Bug Fixes
* ParticleSystem trails gain offset on parent canvas change ([2a1cd50](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/2a1cd502b452b5b56edf8bcfe91adf99d1bb5147)), closes [#323](https://github.com/mob-sakai/ParticleEffectForUGUI/issues/323)
# [4.9.0](https://github.com/mob-sakai/ParticleEffectForUGUI/compare/v4.8.1...v4.9.0) (2024-07-18)
### Features
* ParticleAttractor supports multiple ParticleSystems ([3834780](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/3834780fdb43443fe6e1ef89df54d26a24d62a91))
## [4.8.1](https://github.com/mob-sakai/ParticleEffectForUGUI/compare/v4.8.0...v4.8.1) (2024-06-27)
### Bug Fixes
* remove debug code ([669deb4](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/669deb41d4ac589d9db93b29bc8e95383e7f28a5))
# [4.8.0](https://github.com/mob-sakai/ParticleEffectForUGUI/compare/v4.7.2...v4.8.0) (2024-06-27)
### Bug Fixes
* generated baking-camera object remains in the prefab or scene (again) ([de35cba](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/de35cba34c6312c1405ed522e9927c620c78e72d))
* SetParticleSystemInstance/Prefab APIs destroy generated objects ([ae3f3a8](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/ae3f3a8e62cc733420354d237ab765ac777127c8))
### Features
* add 'custom view' option. ([a703c29](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/a703c2921ca08c2280d0c8fde01e4c0b33b5c69e))
* remove overlay window (editor) ([8358170](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/835817049f4fcf00dd2bf98dbada14f041ad3544))
* restore `Transform.localScale` when setting `autoScalingMode` to something other than `Transform` (again) ([88a970d](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/88a970d93a2b69cf011d86bd1807569e90538e0e))
* the rendering order list in inspector is now more compact ([be90172](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/be901724e064befacf617f4940b0331e1d31e1ca))
## [4.7.2](https://github.com/mob-sakai/ParticleEffectForUGUI/compare/v4.7.1...v4.7.2) (2024-06-21)
### Bug Fixes
* generated baking-camera object remains in the prefab or scene ([0bb8438](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/0bb843830197d8c1252232928becc211c0ada08d))
## [4.7.1](https://github.com/mob-sakai/ParticleEffectForUGUI/compare/v4.7.0...v4.7.1) (2024-06-20)
### 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)

View File

@@ -31,35 +31,35 @@ namespace Coffee.UIExtensions
}
else
{
result.Aggregate(s_Sb, (a, b) =>
{
s_Sb.Append(b);
return s_Sb.Append(", ");
});
result.Aggregate(s_Sb, (a, b) => s_Sb.AppendFormat("{0}, ", b));
s_Sb.Length -= 2;
}
return s_Sb.ToString();
}
public static void Draw(SerializedProperty sp, List<Material> mats)
public static void Draw(SerializedProperty sp, Material[] mats)
{
var pos = EditorGUILayout.GetControlRect(true);
var label = new GUIContent(sp.displayName, sp.tooltip);
var rect = EditorGUI.PrefixLabel(pos, label);
var text = sp.hasMultipleDifferentValues
? "-"
: CollectActiveNames(sp, s_ActiveNames);
bool isClicked;
using (new EditorGUILayout.HorizontalScope(GUILayout.ExpandWidth(false)))
{
var pos = EditorGUILayout.GetControlRect(true);
var label = new GUIContent(sp.displayName, sp.tooltip);
var rect = EditorGUI.PrefixLabel(pos, label);
var text = sp.hasMultipleDifferentValues
? "-"
: CollectActiveNames(sp, s_ActiveNames);
isClicked = GUI.Button(rect, text, EditorStyles.popup);
}
if (!GUI.Button(rect, text, EditorStyles.popup)) return;
if (!isClicked) return;
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;
current.ClearArray();
current.serializedObject.ApplyModifiedProperties();
}, sp);
sp.ClearArray();
sp.serializedObject.ApplyModifiedProperties();
});
if (!sp.hasMultipleDifferentValues)
{
@@ -73,7 +73,7 @@ namespace Coffee.UIExtensions
}
s_Names.Clear();
for (var j = 0; j < mats.Count; j++)
for (var j = 0; j < mats.Length; j++)
{
var mat = mats[j];
if (!mat || !mat.shader) continue;
@@ -82,7 +82,8 @@ namespace Coffee.UIExtensions
{
var name = ShaderUtil.GetPropertyName(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);

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 1006234332be4f329fc1830319b31aaa
timeCreated: 1704502465

View File

@@ -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";
}
}
}

View File

@@ -1,11 +1,11 @@
fileFormatVersion: 2
guid: f22a23b9d98e440478697f4adf30e61c
guid: d3378b5e701274218b04cb5588b8a3bd
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {fileID: 2800000, guid: 5f0675613942149309588d556e33d990, type: 3}
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -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";
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 3d6d0ca7ae8c641aa98b66fd91c05264
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -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.";
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: dfbc9e244a2a040179e7f5b58ec0b978
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -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();
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: edd678db452e49869caeca7e7d269e5d
timeCreated: 1704502476

View File

@@ -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";
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: b2a025408e4a7486a941102775d2c73b
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -1,5 +1,5 @@
fileFormatVersion: 2
guid: 157d70e6cb69d4581b4ed450c7ffd33d
guid: 3e440931f761e4e888510a4e6045287a
folderAsset: yes
DefaultImporter:
externalObjects: {}

View File

@@ -1,5 +1,6 @@
fileFormatVersion: 2
guid: dfba9a6f2258941f5b4429fba806d8e9
guid: 269bcefd175184eebbfa31421171fadf
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:

View File

@@ -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);
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 338da2d8cec784add924489fc4a7bb01
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -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();
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: f16bc447ca4934ca3b9329d1d870440a
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,11 @@
using UnityEngine;
namespace Coffee.UIParticleInternal.AssetModification
{
internal interface IComponentModifier
{
bool isModified { get; }
bool ModifyComponent(GameObject root, bool dryRun);
string Report();
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 1e50323d0799f4daf8ef476f7bf403a4
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,9 @@
using System.Text;
namespace Coffee.UIParticleInternal.AssetModification
{
internal interface ITextModifier
{
bool ModifyText(StringBuilder sb, string text);
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 2ad967b4f039b4deba09ed0c1401cf83
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View 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;
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: c716fe53d75054d309923c577f5059a4
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -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);
}
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: a50643d4fde75458cae1f0d4ef9549ad
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View 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();
}
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: f28067cf4bfca4d92bd5262ac5c7a652
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -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);
}
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 6764c0c6fd61a4f66a8b0e3467be420d
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -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());
}
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 431e5b95f2f5c4f19926a7fc5342e118
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -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;
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: afc6ba9550e5e4c25951b03db43a4fd0
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -2,11 +2,10 @@ using System.Collections.Generic;
using System.Linq;
using System.Text.RegularExpressions;
using UnityEditor;
using UnityEditor.UI;
using UnityEditorInternal;
using UnityEngine;
using UnityEngine.Profiling;
using UnityEngine.UI;
using Coffee.UIParticleInternal;
#if UNITY_2021_2_OR_NEWER
using UnityEditor.Overlays;
#else
@@ -16,7 +15,6 @@ using Object = UnityEngine.Object;
#endif
#if UNITY_2021_2_OR_NEWER
using UnityEditor.SceneManagement;
#elif UNITY_2018_3_OR_NEWER
using UnityEditor.Experimental.SceneManagement;
#endif
@@ -25,31 +23,44 @@ namespace Coffee.UIExtensions
{
[CustomEditor(typeof(UIParticle))]
[CanEditMultipleObjects]
internal class UIParticleEditor : Editor
internal class UIParticleEditor : GraphicEditor
{
internal class State : ScriptableSingleton<State>
#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 is3DScaleMode;
public bool visible => s_SerializedObject != null;
public override void OnGUI()
{
if (visible)
{
WindowFunction();
}
}
}
#endif
//################################
// Constant or Static Members.
//################################
private static readonly GUIContent[] s_ContentMaterials = new[]
{
new GUIContent("Material"),
new GUIContent("Trail Material")
};
private static readonly GUIContent s_ContentRenderingOrder = new GUIContent("Rendering Order");
private static readonly GUIContent s_ContentRefresh = new GUIContent("Refresh");
private static readonly GUIContent s_ContentFix = new GUIContent("Fix");
private static readonly GUIContent s_ContentMaterial = new GUIContent("Material");
private static readonly GUIContent s_ContentTrailMaterial = new GUIContent("Trail Material");
private static readonly GUIContent s_Content3D = new GUIContent("3D");
private static readonly GUIContent s_ContentRandom = new GUIContent("Random");
private static readonly GUIContent s_ContentScale = new GUIContent("Scale");
private static readonly GUIContent s_ContentPrimary = new GUIContent("Primary");
private static readonly Regex s_RegexBuiltInGuid = new Regex(@"^0{16}.0{15}$", RegexOptions.Compiled);
private static readonly List<Material> s_TempMaterials = new List<Material>();
private static SerializedObject s_SerializedObject;
private static bool s_XYZMode;
private SerializedProperty _maskable;
private SerializedProperty _scale3D;
@@ -59,12 +70,8 @@ namespace Coffee.UIExtensions
private SerializedProperty _groupMaxId;
private SerializedProperty _positionMode;
private SerializedProperty _autoScalingMode;
private SerializedProperty _useCustomView;
private SerializedProperty _customViewSize;
private SerializedProperty _timeScaleMultiplier;
private ReorderableList _ro;
private bool _showMax;
private bool _is3DScaleMode;
private static readonly HashSet<Shader> s_Shaders = new HashSet<Shader>();
#if UNITY_2018 || UNITY_2019
@@ -80,14 +87,66 @@ namespace Coffee.UIExtensions
"_ColorMask"
};
[InitializeOnLoadMethod]
private static void Init()
{
#if !UNITY_2021_2_OR_NEWER
var miSceneViewOverlayWindow = Type.GetType("UnityEditor.SceneViewOverlay, UnityEditor")
?.GetMethods(BindingFlags.Public | BindingFlags.Static)
.First(x => x.Name == "Window" && 5 <= x.GetParameters().Length);
var windowFunction = (Action<Object, SceneView>)WindowFunction;
var windowFunctionType = Type.GetType("UnityEditor.SceneViewOverlay+WindowFunction, UnityEditor");
var windowFunctionDelegate = Delegate.CreateDelegate(windowFunctionType, windowFunction.Method);
var windowTitle = new GUIContent(ObjectNames.NicifyVariableName(nameof(UIParticle)));
#if UNITY_2019_2_OR_NEWER
//public static void Window(GUIContent title, WindowFunction sceneViewFunc, int order, Object target, WindowDisplayOption option, EditorWindow window = null)
var sceneViewArgs = new object[] { windowTitle, windowFunctionDelegate, 599, null, 2, null };
#else
//public static void Window(GUIContent title, WindowFunction sceneViewFunc, int order, Object target, WindowDisplayOption option)
var sceneViewArgs = new object[] { windowTitle, windowFunctionDelegate, 599, null, 2 };
#endif
#if UNITY_2019_1_OR_NEWER
SceneView.duringSceneGui += _ =>
#else
SceneView.onSceneGUIDelegate += _ =>
#endif
{
if (s_SerializedObject != null)
{
miSceneViewOverlayWindow.Invoke(null, sceneViewArgs);
}
};
#endif
SerializedObject CreateSerializeObject()
{
var uiParticles = Selection.gameObjects.Select(x => x.GetComponent<ParticleSystem>())
.Where(x => x)
.Select(x => x.GetComponentInParent<UIParticle>(true))
.Where(x => x && x.canvas)
.Concat(Selection.gameObjects.Select(x => x.GetComponent<UIParticle>())
.Where(x => x && x.canvas))
.Distinct()
.OfType<Object>()
.ToArray();
return 0 < uiParticles.Length ? new SerializedObject(uiParticles) : null;
}
s_SerializedObject = CreateSerializeObject();
Selection.selectionChanged += () => s_SerializedObject = CreateSerializeObject();
}
//################################
// Public/Protected Members.
//################################
/// <summary>
/// This function is called when the object becomes enabled and active.
/// </summary>
private void OnEnable()
protected override void OnEnable()
{
base.OnEnable();
_maskable = serializedObject.FindProperty("m_Maskable");
_scale3D = serializedObject.FindProperty("m_Scale3D");
_animatableProperties = serializedObject.FindProperty("m_AnimatableProperties");
@@ -96,44 +155,31 @@ namespace Coffee.UIExtensions
_groupMaxId = serializedObject.FindProperty("m_GroupMaxId");
_positionMode = serializedObject.FindProperty("m_PositionMode");
_autoScalingMode = serializedObject.FindProperty("m_AutoScalingMode");
_useCustomView = serializedObject.FindProperty("m_UseCustomView");
_customViewSize = serializedObject.FindProperty("m_CustomViewSize");
_timeScaleMultiplier = serializedObject.FindProperty("m_TimeScaleMultiplier");
var sp = serializedObject.FindProperty("m_Particles");
_ro = new ReorderableList(sp.serializedObject, sp, true, true, true, true)
{
elementHeightCallback = index =>
{
var ps = sp.GetArrayElementAtIndex(index).objectReferenceValue as ParticleSystem;
var materialCount = 0;
if (ps && ps.TryGetComponent<ParticleSystemRenderer>(out var psr))
{
materialCount = psr.sharedMaterials.Length;
}
return (materialCount + 1) * (EditorGUIUtility.singleLineHeight + 2);
},
elementHeight = EditorGUIUtility.singleLineHeight * 3 + 4,
elementHeightCallback = _ => 3 * (EditorGUIUtility.singleLineHeight + 2),
drawElementCallback = (rect, index, _, __) =>
{
rect.y += 2;
EditorGUI.BeginDisabledGroup(sp.hasMultipleDifferentValues);
rect.y += 1;
rect.height = EditorGUIUtility.singleLineHeight;
var p = sp.GetArrayElementAtIndex(index);
EditorGUI.ObjectField(rect, p, GUIContent.none);
var ps = p.objectReferenceValue as ParticleSystem;
if (!ps || !ps.TryGetComponent<ParticleSystemRenderer>(out var psr)) return;
rect.x += 15;
rect.width -= 15;
var materials = new SerializedObject(psr).FindProperty("m_Materials");
var count = Mathf.Min(materials.arraySize, 2);
for (var i = 0; i < count; i++)
{
rect.y += rect.height + 2;
EditorGUI.PropertyField(rect, materials.GetArrayElementAtIndex(i), s_ContentMaterials[i]);
}
if (materials.serializedObject.hasModifiedProperties)
var ps = p.objectReferenceValue as ParticleSystem;
var materials = ps
? new SerializedObject(ps.GetComponent<ParticleSystemRenderer>()).FindProperty("m_Materials")
: null;
rect.y += rect.height + 1;
MaterialField(rect, s_ContentMaterial, materials, 0);
rect.y += rect.height + 1;
MaterialField(rect, s_ContentTrailMaterial, materials, 1);
EditorGUI.EndDisabledGroup();
if (materials != null && materials.serializedObject.hasModifiedProperties)
{
materials.serializedObject.ApplyModifiedProperties();
}
@@ -167,18 +213,19 @@ namespace Coffee.UIExtensions
uip.RefreshParticles(uip.particles);
}
}
}
// Initialize 3D scale mode.
_is3DScaleMode = State.instance.is3DScaleMode;
if (!_is3DScaleMode)
private static void MaterialField(Rect rect, GUIContent label, SerializedProperty sp, int index)
{
if (sp == null || sp.arraySize <= index)
{
var x = _scale3D.FindPropertyRelative("x");
var y = _scale3D.FindPropertyRelative("y");
var z = _scale3D.FindPropertyRelative("z");
_is3DScaleMode = !Mathf.Approximately(x.floatValue, y.floatValue) ||
!Mathf.Approximately(y.floatValue, z.floatValue) ||
y.hasMultipleDifferentValues ||
z.hasMultipleDifferentValues;
EditorGUI.BeginDisabledGroup(true);
EditorGUI.ObjectField(rect, label, null, typeof(Material), true);
EditorGUI.EndDisabledGroup();
}
else
{
EditorGUI.PropertyField(rect, sp.GetArrayElementAtIndex(index), label);
}
}
@@ -190,7 +237,6 @@ namespace Coffee.UIExtensions
var current = target as UIParticle;
if (!current) return;
Profiler.BeginSample("(UIP:E) OnInspectorGUI");
serializedObject.Update();
// Maskable
@@ -198,16 +244,17 @@ namespace Coffee.UIExtensions
// Scale
EditorGUI.BeginDisabledGroup(!_meshSharing.hasMultipleDifferentValues && _meshSharing.intValue == 4);
if (DrawFloatOrVector3Field(_scale3D, _is3DScaleMode) != _is3DScaleMode)
{
State.instance.is3DScaleMode = _is3DScaleMode = !_is3DScaleMode;
}
s_XYZMode = DrawFloatOrVector3Field(_scale3D, s_XYZMode);
EditorGUI.EndDisabledGroup();
// AnimatableProperties
current.GetMaterials(s_TempMaterials);
AnimatablePropertyEditor.Draw(_animatableProperties, s_TempMaterials);
var mats = current.particles
.Where(x => x)
.Select(x => x.GetComponent<ParticleSystemRenderer>().sharedMaterial)
.Where(x => x)
.ToArray();
AnimatablePropertyEditor.Draw(_animatableProperties, mats);
// Mesh sharing
EditorGUI.BeginChangeCheck();
@@ -215,12 +262,9 @@ namespace Coffee.UIExtensions
if (EditorGUI.EndChangeCheck())
{
serializedObject.ApplyModifiedProperties();
foreach (var t in targets)
foreach (var uip in targets.OfType<UIParticle>())
{
if (t is UIParticle uip)
{
uip.ResetGroupId();
}
uip.ResetGroupId();
}
}
@@ -228,32 +272,16 @@ namespace Coffee.UIExtensions
EditorGUILayout.PropertyField(_positionMode);
// Auto Scaling
EditorGUILayout.PropertyField(_autoScalingMode);
// Custom View Size
EditorGUILayout.PropertyField(_useCustomView);
EditorGUI.BeginChangeCheck();
EditorGUI.BeginDisabledGroup(!_useCustomView.boolValue);
EditorGUI.indentLevel++;
EditorGUILayout.PropertyField(_customViewSize);
EditorGUI.indentLevel--;
EditorGUI.EndDisabledGroup();
if (EditorGUI.EndChangeCheck())
{
_customViewSize.floatValue = Mathf.Max(0.1f, _customViewSize.floatValue);
}
// Time Scale Multiplier
EditorGUILayout.PropertyField(_timeScaleMultiplier);
DrawAutoScaling(_autoScalingMode, targets.OfType<UIParticle>());
// Target ParticleSystems.
EditorGUI.BeginChangeCheck();
EditorGUI.BeginDisabledGroup(targets.OfType<UIParticle>().Any(x => !x.canvas));
_ro.DoLayoutList();
EditorGUI.EndDisabledGroup();
serializedObject.ApplyModifiedProperties();
if (EditorGUI.EndChangeCheck())
{
EditorApplication.QueuePlayerLoopUpdate();
foreach (var uip in targets.OfType<UIParticle>())
{
uip.RefreshParticles(uip.particles);
@@ -261,8 +289,7 @@ namespace Coffee.UIExtensions
}
// Non-UI built-in shader is not supported.
Profiler.BeginSample("(UIP:E) Non-UI built-in shader is not supported.");
foreach (var mat in s_TempMaterials)
foreach (var mat in current.materials)
{
if (!mat || !mat.shader) continue;
var shader = mat.shader;
@@ -275,18 +302,15 @@ namespace Coffee.UIExtensions
}
}
Profiler.EndSample();
// Does the shader support UI masks?
Profiler.BeginSample("(UIP:E) Does the shader support UI masks?");
if (current.maskable && current.GetComponentInParent<Mask>(false))
{
foreach (var mat in s_TempMaterials)
foreach (var mat in current.materials)
{
if (!mat || !mat.shader) continue;
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)
{
if (mat.HasProperty(propName)) continue;
@@ -300,9 +324,7 @@ namespace Coffee.UIExtensions
}
}
s_TempMaterials.Clear();
s_Shaders.Clear();
Profiler.EndSample();
// UIParticle for trail should be removed.
var label = "This UIParticle component should be removed. The UIParticle for trails is no longer needed.";
@@ -341,14 +363,12 @@ namespace Coffee.UIExtensions
}
}
#endif
Profiler.EndSample();
}
private static bool IsBuiltInObject(Object obj)
private bool IsBuiltInObject(Object obj)
{
return AssetDatabase.IsMainAsset(obj)
&& AssetDatabase.TryGetGUIDAndLocalFileIdentifier(obj, out var guid, out long _)
&& s_RegexBuiltInGuid.IsMatch(guid);
return AssetDatabase.TryGetGUIDAndLocalFileIdentifier(obj, out var guid, out long _)
&& Regex.IsMatch(guid, "^0{16}.0{15}$", RegexOptions.Compiled);
}
#if UNITY_2018 || UNITY_2019
@@ -442,7 +462,7 @@ namespace Coffee.UIExtensions
{
EditorGUI.BeginDisabledGroup(true);
var obj = UIParticleUpdater.GetPrimary(spGroupId.intValue);
EditorGUILayout.ObjectField(s_ContentPrimary, obj, typeof(UIParticle), false);
EditorGUILayout.ObjectField("Primary", obj, typeof(UIParticle), false);
EditorGUI.EndDisabledGroup();
}
@@ -452,20 +472,63 @@ namespace Coffee.UIExtensions
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);
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)
{
if (!p || (ignoreCurrent && target == p)) return;
Misc.DestroyImmediate(p);
if (p.TryGetComponent<CanvasRenderer>(out var cr))
{
Misc.DestroyImmediate(cr);
}
var cr = p.canvasRenderer;
DestroyImmediate(p);
DestroyImmediate(cr);
#if UNITY_2018_3_OR_NEWER
var stage = PrefabStageUtility.GetCurrentPrefabStage();

8
Packages/src/Icons.meta Normal file
View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 7a55e246f37df405bac88eac692e3a86
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

Before

Width:  |  Height:  |  Size: 418 B

After

Width:  |  Height:  |  Size: 418 B

View File

@@ -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:

View File

@@ -1,87 +1,61 @@
# <img alt="UIParticleIcon" src="https://github.com/mob-sakai/ParticleEffectForUGUI/assets/12690315/d76e105e-a840-4f61-a1f6-8cf311c0812d" width="26"/> UI Particle v5 <!-- omit in toc -->
# Particle Effect For UGUI (UI Particle)
This package provides a component to render particle effects for uGUI in Unity 2018.2 or later.
The particle rendering is maskable and sortable, without the need for an extra Camera, RenderTexture, or Canvas.
[![](https://img.shields.io/npm/v/com.coffee.ui-particle?label=openupm&registry_uri=https://package.openupm.com)](https://openupm.com/packages/com.coffee.ui-particle/)
[![](https://img.shields.io/github/v/release/mob-sakai/ParticleEffectForUGUI)](https://github.com/mob-sakai/ParticleEffectForUGUI/releases)
[![](https://img.shields.io/github/license/mob-sakai/ParticleEffectForUGUI.svg)](https://github.com/mob-sakai/ParticleEffectForUGUI/blob/main/LICENSE.md)
![](https://img.shields.io/badge/Unity-2019.3+-57b9d3.svg?style=flat&logo=unity)
![](https://img.shields.io/badge/uGUI_2.0_Ready-57b9d3.svg?style=flat)
![](https://img.shields.io/badge/UPR%2FHDPR_Ready-57b9d3.svg?style=flat)
[![](https://img.shields.io/github/v/release/mob-sakai/ParticleEffectForUGUI?include_prereleases)](https://github.com/mob-sakai/ParticleEffectForUGUI/releases)
[![](https://img.shields.io/github/license/mob-sakai/ParticleEffectForUGUI.svg)](https://github.com/mob-sakai/ParticleEffectForUGUI/blob/main/LICENSE.txt)
![](https://img.shields.io/badge/Unity-2018.2+-57b9d3.svg?style=flat&logo=unity)
![](https://github.com/mob-sakai/ParticleEffectForUGUI/actions/workflows/test.yml/badge.svg?branch=develop)
[![PRs Welcome](https://img.shields.io/badge/PRs-welcome-orange.svg)](http://makeapullrequest.com)
[![](https://img.shields.io/github/watchers/mob-sakai/ParticleEffectForUGUI.svg?style=social&label=Watch)](https://github.com/mob-sakai/ParticleEffectForUGUI/subscription)
[![](https://img.shields.io/twitter/follow/mob_sakai.svg?label=Follow&style=social)](https://twitter.com/intent/follow?screen_name=mob_sakai)
<< [📝 Description](#-description-) | [📌 Key Features](#-key-features) | [🎮 Demo](#-demo) | [⚙ Installation](#-installation) | [🔄 Upgrading to 5.x](#-upgrading-from-3x4x-to-5x) | [🚀 Usage](#-usage) | [🛠 Development Note](#-development-note) | [🤝 Contributing](#-contributing) >>
## 📝 Description <!-- omit in toc -->
![](https://user-images.githubusercontent.com/12690315/41771577-8da4b968-7650-11e8-9524-cd162c422d9d.gif)
This package uses the new APIs `MeshBake/MeshTrailBake` (introduced in Unity 2018.2) to render particles through `CanvasRenderer`.
You can render, mask, and sort your `ParticleSystems` for UI without the need for an additional `Camera`, `RenderTexture`, or `Canvas`.
- [📌 Key Features](#-key-features)
- [🎮 Demo](#-demo)
- [⚙ Installation](#-installation)
- [Install via OpenUPM](#install-via-openupm)
- [Install via UPM (with Package Manager UI)](#install-via-upm-with-package-manager-ui)
- [Install via UPM (Manually)](#install-via-upm-manually)
- [Install as Embedded Package](#install-as-embedded-package)
- [🔄 Upgrading from v3/v4 to v5](#-upgrading-from-v3v4-to-v5)
- [Breaking Changes](#breaking-changes)
- [🚀 Usage](#-usage)
- [Component: UIParticle](#component-uiparticle)
- [Basic Usage](#basic-usage)
- [Usage with Your Existing ParticleSystem Prefab](#usage-with-your-existing-particlesystem-prefab)
- [Usage with `Mask` or `RectMask2D` Component](#usage-with-mask-or-rectmask2d-component)
- [Usage with Script](#usage-with-script)
- [Component: UIParticleAttractor](#component-uiparticleattractor)
- [Project Settings](#project-settings)
- [🛠 Development Note](#-development-note)
- [Compares the Baking mesh approach with the conventional approach](#compares-the-baking-mesh-approach-with-the-conventional-approach)
- [Performance test results](#performance-test-results)
- [🔍 FAQ: Why Are My UIParticles Not Displayed Correctly?](#-faq-why-are-my-uiparticles-not-displayed-correctly)
- [Shader Limitation](#shader-limitation)
- [Built-in shaders are not supported](#built-in-shaders-are-not-supported)
- [(Unity 2018 or 2019) UV.zw components will be discarded](#unity-2018-or-2019-uvzw-components-will-be-discarded)
- [(Unity 2018 or 2019) Custom vertex streams](#unity-2018-or-2019-custom-vertex-streams)
- [Overheads](#overheads)
- [How to Make a Custom Shader to Support `Mask` and `RectMask2D` Component](#how-to-make-a-custom-shader-to-support-mask-and-rectmask2d-component)
- [🤝 Contributing](#-contributing)
- [Issues](#issues)
- [Pull Requests](#pull-requests)
- [Support](#support)
- [License](#license)
- [Author](#author)
- [See Also](#see-also)
<< [📝 Description](#-description) | [🎮 Demo](#-demo) | [⚙ Installation](#-installation) | [🚀 Usage](#-usage) | [🛠 Development Note](#-development-note) | [🤝 Contributing](#-contributing) >>
<br><br>
## 📌 Key Features
## 📝 Description
* **Easy to use:** The package is ready to use out of the box.
* **Sortable:** Sort particle effects and other UI elements by sibling index.
* **Maskable:** Supports `Mask` or `RectMask2D`.
* **No extra components required:** No need for an additional `Camera`, `RenderTexture`, or `Canvas`.
* **Trail module support:** Fully supports the Trail module.
* **CanvasGroup alpha support:** Integrates with `CanvasGroup` alpha.
* **No allocations:** Efficiently renders particles without allocations.
* **Any canvas render mode support:** Works with overlay, camera space, and world space.
* **Any Render pipeline support:** Compatible with Universal Render Pipeline (URP) and High Definition Render Pipeline (HDRP).
* **Disabling domain reload support:** Supports disabling `Enter Play Mode Options > Reload Domain`.
* **Animatable material properties:** Supports changing material properties with AnimationClip (AnimatableProperty).
![AnimatableProperty.gif](https://user-images.githubusercontent.com/12690315/53286323-2d94a980-37b0-11e9-8afb-c4a207805ff2.gif)
* **Multiple materials:** Supports 8+ materials.
* **Correct positioning:** Adjusts world space particle positions correctly when changing window size for standalone platforms (Windows, MacOSX, and Linux).
* **Adaptive scaling:** Provides adaptive scaling for UI (AutoScalingMode).
* **Performance optimization:** Mesh sharing group to improve performance.
<img alt="MeshSharing.gif" src="https://user-images.githubusercontent.com/12690315/174311048-c882df81-6c34-4eba-b0aa-5645457692f1.gif" width="450"/>
* **Particle attractor:** Includes a particle attractor component.
<img alt="ParticleAttractor.gif" src="https://user-images.githubusercontent.com/12690315/174311027-462929a4-13f0-4ec4-86ea-9c832f2eecf1.gif" width="450"/>
* **Emission position mode:** Supports relative/absolute particle emission position modes.
<img alt="AbsolutePosition.gif" src="https://user-images.githubusercontent.com/12690315/175751579-5a2357e8-2ecf-4afd-83c8-66e9771bde39.gif" width="450"/>
* **Custom view size:** Fixes min/max particle size mismatch.
![CustomViewSize.gif](https://github.com/mob-sakai/ParticleEffectForUGUI/assets/12690315/dd929959-1a37-420b-b13d-e849022b9c9d)
![](https://user-images.githubusercontent.com/12690315/41771577-8da4b968-7650-11e8-9524-cd162c422d9d.gif)
This package utilizes the new APIs `MeshBake/MashTrailBake` (introduced with Unity 2018.2) to render particles through
CanvasRenderer.
You can render, mask, and sort your ParticleSystems for UI without the necessity of an additional Camera, RenderTexture,
or Canvas.
### Features
* Easy to use: The package is ready to use out of the box.
* Sort particle effects and other UI by sibling index.
* No extra Camera, RenderTexture, or Canvas required.
* Masking options for Mask or RectMask2D.
* Support for the Trail module.
* Support for CanvasGroup alpha.
* No allocations needed to render particles.
* Compatibility with overlay, camera space, and world space.
* Support for Universal Render Pipeline (URP) and High Definition Render Pipeline (HDRP).
* Support for disabling `Enter Play Mode Options > Reload Domain`.
* Support for changing material property with AnimationClip (AnimatableProperty).
![AnimatableProperty.gif][AnimatableProperty.gif]
* [4.0.0+] Support for 8+ materials.
* [4.0.0+] Correct world space particle position adjustment when changing window size for standalone platforms (Windows,
MacOSX, and Linux).
* [4.0.0+] Adaptive scaling for UI.
* [4.0.0+] Mesh sharing group to improve performance.
![MeshSharing.gif][MeshSharing.gif]
* [4.0.0+] Particle attractor component.
![ParticleAttractor.gif][ParticleAttractor.gif]
* [4.1.0+] Relative/Absolute particle position mode.
![AbsolutePosition.gif][AbsolutePosition.gif]
[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>
@@ -102,106 +76,66 @@ You can render, mask, and sort your `ParticleSystems` for UI without the need fo
[JMO]: https://assetstore.unity.com/publishers/1669
<br><br>
## ⚙ Installation
_This package requires **Unity 2019.3 or later**._
_This package requires Unity 2018.3 or later._
#### Install via OpenUPM
- This package is available on [OpenUPM](https://openupm.com) package registry.
- This is the preferred method of installation, as you can easily receive updates as they're released.
- 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@5.0.0
```
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.
#### 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.
- Click `+ > Add package from git URL...` and input the repository URL: `https://github.com/mob-sakai/ParticleEffectForUGUI.git?path=Packages/src`
![](https://github.com/user-attachments/assets/f88f47ad-c606-44bd-9e86-ee3f72eac548)
- To update the package, change suffix `#{version}` to the target version.
- e.g. `https://github.com/mob-sakai/ParticleEffectForUGUI.git?path=Packages/src#5.0.0`
```sh
openupm add com.coffee.ui-particle
```
#### 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:
```json
{
"dependencies": {
"com.coffee.ui-particle": "https://github.com/mob-sakai/ParticleEffectForUGUI.git?path=Packages/src",
...
}
Navigate to your project's Packages folder and open the `manifest.json` file. Then add this package somewhere in
the `dependencies` block:
```json
{
"dependencies": {
"com.coffee.ui-particle": "https://github.com/mob-sakai/ParticleEffectForUGUI.git",
...
}
```
}
```
- To update the package, change suffix `#{version}` to the target version.
- e.g. `"com.coffee.ui-particle": "https://github.com/mob-sakai/ParticleEffectForUGUI.git?path=Packages/src#5.0.0",`
To update the package, change suffix `#{version}` to the target version.
### Install as Embedded Package
* e.g. `"com.coffee.ui-particle": "https://github.com/mob-sakai/ParticleEffectForUGUI.git#4.6.0",`
1. Download the `Source code (zip)` file from [Releases](https://github.com/mob-sakai/SoftMaskForUGUI/releases) and
extract it.
2. Move the `<extracted_dir>/Packages/src` directory into your project's `Packages` directory.
![](https://github.com/user-attachments/assets/187cbcbe-5922-4ed5-acec-cf19aa17d208)
- You can rename the `src` directory if needed.
- If you intend to fix bugs or add features, installing it as an embedded package is recommended.
- To update the package, re-download it and replace the existing contents.
<br><br>
## 🔄 Upgrading from v3/v4 to v5
### Breaking Changes
- The default value of `UIParticle.scale` has been changed from `10` to `1`.
- `UIParticle` no longer inherits from `MaskableGraphic`.
- If you are installing via git URL, add `?path=Packages/src`.
```json
// v3/v4
"com.coffee.ui-particle": "https://github.com/mob-sakai/ParticleEffectForUGUI.git",
// v5
"com.coffee.ui-particle": "https://github.com/mob-sakai/ParticleEffectForUGUI.git?path=Packages/src",
```
Or, use [UpmGitExtension](https://github.com/mob-sakai/UpmGitExtension) to install and update the package.
<br><br>
## 🚀 Usage
### Component: UIParticle
### UIParticle Component
`UIParticle` controls the ParticleSystems that are attached to its own game objects and child game objects.
![](https://github.com/user-attachments/assets/bc9eb783-afce-4102-ac61-aee9ea8d6f2f)
![](https://github.com/mob-sakai/ParticleEffectForUGUI/assets/12690315/3559df45-63e7-4c4c-9233-f455779efa29)
- **Maskable**: Does this graphic allow maskable.
- **Scale**: Scale the rendering particles. When the `3D` toggle is enabled, 3D scale (x, y, z) is supported.
- **Maskable**: Does this graphic allow masking.
- **Scale**: Scale the rendering. When the `3D` toggle is enabled, 3D scale (x, y, z) is supported.
- **Animatable Properties**: If you want to update material properties (e.g., `_MainTex_ST`, `_Color`) in AnimationClip,
use this to mark 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
be displayed with a small load. When the `Random` toggle is enabled, it will be grouped randomly.
- **None:** Disable mesh sharing.
- **Auto:** Automatically select Primary/Replica.
- **Primary:** Provides particle simulation results to the same group.
- **Primary Simulator:** Primary, but do not render the particle (simulation only).
- **Replica:** Render simulation results provided by the primary.
- **Position Mode**: Emission position mode.
- **Absolute:** The particles will be emitted from the world position.
- **Relative:** The particles will be emitted from the scaled position.
- **Auto Scaling Mode**: How to automatically adjust when the Canvas scale is changed by the screen size or reference resolution.
- **None:** Do nothing.
- **Transform:** Transform.lossyScale (=world scale) will be set to (1, 1, 1).
- **UIParticle:** UIParticle.scale will be adjusted.
- **Use Custom View:** Use this if the particles are not displayed correctly due to min/max particle size.
- **Custom view size:** Change the bake view size.
- **Time Scale Multiplier:** Time scale multiplier.
- **Absolute:** Emit from the world position of the `ParticleSystem`.
- **Relative:** Emit from the scaled position of the `ParticleSystem`.
- **Auto Scaling**: `Transform.lossyScale` (=world scale) will be set to `(1, 1, 1)` on update. It prevents the
root-Canvas scale from affecting the hierarchy-scaled `ParticleSystem`.
- **Rendering Order**: The ParticleSystem list to be rendered. You can change the order and the materials.
**NOTE:** Press the `Refresh` button to reconstruct the rendering order based on children ParticleSystem's sorting order
@@ -209,7 +143,7 @@ and z-position.
<br><br>
### Basic Usage
#### Basic Usage
1. Select `GameObject/UI/ParticleSystem` to create UIParticle with a ParticleSystem.
![particle](https://user-images.githubusercontent.com/12690315/95007361-cad0e880-0649-11eb-8835-f145d62c5977.png)
@@ -218,7 +152,7 @@ and z-position.
<br>
### Usage with Your Existing ParticleSystem Prefab
#### With Your Existing ParticleSystem Prefab
1. Select `GameObject/UI/ParticleSystem (Empty)` to create UIParticle.
![empty](https://user-images.githubusercontent.com/12690315/95007362-cb697f00-0649-11eb-8a09-29b0a13791e4.png)
@@ -227,25 +161,24 @@ and z-position.
<br>
### Usage with `Mask` or `RectMask2D` Component
#### With `Mask` or `RectMask2D` Component
If you want to mask particles, set a stencil-supported shader (such as `UI/UIAdditive`) to the material for
ParticleSystem.
If you use some custom shaders, see
the [How to Make a Custom Shader to Support Mask/RectMask2D Component](#how-to-make-a-custom-shader-to-support-mask-and-rectmask2d-component)
the [How to Make a Custom Shader to Support Mask/RectMask2D Component](#how-to-make-a-custom-shader-to-support-maskrectmask2d-component)
section.
![](https://user-images.githubusercontent.com/12690315/95017591-3b512700-0695-11eb-864e-04166ea1809a.png)
<br><br>
### Usage with Script
### Script usage
```cs
// Instantiate ParticleSystem prefab with UIParticle on runtime.
// Instant ParticleSystem prefab with UIParticle on runtime.
var go = GameObject.Instantiate(prefab);
var uiParticle = go.AddComponent<UIParticle>();
uiParticle.scale = 100;
// Control by ParticleSystem.
particleSystem.Play();
@@ -258,14 +191,14 @@ uiParticle.Stop();
<br><br>
### Component: UIParticleAttractor
### UIParticleAttractor component
`UIParticleAttractor` attracts particles generated by the specified ParticleSystem.
![](https://github.com/mob-sakai/ParticleEffectForUGUI/assets/12690315/5c20ad73-4b9a-4f38-9cdc-119df5cce077)
![](https://github.com/mob-sakai/ParticleEffectForUGUI/assets/12690315/ea6ae0ed-f9a8-437c-8baa-47526303391e)
![](https://user-images.githubusercontent.com/12690315/174311027-462929a4-13f0-4ec4-86ea-9c832f2eecf1.gif)
- **Particle Systems**: Attracts particles generated by the specified ParticleSystems.
- **Particle System**: Attracts particles generated by the specified particle system.
- **Destination Radius**: Once the particle is within the radius, the particle lifetime will become 0, and `OnAttracted`
will be called.
- **Delay Rate**: Delay to start attracting. It is a percentage of the particle's start lifetime.
@@ -279,14 +212,6 @@ uiParticle.Stop();
<br><br>
### Project Settings
![](https://github.com/user-attachments/assets/befc7f34-fb47-4006-831a-eba79fda11ca)
- Click `Edit > Project Settings` to open the Project Settings window and then select `UI > UI Particle` category.
<br><br>
## 🛠 Development Note
### Compares the Baking mesh approach with the conventional approach
@@ -418,7 +343,7 @@ When improving performance, keep the following in mind:
- Consider a single material, atlasing the sprites, and using `Sprite` mode in the `Texture Sheet Animation` module
in the ParticleSystem.
### How to Make a Custom Shader to Support `Mask` and `RectMask2D` Component
### How to Make a Custom Shader to Support Mask/RectMask2D Component
<details>
<summary>Shader tips</summary>

View File

@@ -1,33 +0,0 @@
fileFormatVersion: 2
guid: 4d73b3825bf044d418ae21bb331d3902
PluginImporter:
externalObjects: {}
serializedVersion: 2
iconMap: {}
executionOrder: {}
defineConstraints: []
isPreloaded: 0
isOverridable: 1
isExplicitlyReferenced: 0
validateReferences: 1
platformData:
- first:
Any:
second:
enabled: 1
settings: {}
- first:
Editor: Editor
second:
enabled: 0
settings:
DefaultValueInitialized: true
- first:
Windows Store Apps: WindowsStoreApps
second:
enabled: 0
settings:
CPU: AnyCPU
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -1,5 +1,4 @@
using System;
using System.Collections.Generic;
using UnityEditor;
using UnityEngine;
using UnityEngine.Profiling;
@@ -12,48 +11,6 @@ namespace Coffee.UIParticleInternal
/// </summary>
internal static class ComponentExtensions
{
/// <summary>
/// Get components in children of a specific type in the hierarchy of a GameObject.
/// </summary>
public static T[] GetComponentsInChildren<T>(this Component self, int depth)
where T : Component
{
var results = InternalListPool<T>.Rent();
self.GetComponentsInChildren_Internal(results, depth);
var array = results.ToArray();
InternalListPool<T>.Return(ref results);
return array;
}
/// <summary>
/// Get components in children of a specific type in the hierarchy of a GameObject.
/// </summary>
public static void GetComponentsInChildren<T>(this Component self, List<T> results, int depth)
where T : Component
{
results.Clear();
self.GetComponentsInChildren_Internal(results, depth);
}
private static void GetComponentsInChildren_Internal<T>(this Component self, List<T> results, int depth)
where T : Component
{
if (!self || results == null || depth < 0) return;
var tr = self.transform;
if (tr.TryGetComponent<T>(out var t))
{
results.Add(t);
}
if (depth - 1 < 0) return;
var childCount = tr.childCount;
for (var i = 0; i < childCount; i++)
{
tr.GetChild(i).GetComponentsInChildren_Internal(results, depth - 1);
}
}
/// <summary>
/// Get or add a component of a specific type to a GameObject.
/// </summary>
@@ -134,35 +91,6 @@ namespace Coffee.UIParticleInternal
Profiler.EndSample();
}
/// <summary>
/// Add a component of a specific type to the children of a GameObject.
/// </summary>
public static void AddComponentOnChildren<T>(this Component self, bool includeSelf)
where T : Component
{
if (self == null) return;
Profiler.BeginSample("(COF)[ComponentExt] AddComponentOnChildren > Self");
if (includeSelf && !self.TryGetComponent<T>(out _))
{
self.gameObject.AddComponent<T>();
}
Profiler.EndSample();
Profiler.BeginSample("(COF)[ComponentExt] AddComponentOnChildren > Child");
var childCount = self.transform.childCount;
for (var i = 0; i < childCount; i++)
{
var child = self.transform.GetChild(i);
if (child.TryGetComponent<T>(out _)) continue;
child.gameObject.AddComponent<T>();
}
Profiler.EndSample();
}
#if !UNITY_2021_2_OR_NEWER && !UNITY_2020_3_45 && !UNITY_2020_3_46 && !UNITY_2020_3_47 && !UNITY_2020_3_48
public static T GetComponentInParent<T>(this Component self, bool includeInactive) where T : Component
{
@@ -204,7 +132,7 @@ namespace Coffee.UIParticleInternal
target.enabled = false;
// Find MonoScript of the specified component.
foreach (var script in MonoImporter.GetAllRuntimeMonoScripts())
foreach (var script in Resources.FindObjectsOfTypeAll<MonoScript>())
{
if (script.GetClass() != typeof(T))
{

View 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);
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 833553390099d40c9b212823f0852c46
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View 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
}
}
}

View File

@@ -1,5 +1,5 @@
fileFormatVersion: 2
guid: 182319ecc315e4858b119764af0fbcb0
guid: 39ed6a6b0a72e482488bd298b2ae762e
MonoImporter:
externalObjects: {}
serializedVersion: 2

View File

@@ -17,15 +17,11 @@ namespace Coffee.UIParticleInternal
Type.GetType("UnityEditor.Experimental.U2D.SpriteEditorExtension, UnityEditor")
?? Type.GetType("UnityEditor.U2D.SpriteEditorExtension, UnityEditor");
private static readonly Func<Sprite, Texture2D> s_GetActiveAtlasTextureMethod =
(Func<Sprite, Texture2D>)Delegate.CreateDelegate(typeof(Func<Sprite, Texture2D>),
s_SpriteEditorExtensionType
.GetMethod("GetActiveAtlasTexture", BindingFlags.Static | BindingFlags.NonPublic));
private static readonly MethodInfo s_GetActiveAtlasTextureMethod = s_SpriteEditorExtensionType
.GetMethod("GetActiveAtlasTexture", BindingFlags.Static | BindingFlags.NonPublic);
private static readonly Func<Sprite, SpriteAtlas> s_GetActiveAtlasMethod =
(Func<Sprite, SpriteAtlas>)Delegate.CreateDelegate(typeof(Func<Sprite, SpriteAtlas>),
s_SpriteEditorExtensionType
.GetMethod("GetActiveAtlas", BindingFlags.Static | BindingFlags.NonPublic));
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.
@@ -34,7 +30,9 @@ namespace Coffee.UIParticleInternal
{
if (!self) return null;
var ret = s_GetActiveAtlasTextureMethod(self);
if (Application.isPlaying) return self.texture;
var ret = s_GetActiveAtlasTextureMethod.Invoke(null, new object[] { self }) as Texture2D;
return ret ? ret : self.texture;
}
@@ -45,7 +43,7 @@ namespace Coffee.UIParticleInternal
{
if (!self) return null;
return s_GetActiveAtlasMethod(self);
return s_GetActiveAtlasMethod.Invoke(null, new object[] { self }) as SpriteAtlas;
}
#else
/// <summary>

View File

@@ -1,9 +1,9 @@
using System;
using System.Linq;
using System.Reflection;
using UnityEngine;
using Object = UnityEngine.Object;
#if UNITY_EDITOR
using System.IO;
using UnityEditor;
using UnityEditor.Build;
using UnityEditor.Build.Reporting;
@@ -13,51 +13,41 @@ namespace Coffee.UIParticleInternal
{
public abstract class PreloadedProjectSettings : ScriptableObject
#if UNITY_EDITOR
, IPreprocessBuildWithReport
{
private class Postprocessor : AssetPostprocessor
int IOrderedCallback.callbackOrder => 0;
void IPreprocessBuildWithReport.OnPreprocessBuild(BuildReport report)
{
private static void OnPostprocessAllAssets(string[] _, string[] __, string[] ___, string[] ____)
{
Initialize();
}
}
private class PreprocessBuildWithReport : IPreprocessBuildWithReport
{
int IOrderedCallback.callbackOrder => 0;
void IPreprocessBuildWithReport.OnPreprocessBuild(BuildReport report)
{
Initialize();
}
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)
{
// When create a new instance, automatically set it as default settings.
defaultSettings = CreateInstance(t) as PreloadedProjectSettings;
defaultSettings = t.GetProperty("instance", flags)
?.GetValue(null, null) as PreloadedProjectSettings;
SetDefaultSettings(defaultSettings);
}
else if (GetPreloadedSettings(t).Length != 1)
{
SetDefaultSettings(defaultSettings);
}
if (defaultSettings)
{
defaultSettings.OnInitialize();
}
}
EditorApplication.QueuePlayerLoopUpdate();
}
protected static string GetDefaultName(Type type, bool nicify)
{
var typeName = type.Name;
var typeName = type.Name.Replace("ProjectSettings", "");
return nicify
? ObjectNames.NicifyVariableName(typeName)
: typeName;
@@ -81,8 +71,6 @@ namespace Coffee.UIParticleInternal
protected static void SetDefaultSettings(PreloadedProjectSettings asset)
{
if (!asset) return;
var type = asset.GetType();
if (string.IsNullOrEmpty(AssetDatabase.GetAssetPath(asset)))
{
@@ -93,11 +81,7 @@ namespace Coffee.UIParticleInternal
var assetPath = $"Assets/ProjectSettings/{GetDefaultName(type, false)}.asset";
assetPath = AssetDatabase.GenerateUniqueAssetPath(assetPath);
if (!File.Exists(assetPath))
{
AssetDatabase.CreateAsset(asset, assetPath);
asset.OnCreateAsset();
}
AssetDatabase.CreateAsset(asset, assetPath);
}
var preloadedAssets = PlayerSettings.GetPreloadedAssets();
@@ -111,20 +95,13 @@ namespace Coffee.UIParticleInternal
AssetDatabase.Refresh();
}
protected virtual void OnCreateAsset()
{
}
protected virtual void OnInitialize()
{
}
}
#else
{
}
#endif
public abstract class PreloadedProjectSettings<T> : PreloadedProjectSettings
where T : PreloadedProjectSettings<T>
{
@@ -133,8 +110,6 @@ namespace Coffee.UIParticleInternal
#if UNITY_EDITOR
private string _jsonText;
public static bool hasInstance => s_Instance;
public static T instance
{
get

View File

@@ -10,9 +10,8 @@ namespace Coffee.UIParticleInternal
/// </summary>
internal class FastActionBase<T>
{
private static readonly InternalObjectPool<LinkedListNode<T>> s_NodePool =
new InternalObjectPool<LinkedListNode<T>>(() => new LinkedListNode<T>(default), _ => true,
x => x.Value = default);
private 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>();
@@ -21,7 +20,6 @@ namespace Coffee.UIParticleInternal
/// </summary>
public void Add(T rhs)
{
if (rhs == null) return;
Profiler.BeginSample("(COF)[FastAction] Add Action");
var node = s_NodePool.Rent();
node.Value = rhs;
@@ -34,7 +32,6 @@ namespace Coffee.UIParticleInternal
/// </summary>
public void Remove(T rhs)
{
if (rhs == null) return;
Profiler.BeginSample("(COF)[FastAction] Remove Action");
var node = _delegates.Find(rhs);
if (node != null)
@@ -66,11 +63,6 @@ namespace Coffee.UIParticleInternal
node = node.Next;
}
}
public void Clear()
{
_delegates.Clear();
}
}
/// <summary>

View File

@@ -46,6 +46,7 @@ namespace Coffee.UIParticleInternal
GetFrameCache<T>().Set((key1.GetHashCode(), key2.GetHashCode()), result);
}
/// <summary>
/// Sets a value in the frame cache with a specified key.
/// </summary>

View File

@@ -1,12 +1,11 @@
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;
#else
using Conditional = System.Diagnostics.ConditionalAttribute;
#endif
namespace Coffee.UIParticleInternal
@@ -42,6 +41,7 @@ namespace Coffee.UIParticleInternal
#endif
}
#if !ENABLE_COFFEE_LOGGER
[Conditional(k_DisableSymbol)]
#endif
@@ -51,6 +51,7 @@ namespace Coffee.UIParticleInternal
Log_Internal(LogType.Log, tag, message, context ? context : tag as Object);
}
#if !ENABLE_COFFEE_LOGGER
[Conditional(k_DisableSymbol)]
#endif
@@ -59,6 +60,7 @@ namespace Coffee.UIParticleInternal
Log_Internal(LogType.Log, tag, message, context ? context : tag as Object);
}
#if !ENABLE_COFFEE_LOGGER
[Conditional(k_DisableSymbol)]
#endif
@@ -76,6 +78,7 @@ namespace Coffee.UIParticleInternal
#endif
}
#if !ENABLE_COFFEE_LOGGER
[Conditional(k_DisableSymbol)]
#endif
@@ -119,6 +122,7 @@ namespace Coffee.UIParticleInternal
#endif
}
#if !ENABLE_COFFEE_LOGGER
[Conditional(k_DisableSymbol)]
#endif
@@ -135,9 +139,6 @@ namespace Coffee.UIParticleInternal
switch (tag)
{
case string name:
sb.Append(name);
break;
case Type type:
AppendType(sb, type);
break;
@@ -164,6 +165,7 @@ namespace Coffee.UIParticleInternal
#endif
}
#if !ENABLE_COFFEE_LOGGER
[Conditional(k_DisableSymbol)]
#endif
@@ -202,6 +204,7 @@ namespace Coffee.UIParticleInternal
#endif
}
#if !ENABLE_COFFEE_LOGGER
[Conditional(k_DisableSymbol)]
#endif

View File

@@ -15,7 +15,7 @@ namespace Coffee.UIParticleInternal
#if UNITY_EDITOR
[RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.SubsystemRegistration)]
public static void Clear()
private static void Clear()
{
s_Repository.Clear();
}
@@ -42,33 +42,6 @@ namespace Coffee.UIParticleInternal
Profiler.EndSample();
}
/// <summary>
/// Adds or retrieves a cached material based on the hash.
/// </summary>
public static void Get(Hash128 hash, ref Material material, string shaderName)
{
Profiler.BeginSample("(COF)[MaterialRepository] Get");
s_Repository.Get(hash, ref material, x => new Material(Shader.Find(x))
{
hideFlags = HideFlags.DontSave | HideFlags.NotEditable
}, shaderName);
Profiler.EndSample();
}
/// <summary>
/// Adds or retrieves a cached material based on the hash.
/// </summary>
public static void Get(Hash128 hash, ref Material material, string shaderName, string[] keywords)
{
Profiler.BeginSample("(COF)[MaterialRepository] Get");
s_Repository.Get(hash, ref material, x => new Material(Shader.Find(x.shaderName))
{
hideFlags = HideFlags.DontSave | HideFlags.NotEditable,
shaderKeywords = x.keywords
}, (shaderName, keywords));
Profiler.EndSample();
}
/// <summary>
/// Adds or retrieves a cached material based on the hash.
/// </summary>

View File

@@ -1,132 +0,0 @@
using System;
using System.Diagnostics;
using UnityEditor;
using UnityEngine;
using Object = UnityEngine.Object;
#if UNITY_EDITOR
using System.IO;
using System.Linq;
using System.Reflection;
#if UNITY_2021_2_OR_NEWER
using UnityEditor.SceneManagement;
#else
using UnityEditor.Experimental.SceneManagement;
#endif
#endif
namespace Coffee.UIParticleInternal
{
internal static class Misc
{
public static T[] FindObjectsOfType<T>() where T : Object
{
#if UNITY_2023_1_OR_NEWER
return Object.FindObjectsByType<T>(FindObjectsInactive.Include, FindObjectsSortMode.None);
#else
return Object.FindObjectsOfType<T>();
#endif
}
public static void Destroy(Object obj)
{
if (!obj) return;
#if UNITY_EDITOR
if (!Application.isPlaying)
{
Object.DestroyImmediate(obj);
}
else
#endif
{
Object.Destroy(obj);
}
}
public static void DestroyImmediate(Object obj)
{
if (!obj) return;
#if UNITY_EDITOR
if (Application.isEditor)
{
Object.DestroyImmediate(obj);
}
else
#endif
{
Object.Destroy(obj);
}
}
[Conditional("UNITY_EDITOR")]
public static void SetDirty(Object obj)
{
#if UNITY_EDITOR
if (!obj) return;
EditorUtility.SetDirty(obj);
#endif
}
#if UNITY_EDITOR
public static T[] GetAllComponentsInPrefabStage<T>() where T : Component
{
var prefabStage = PrefabStageUtility.GetCurrentPrefabStage();
if (prefabStage == null) return Array.Empty<T>();
return prefabStage.prefabContentsRoot.GetComponentsInChildren<T>(true);
}
public static bool isBatchOrBuilding => Application.isBatchMode || BuildPipeline.isBuildingPlayer;
#endif
[Conditional("UNITY_EDITOR")]
public static void QueuePlayerLoopUpdate()
{
#if UNITY_EDITOR
if (!EditorApplication.isPlaying)
{
EditorApplication.QueuePlayerLoopUpdate();
}
#endif
}
}
#if !UNITY_2021_2_OR_NEWER
[AttributeUsage(AttributeTargets.Class)]
[Conditional("UNITY_EDITOR")]
internal class IconAttribute : Attribute
{
private readonly string _path;
public IconAttribute(string path)
{
_path = path;
}
#if UNITY_EDITOR
private static Action<Object, Texture2D> s_SetIconForObject = typeof(EditorGUIUtility)
.GetMethod("SetIconForObject", BindingFlags.Static | BindingFlags.NonPublic)
.CreateDelegate(typeof(Action<Object, Texture2D>), null) as Action<Object, Texture2D>;
[InitializeOnLoadMethod]
private static void InitializeOnLoadMethod()
{
if (Misc.isBatchOrBuilding) return;
var types = TypeCache.GetTypesWithAttribute<IconAttribute>();
var scripts = MonoImporter.GetAllRuntimeMonoScripts();
foreach (var type in types)
{
var script = scripts.FirstOrDefault(x => x.GetClass() == type);
if (!script) continue;
var path = type.GetCustomAttribute<IconAttribute>()?._path;
var icon = AssetDatabase.LoadAssetAtPath<Texture2D>(path);
if (!icon) continue;
s_SetIconForObject(script, icon);
}
}
#endif
}
#endif
}

View File

@@ -6,58 +6,15 @@ namespace Coffee.UIParticleInternal
/// <summary>
/// Object pool.
/// </summary>
internal class InternalObjectPool<T> where T : class
internal class ObjectPool<T>
{
#if UNITY_2021_1_OR_NEWER
private readonly Predicate<T> _onValid; // Delegate for checking if instances are valid
private readonly UnityEngine.Pool.ObjectPool<T> _pool;
public InternalObjectPool(Func<T> onCreate, Predicate<T> onValid, Action<T> onReturn)
{
_pool = new UnityEngine.Pool.ObjectPool<T>(onCreate, null, onReturn);
_onValid = onValid;
}
/// <summary>
/// Rent an instance from the pool.
/// When you no longer need it, return it with <see cref="Return" />.
/// </summary>
public T Rent()
{
while (0 < _pool.CountInactive)
{
var instance = _pool.Get();
if (_onValid(instance))
{
return instance;
}
}
// If there are no instances in the pool, create a new one.
Logging.Log(this, $"A new instance is created (pooled: {_pool.CountInactive}, created: {_pool.CountAll}).");
return _pool.Get();
}
/// <summary>
/// Return an instance to the pool and assign null.
/// Be sure to return the instance obtained with <see cref="Rent" /> with this method.
/// </summary>
public void Return(ref T instance)
{
if (instance == null) return; // Ignore if already pooled or null.
_pool.Release(instance);
Logging.Log(this, $"An instance is released (pooled: {_pool.CountInactive}, created: {_pool.CountAll}).");
instance = default; // Set the reference to null.
}
#else
private readonly Func<T> _onCreate; // Delegate for creating instances
private readonly Action<T> _onReturn; // Delegate for returning instances to the pool
private readonly Predicate<T> _onValid; // Delegate for checking if instances are valid
private readonly Stack<T> _pool = new Stack<T>(32); // Object pool
private int _count; // Total count of created instances
public InternalObjectPool(Func<T> onCreate, Predicate<T> onValid, Action<T> onReturn)
public ObjectPool(Func<T> onCreate, Predicate<T> onValid, Action<T> onReturn)
{
_onCreate = onCreate;
_onValid = onValid;
@@ -97,40 +54,15 @@ namespace Coffee.UIParticleInternal
Logging.Log(this, $"An instance is released (pooled: {_pool.Count}, created: {_count}).");
instance = default; // Set the reference to null.
}
#endif
}
/// <summary>
/// Object pool for <see cref="List{T}" />.
/// </summary>
internal static class InternalListPool<T>
internal static class ListPool<T>
{
#if UNITY_2021_1_OR_NEWER
/// <summary>
/// Rent an instance from the pool.
/// When you no longer need it, return it with <see cref="Return" />.
/// </summary>
public static List<T> Rent()
{
return UnityEngine.Pool.ListPool<T>.Get();
}
/// <summary>
/// Return an instance to the pool and assign null.
/// Be sure to return the instance obtained with <see cref="Rent" /> with this method.
/// </summary>
public static void Return(ref List<T> toRelease)
{
if (toRelease != null)
{
UnityEngine.Pool.ListPool<T>.Release(toRelease);
}
toRelease = null;
}
#else
private static readonly InternalObjectPool<List<T>> s_ListPool =
new InternalObjectPool<List<T>>(() => new List<T>(), _ => true, x => x.Clear());
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.
@@ -149,6 +81,5 @@ namespace Coffee.UIParticleInternal
{
s_ListPool.Return(ref toRelease);
}
#endif
}
}

View File

@@ -8,11 +8,10 @@ namespace Coffee.UIParticleInternal
{
internal class ObjectRepository<T> where T : Object
{
private readonly Dictionary<Hash128, Entry> _cache = new Dictionary<Hash128, Entry>(8);
private readonly Dictionary<int, Hash128> _objectKey = new Dictionary<int, Hash128>(8);
private readonly List<Entry> _cache = new List<Entry>();
private readonly string _name;
private readonly Action<T> _onRelease;
private readonly Stack<Entry> _pool = new Stack<Entry>(8);
private readonly Stack<Entry> _pool = new Stack<Entry>();
public ObjectRepository(Action<T> onRelease = null)
{
@@ -37,33 +36,40 @@ namespace Coffee.UIParticleInternal
{
_onRelease = onRelease;
}
for (var i = 0; i < 8; i++)
{
_pool.Push(new Entry());
}
}
public int count => _cache.Count;
public void Clear()
{
foreach (var kv in _cache)
for (var i = 0; i < _cache.Count; i++)
{
var entry = kv.Value;
var entry = _cache[i];
if (entry == null) continue;
entry.Release(_onRelease);
_pool.Push(entry);
}
_cache.Clear();
_objectKey.Clear();
}
public bool Valid(Hash128 hash, T obj)
{
return _cache.TryGetValue(hash, out var entry) && entry.storedObject == obj;
// 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>
@@ -71,69 +77,82 @@ namespace Coffee.UIParticleInternal
/// </summary>
public void Get(Hash128 hash, ref T obj, Func<T> onCreate)
{
if (GetFromCache(hash, ref obj)) return;
Add(hash, ref obj, 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)
{
if (GetFromCache(hash, ref obj)) return;
Add(hash, ref obj, onCreate(source));
}
private bool GetFromCache(Hash128 hash, ref T obj)
{
// Find existing entry.
Profiler.BeginSample("(COF)[ObjectRepository] GetFromCache");
if (_cache.TryGetValue(hash, out var entry))
Profiler.BeginSample("(COF)[ObjectRepository] Get > Find existing entry");
for (var i = 0; i < _cache.Count; ++i)
{
if (!entry.storedObject)
{
Release(ref entry.storedObject);
Profiler.EndSample();
return false;
}
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(total#{count}): {entry}");
Logging.Log(_name, $"Get(#{count}): {entry}");
}
Profiler.EndSample();
return true;
}
Profiler.EndSample();
return false;
}
private void Add(Hash128 hash, ref T obj, T newObject)
{
if (!newObject)
{
Release(ref obj);
obj = newObject;
return;
}
// Create and add a new entry.
Profiler.BeginSample("(COF)[ObjectRepository] Add");
Profiler.EndSample();
// Create new entry.
Profiler.BeginSample("(COF)[ObjectRepository] Get > Create new entry");
var newEntry = 0 < _pool.Count ? _pool.Pop() : new Entry();
newEntry.storedObject = newObject;
newEntry.storedObject = onCreate(source);
newEntry.hash = hash;
newEntry.reference = 1;
_cache[hash] = newEntry;
_objectKey[newObject.GetInstanceID()] = hash;
Logging.Log(_name, $"<color=#03c700>Add</color>(total#{count}): {newEntry}");
_cache.Add(newEntry);
Logging.Log(_name, $"Get(#{count}): {newEntry}");
Release(ref obj);
obj = newObject;
obj = newEntry.storedObject;
Profiler.EndSample();
}
@@ -144,45 +163,35 @@ namespace Coffee.UIParticleInternal
{
if (ReferenceEquals(obj, null)) return;
// Find and release the entry.
Profiler.BeginSample("(COF)[ObjectRepository] Release");
var id = obj.GetInstanceID();
if (_objectKey.TryGetValue(id, out var hash)
&& _cache.TryGetValue(hash, out var entry))
for (var i = 0; i < _cache.Count; i++)
{
entry.reference--;
if (entry.reference <= 0 || !entry.storedObject)
var entry = _cache[i];
if (entry.storedObject != obj)
{
Remove(entry);
continue;
}
else
if (--entry.reference <= 0)
{
Logging.Log(_name, $"Release(total#{_cache.Count}): {entry}");
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;
}
}
else
{
Logging.Log(_name, $"Release(total#{_cache.Count}): <color=red>Already released: {obj}</color>");
Logging.Log(_name, $"Release(#{count}): {entry}");
break;
}
obj = null;
Profiler.EndSample();
}
private void Remove(Entry entry)
{
if (ReferenceEquals(entry, null)) return;
Profiler.BeginSample("(COF)[ObjectRepository] Remove");
_cache.Remove(entry.hash);
_objectKey.Remove(entry.storedObject.GetInstanceID());
_pool.Push(entry);
entry.reference = 0;
Logging.Log(_name, $"<color=#f29e03>Remove</color>(total#{_cache.Count}): {entry}");
entry.Release(_onRelease);
Profiler.EndSample();
}
private class Entry
{
public Hash128 hash;
@@ -202,7 +211,7 @@ namespace Coffee.UIParticleInternal
public override string ToString()
{
return $"h{(uint)hash.GetHashCode()} (refs#{reference}), {storedObject}";
return $"h{(uint)hash.GetHashCode()} (#{reference}), {storedObject}";
}
}
}

View File

@@ -14,8 +14,6 @@ namespace Coffee.UIParticleInternal
private static readonly FastAction s_AfterCanvasRebuildAction = new FastAction();
private static readonly FastAction s_LateAfterCanvasRebuildAction = new FastAction();
private static readonly FastAction s_BeforeCanvasRebuildAction = new FastAction();
private static readonly FastAction s_OnScreenSizeChangedAction = new FastAction();
private static Vector2Int s_LastScreenSize;
static UIExtraCallbacks()
{
@@ -50,15 +48,6 @@ namespace Coffee.UIParticleInternal
remove => s_AfterCanvasRebuildAction.Remove(value);
}
/// <summary>
/// Event that occurs when the screen size changes.
/// </summary>
public static event Action onScreenSizeChanged
{
add => s_OnScreenSizeChangedAction.Add(value);
remove => s_OnScreenSizeChangedAction.Remove(value);
}
/// <summary>
/// Initializes the UIExtraCallbacks to ensure proper event handling.
/// </summary>
@@ -75,12 +64,11 @@ namespace Coffee.UIParticleInternal
#if UNITY_EDITOR
[InitializeOnLoadMethod]
#endif
#else
[RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.BeforeSceneLoad)]
#endif
private static void InitializeOnLoad()
{
Canvas.willRenderCanvases -= OnAfterCanvasRebuild;
s_IsInitializedAfterCanvasRebuild = false;
}
/// <summary>
@@ -88,17 +76,6 @@ namespace Coffee.UIParticleInternal
/// </summary>
private static void OnBeforeCanvasRebuild()
{
var screenSize = new Vector2Int(Screen.width, Screen.height);
if (s_LastScreenSize != screenSize)
{
if (s_LastScreenSize != default)
{
s_OnScreenSizeChangedAction.Invoke();
}
s_LastScreenSize = screenSize;
}
s_BeforeCanvasRebuildAction.Invoke();
InitializeAfterCanvasRebuild();
}

View File

@@ -6,22 +6,20 @@ using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.Rendering;
using UnityEngine.Serialization;
using UnityEngine.UI;
using Random = UnityEngine.Random;
[assembly: InternalsVisibleTo("Coffee.UIParticle.Editor")]
[assembly: InternalsVisibleTo("Coffee.UIParticle.PerformanceDemo")]
[assembly: InternalsVisibleTo("Coffee.UIParticle.Demo")]
namespace Coffee.UIExtensions
{
/// <summary>
/// Render maskable and sortable particle effect ,without Camera, RenderTexture or Canvas.
/// </summary>
[Icon("Packages/com.coffee.ui-particle/Icons/UIParticleIcon.png")]
[ExecuteAlways]
[RequireComponent(typeof(RectTransform))]
[RequireComponent(typeof(CanvasRenderer))]
public class UIParticle : UIBehaviour, ISerializationCallbackReceiver
public class UIParticle : MaskableGraphic, ISerializationCallbackReceiver
{
public enum AutoScalingMode
{
@@ -47,26 +45,23 @@ namespace Coffee.UIExtensions
[HideInInspector]
[SerializeField]
[Obsolete]
internal bool m_IsTrail;
[HideInInspector]
[FormerlySerializedAs("m_IgnoreParent")]
[SerializeField]
[Obsolete]
private bool m_IgnoreCanvasScaler;
[HideInInspector]
[SerializeField]
[Obsolete]
internal bool m_AbsoluteMode;
private 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]
private Vector3 m_Scale3D = new Vector3(1, 1, 1);
private Vector3 m_Scale3D = new Vector3(10, 10, 10);
[Tooltip("If you want to update material properties (e.g. _MainTex_ST, _Color) in AnimationClip, " +
"use this to mark as animatable.")]
[Tooltip("Animatable material properties.\n" +
"If you want to change the material properties of the ParticleSystem in Animation, enable it.")]
[SerializeField]
internal AnimatableProperty[] m_AnimatableProperties = new AnimatableProperty[0];
@@ -74,13 +69,12 @@ namespace Coffee.UIExtensions
[SerializeField]
private List<ParticleSystem> m_Particles = new List<ParticleSystem>();
[Tooltip("Particle simulation results are shared within the same group. " +
"A large number of the same effects can be displayed with a small load.\n" +
"None: Disable mesh sharing.\n" +
"Auto: Automatically select Primary/Replica.\n" +
"Primary: Provides particle simulation results to the same group.\n" +
[Tooltip("Mesh sharing.\n" +
"None: disable mesh sharing.\n" +
"Auto: automatically select Primary/Replica.\n" +
"Primary: provides particle simulation results to the same group.\n" +
"Primary Simulator: Primary, but do not render the particle (simulation only).\n" +
"Replica: Render simulation results provided by the primary.")]
"Replica: render simulation results provided by the primary.")]
[SerializeField]
private MeshSharing m_MeshSharing = MeshSharing.None;
@@ -92,85 +86,36 @@ namespace Coffee.UIExtensions
[SerializeField]
private int m_GroupMaxId;
[Tooltip("Emission position mode.\n" +
"Relative: The particles will be emitted from the scaled position.\n" +
"Absolute: The particles will be emitted from the world position.")]
[Tooltip("Relative: The particles will be emitted from the scaled position of ParticleSystem.\n" +
"Absolute: The particles will be emitted from the world position of ParticleSystem.")]
[SerializeField]
private PositionMode m_PositionMode = PositionMode.Relative;
[SerializeField]
[Obsolete]
internal bool m_AutoScaling;
[Tooltip("Prevent the root-Canvas scale from affecting the hierarchy-scaled ParticleSystem.")]
private bool m_AutoScaling = true;
[SerializeField]
[Tooltip(
"How to automatically adjust when the Canvas scale is changed by the screen size or reference resolution.\n" +
"None: Do nothing.\n" +
"Transform: Transform.lossyScale (=world scale) will be set to (1, 1, 1).\n" +
"UIParticle: UIParticle.scale will be adjusted.")]
[Tooltip("Transform: Transform.lossyScale (=world scale) will be set to (1, 1, 1)." +
"UIParticle: UIParticle.scale will be adjusted.")]
private AutoScalingMode m_AutoScalingMode = AutoScalingMode.Transform;
[SerializeField]
[Tooltip("Use a custom view.\n" +
"Use this if the particles are not displayed correctly due to min/max particle size.")]
private bool m_UseCustomView;
[SerializeField]
[Tooltip("Custom view size.\n" +
"Change the bake view size.")]
private float m_CustomViewSize = 10;
[SerializeField]
[Tooltip("Time scale multiplier.")]
private float m_TimeScaleMultiplier = 1;
[SerializeField]
private bool m_Maskable = true;
private readonly List<UIParticleRenderer> _renderers = new List<UIParticleRenderer>();
private Camera _bakeCamera;
private Canvas _canvas;
private int _groupId;
private bool _isScaleStored;
private Vector3 _storedScale;
private Camera _orthoCamera;
private DrivenRectTransformTracker _tracker;
public RectTransform rectTransform => transform as RectTransform;
public Canvas canvas
{
get
{
if (_canvas) return _canvas;
var tr = transform;
while (tr && !_canvas)
{
if (tr.TryGetComponent(out _canvas)) return _canvas;
tr = tr.parent;
}
return null;
}
}
/// <summary>
/// Does this graphic allow masking.
/// Should this graphic be considered a target for ray-casting?
/// </summary>
public bool maskable
public override bool raycastTarget
{
get => m_Maskable;
set
{
if (value == m_Maskable) return;
m_Maskable = value;
UpdateRendererMaterial();
}
get => false;
set { }
}
/// <summary>
/// Particle simulation results are shared within the same group.
/// A large number of the same effects can be displayed with a small load.
/// Mesh sharing.
/// None: disable mesh sharing.
/// Auto: automatically select Primary/Replica.
/// Primary: provides particle simulation results to the same group.
@@ -213,9 +158,9 @@ namespace Coffee.UIExtensions
}
/// <summary>
/// Emission position mode.
/// Relative: The particles will be emitted from the scaled position.
/// Absolute: The particles will be emitted from the world position.
/// Particle position mode.
/// Relative: The particles will be emitted from the scaled position of the ParticleSystem.
/// Absolute: The particles will be emitted from the world position of the ParticleSystem.
/// </summary>
public PositionMode positionMode
{
@@ -228,7 +173,6 @@ namespace Coffee.UIExtensions
/// Relative: The particles will be emitted from the scaled position of the ParticleSystem.
/// Absolute: The particles will be emitted from the world position of the ParticleSystem.
/// </summary>
[Obsolete("The absoluteMode is now obsolete. Please use the autoScalingMode instead.", false)]
public bool absoluteMode
{
get => m_PositionMode == PositionMode.Absolute;
@@ -246,12 +190,8 @@ namespace Coffee.UIExtensions
}
/// <summary>
/// How to automatically adjust when the Canvas scale is changed by the screen size or reference resolution.
/// <para/>
/// None: Do nothing.
/// <para/>
/// Auto scaling mode.
/// Transform: Transform.lossyScale (=world scale) will be set to (1, 1, 1).
/// <para/>
/// UIParticle: UIParticle.scale will be adjusted.
/// </summary>
public AutoScalingMode autoScalingMode
@@ -261,44 +201,10 @@ namespace Coffee.UIExtensions
{
if (m_AutoScalingMode == value) return;
m_AutoScalingMode = value;
if (autoScalingMode != AutoScalingMode.Transform && _isScaleStored)
{
transform.localScale = _storedScale;
_isScaleStored = false;
}
UpdateTracker();
}
}
/// <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);
}
/// <summary>
/// Time scale multiplier.
/// </summary>
public float timeScaleMultiplier
{
get => m_TimeScaleMultiplier;
set => m_TimeScaleMultiplier = value;
}
internal bool useMeshSharing => m_MeshSharing != MeshSharing.None;
internal bool isPrimary =>
@@ -338,12 +244,30 @@ namespace Coffee.UIExtensions
/// <summary>
/// Particle effect scale.
/// </summary>
public Vector3 scale3DForCalc => autoScalingMode == AutoScalingMode.Transform
? m_Scale3D
: m_Scale3D.GetScaled(canvasScale, transform.localScale);
public Vector3 scale3DForCalc => autoScalingMode == AutoScalingMode.UIParticle
? m_Scale3D.GetScaled(canvasScale)
: m_Scale3D;
public List<ParticleSystem> particles => m_Particles;
/// <summary>
/// Get all base materials to render.
/// </summary>
public IEnumerable<Material> materials
{
get
{
for (var i = 0; i < _renderers.Count; i++)
{
var r = _renderers[i];
if (!r || !r.material) continue;
yield return r.material;
}
}
}
public override Material materialForRendering => null;
/// <summary>
/// Paused.
/// </summary>
@@ -351,15 +275,15 @@ namespace Coffee.UIExtensions
public Vector3 parentScale { get; private set; }
private Vector3 canvasScale { get; set; }
public Vector3 canvasScale { get; private set; }
protected override void OnEnable()
{
_isScaleStored = false;
ResetGroupId();
UpdateTracker();
UIParticleUpdater.Register(this);
RegisterDirtyMaterialCallback(UpdateRendererMaterial);
//
if (0 < particles.Count)
{
RefreshParticles(particles);
@@ -369,7 +293,7 @@ namespace Coffee.UIExtensions
RefreshParticles();
}
UpdateRendererMaterial();
base.OnEnable();
}
/// <summary>
@@ -377,24 +301,12 @@ namespace Coffee.UIExtensions
/// </summary>
protected override void OnDisable()
{
_tracker.Clear();
if (autoScalingMode == AutoScalingMode.Transform && _isScaleStored)
{
transform.localScale = _storedScale;
}
_isScaleStored = false;
UpdateTracker();
UIParticleUpdater.Unregister(this);
_renderers.ForEach(r => r.Reset());
_canvas = null;
}
UnregisterDirtyMaterialCallback(UpdateRendererMaterial);
/// <summary>
/// Called when the state of the parent Canvas is changed.
/// </summary>
protected override void OnCanvasHierarchyChanged()
{
_canvas = null;
base.OnDisable();
}
/// <summary>
@@ -404,13 +316,13 @@ namespace Coffee.UIExtensions
{
}
/// <summary>
/// This function is called when a direct or indirect parent of the transform of the GameObject has changed.
/// </summary>
protected override void OnTransformParentChanged()
#if UNITY_EDITOR
protected override void OnValidate()
{
_canvas = null;
base.OnValidate();
UpdateTracker();
}
#endif
void ISerializationCallbackReceiver.OnBeforeSerialize()
{
@@ -418,7 +330,6 @@ namespace Coffee.UIExtensions
void ISerializationCallbackReceiver.OnAfterDeserialize()
{
#pragma warning disable CS0612 // Type or member is obsolete
if (m_IgnoreCanvasScaler || m_AutoScaling)
{
m_IgnoreCanvasScaler = false;
@@ -431,47 +342,31 @@ namespace Coffee.UIExtensions
m_AbsoluteMode = false;
m_PositionMode = PositionMode.Absolute;
}
#pragma warning restore CS0612 // Type or member is obsolete
}
/// <summary>
/// Play the ParticleSystems.
/// </summary>
public void Play()
{
particles.Exec(p => p.Simulate(0, false, true));
isPaused = false;
}
/// <summary>
/// Pause the ParticleSystems.
/// </summary>
public void Pause()
{
particles.Exec(p => p.Pause());
isPaused = true;
}
/// <summary>
/// Unpause the ParticleSystems.
/// </summary>
public void Resume()
{
isPaused = false;
}
/// <summary>
/// Stop the ParticleSystems.
/// </summary>
public void Stop()
{
particles.Exec(p => p.Stop());
isPaused = true;
}
/// <summary>
/// Start emission of the ParticleSystems.
/// </summary>
public void StartEmission()
{
particles.Exec(p =>
@@ -481,9 +376,6 @@ namespace Coffee.UIExtensions
});
}
/// <summary>
/// Stop emission of the ParticleSystems.
/// </summary>
public void StopEmission()
{
particles.Exec(p =>
@@ -493,52 +385,24 @@ namespace Coffee.UIExtensions
});
}
/// <summary>
/// Clear the particles of the ParticleSystems.
/// </summary>
public void Clear()
{
particles.Exec(p => p.Clear());
isPaused = true;
}
/// <summary>
/// Get all base materials to render.
/// </summary>
public void GetMaterials(List<Material> result)
{
if (result == null) return;
for (var i = 0; i < _renderers.Count; i++)
{
var r = _renderers[i];
if (!r || !r.material) continue;
result.Add(r.material);
}
}
/// <summary>
/// Refresh UIParticle using the ParticleSystem instance.
/// </summary>
public void SetParticleSystemInstance(GameObject instance)
{
SetParticleSystemInstance(instance, true);
}
/// <summary>
/// Refresh UIParticle using the ParticleSystem instance.
/// </summary>
public void SetParticleSystemInstance(GameObject instance, bool destroyOldParticles)
{
if (!instance) return;
var childCount = transform.childCount;
for (var i = 0; i < childCount; i++)
foreach (Transform child in transform)
{
var go = transform.GetChild(i).gameObject;
if (go.TryGetComponent<Camera>(out var cam) && cam == _bakeCamera) continue;
if (go.TryGetComponent<UIParticleRenderer>(out var _)) continue;
var go = child.gameObject;
go.SetActive(false);
if (destroyOldParticles)
{
@@ -553,10 +417,6 @@ namespace Coffee.UIExtensions
RefreshParticles(instance);
}
/// <summary>
/// Refresh UIParticle using the prefab.
/// The prefab is automatically instantiated.
/// </summary>
public void SetParticleSystemPrefab(GameObject prefab)
{
if (!prefab) return;
@@ -564,31 +424,16 @@ namespace Coffee.UIExtensions
SetParticleSystemInstance(Instantiate(prefab.gameObject), true);
}
/// <summary>
/// Refresh UIParticle.
/// Collect ParticleSystems under the GameObject and refresh the UIParticle.
/// </summary>
public void RefreshParticles()
{
RefreshParticles(gameObject);
}
/// <summary>
/// Refresh UIParticle.
/// Collect ParticleSystems under the GameObject and refresh the UIParticle.
/// </summary>
private void RefreshParticles(GameObject root)
{
if (!root) return;
root.GetComponentsInChildren(true, particles);
for (var i = particles.Count - 1; 0 <= i; i--)
{
var ps = particles[i];
if (!ps || ps.GetComponentInParent<UIParticle>(true) != this)
{
particles.RemoveAt(i);
}
}
particles.RemoveAll(x => x.GetComponentInParent<UIParticle>(true) != this);
for (var i = 0; i < particles.Count; i++)
{
@@ -603,74 +448,46 @@ namespace Coffee.UIExtensions
RefreshParticles(particles);
}
/// <summary>
/// Refresh UIParticle using a list of ParticleSystems.
/// </summary>
public void RefreshParticles(List<ParticleSystem> particleSystems)
public void RefreshParticles(List<ParticleSystem> particles)
{
// Collect children UIParticleRenderer components.
// #246: Nullptr exceptions when using nested UIParticle components in hierarchy
_renderers.Clear();
var childCount = transform.childCount;
for (var i = 0; i < childCount; i++)
foreach (Transform child in transform)
{
var child = transform.GetChild(i);
if (child.TryGetComponent(out UIParticleRenderer uiParticleRenderer))
var uiParticleRenderer = child.GetComponent<UIParticleRenderer>();
if (uiParticleRenderer != null)
{
_renderers.Add(uiParticleRenderer);
}
}
// Reset the UIParticleRenderer components.
for (var i = 0; i < _renderers.Count; i++)
{
_renderers[i].Reset(i);
}
// Set the ParticleSystem to the UIParticleRenderer. If the trail is enabled, set it additionally.
var j = 0;
for (var i = 0; i < particleSystems.Count; i++)
for (var i = 0; i < particles.Count; i++)
{
var ps = particleSystems[i];
var ps = particles[i];
if (!ps) continue;
var mainEmitter = ps.GetMainEmitter(particleSystems);
GetRenderer(j++).Set(this, ps, false, mainEmitter);
// If the trail is enabled, set it additionally.
GetRenderer(j++).Set(this, ps, false);
if (ps.trails.enabled)
{
GetRenderer(j++).Set(this, ps, true, mainEmitter);
GetRenderer(j++).Set(this, ps, true);
}
}
}
internal void UpdateTransformScale()
{
_tracker.Clear();
canvasScale = canvas.rootCanvas.transform.localScale.Inverse();
parentScale = transform.parent.lossyScale;
if (autoScalingMode != AutoScalingMode.Transform)
{
if (_isScaleStored)
{
transform.localScale = _storedScale;
}
if (autoScalingMode != AutoScalingMode.Transform) return;
_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();
if (currentScale != newScale)
if (transform.localScale != newScale)
{
transform.localScale = newScale;
}
@@ -683,10 +500,11 @@ namespace Coffee.UIExtensions
for (var i = 0; i < _renderers.Count; i++)
{
var r = _renderers[i];
if (r) continue;
RefreshParticles(particles);
break;
if (!r)
{
RefreshParticles(particles);
break;
}
}
var bakeCamera = GetBakeCamera();
@@ -694,7 +512,6 @@ namespace Coffee.UIExtensions
{
var r = _renderers[i];
if (!r) continue;
r.UpdateMesh(bakeCamera);
}
}
@@ -706,6 +523,17 @@ namespace Coffee.UIExtensions
: Random.Range(m_GroupId, m_GroupMaxId + 1);
}
protected override void UpdateMaterial()
{
}
/// <summary>
/// Call to update the geometry of the Graphic onto the CanvasRenderer.
/// </summary>
protected override void UpdateGeometry()
{
}
private void UpdateRendererMaterial()
{
for (var i = 0; i < _renderers.Count; i++)
@@ -735,55 +563,64 @@ namespace Coffee.UIExtensions
private Camera GetBakeCamera()
{
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;
return _bakeCamera;
}
// 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")
// Find existing ortho-camera.
foreach (Transform child in transform)
{
_bakeCamera = cam;
break;
var cam = child.GetComponent<Camera>();
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");
go.SetActive(false);
go.transform.SetParent(transform, false);
_bakeCamera = go.AddComponent<Camera>();
_tracker.Clear();
}
else
{
_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 = UIParticleProjectSettings.globalHideFlags;
return _bakeCamera;
}
}
}

Some files were not shown because too many files have changed in this diff Show More