2025-07-08 10:46:31 +00:00
using System.Collections ;
using System.Collections.Generic ;
using System.IO ;
using UnityEngine ;
using UnityEngine.UI ;
#if UNITY_EDITOR
using UnityEditor ;
using UnityEditor.SceneManagement ;
#endif
namespace AllIn1VfxToolkit
{
[ExecuteInEditMode]
[DisallowMultipleComponent]
[AddComponentMenu("AllIn1VfxToolkit/AddAllIn1Vfx")]
public class AllIn1VfxComponent : MonoBehaviour
{
private Material currMaterial , prevMaterial ;
private bool matAssigned = false , destroyed = false ;
private enum AfterSetAction
{
Clear ,
CopyMaterial ,
Reset
} ;
#if UNITY_EDITOR
private static float timeLastReload = - 1f ;
private void Start ( )
{
if ( timeLastReload < 0 ) timeLastReload = Time . time ;
}
private void Update ( )
{
if ( matAssigned | | Application . isPlaying | | ! gameObject . activeSelf ) return ;
Renderer sr = GetComponent < Renderer > ( ) ;
if ( sr ! = null )
{
if ( sr . sharedMaterial = = null )
{
CleanMaterial ( ) ;
MakeNewMaterial ( notifyWhenDone : true ) ;
}
if ( ! sr . sharedMaterial . shader . name . Contains ( "Vfx" ) ) MakeNewMaterial ( notifyWhenDone : true ) ;
else matAssigned = true ;
}
else
{
Graphic img = GetComponent < Graphic > ( ) ;
if ( img ! = null )
{
if ( ! img . material . shader . name . Contains ( "Vfx" ) ) MakeNewMaterial ( notifyWhenDone : true ) ;
else matAssigned = true ;
}
}
}
#endif
private void MakeNewMaterial ( string shaderName = "AllIn1Vfx" , bool notifyWhenDone = false )
{
bool operationSuccessful = SetMaterial ( AfterSetAction . Clear , shaderName ) ;
#if UNITY_EDITOR
if ( notifyWhenDone & & operationSuccessful ) AllIn1VfxWindow . ShowSceneViewNotification ( "AllIn1Vfx: Material Created and Assigned" ) ;
#endif
}
public bool MakeCopy ( )
{
if ( currMaterial = = null )
{
if ( FetchCurrentMaterial ( ) ) return false ;
}
string shaderName = currMaterial . shader . name ;
if ( shaderName . Contains ( "AllIn1Vfx/" ) ) shaderName = shaderName . Replace ( "AllIn1Vfx/" , "" ) ;
return SetMaterial ( AfterSetAction . CopyMaterial , shaderName ) ;
}
private bool FetchCurrentMaterial ( )
{
bool rendererExists = false ;
Renderer sr = GetComponent < Renderer > ( ) ;
if ( sr ! = null )
{
rendererExists = true ;
currMaterial = sr . sharedMaterial ;
}
else
{
Graphic img = GetComponent < Graphic > ( ) ;
if ( img ! = null )
{
rendererExists = true ;
currMaterial = img . material ;
}
}
if ( ! rendererExists )
{
MissingRenderer ( ) ;
return true ;
}
return false ;
}
private void ResetAllProperties ( string shaderName )
{
SetMaterial ( AfterSetAction . Reset , shaderName ) ;
}
private bool SetMaterial ( AfterSetAction action , string shaderName )
{
#if UNITY_EDITOR
Shader allIn1VfxShader = AllIn1VfxWindow . FindShader ( shaderName ) ;
if ( ! Application . isPlaying & & Application . isEditor & & allIn1VfxShader ! = null )
{
bool rendererExists = false ;
Renderer sr = GetComponent < Renderer > ( ) ;
if ( sr ! = null )
{
rendererExists = true ;
Renderer currentRenderer = GetComponent < Renderer > ( ) ;
if ( currentRenderer . sharedMaterial = = null )
{
AllIn1VfxWindow . SceneViewNotificationAndLog ( "Error: No Material Found" ) ;
return false ;
}
prevMaterial = new Material ( currentRenderer . sharedMaterial ) ;
currMaterial = new Material ( allIn1VfxShader ) ;
currentRenderer . sharedMaterial = currMaterial ;
currentRenderer . sharedMaterial . hideFlags = HideFlags . None ;
matAssigned = true ;
DoAfterSetAction ( action ) ;
}
else
{
Graphic img = GetComponent < Graphic > ( ) ;
if ( img ! = null )
{
rendererExists = true ;
prevMaterial = new Material ( img . material ) ;
currMaterial = new Material ( allIn1VfxShader ) ;
img . material = currMaterial ;
img . material . hideFlags = HideFlags . None ;
matAssigned = true ;
DoAfterSetAction ( action ) ;
}
}
if ( ! rendererExists ) MissingRenderer ( ) ;
else SetSceneDirty ( ) ;
return rendererExists ;
}
else if ( allIn1VfxShader = = null )
{
string logErrorMessage = "You are missing shader variants. Maybe reinstall the asset? You looked for " + shaderName ;
Debug . LogError ( logErrorMessage ) ;
AllIn1VfxWindow . ShowSceneViewNotification ( logErrorMessage ) ;
return false ;
}
#endif
return false ;
}
private void DoAfterSetAction ( AfterSetAction action )
{
switch ( action )
{
case AfterSetAction . Clear :
ClearAllKeywords ( ) ;
break ;
case AfterSetAction . CopyMaterial :
currMaterial . CopyPropertiesFromMaterial ( prevMaterial ) ;
break ;
}
}
public bool TryCreateNew ( )
{
bool rendererExists = false ;
Renderer sr = GetComponent < Renderer > ( ) ;
if ( sr ! = null )
{
rendererExists = true ;
if ( sr ! = null & & sr . sharedMaterial ! = null & & sr . sharedMaterial . shader . name . Contains ( "Vfx" ) )
{
ResetAllProperties ( "AllIn1Vfx" ) ;
ClearAllKeywords ( ) ;
}
else
{
CleanMaterial ( ) ;
MakeNewMaterial ( "AllIn1Vfx" ) ;
}
}
else
{
Graphic img = GetComponent < Graphic > ( ) ;
if ( img ! = null )
{
rendererExists = true ;
if ( img . material . shader . name . Contains ( "Vfx" ) )
{
ResetAllProperties ( "AllIn1Vfx" ) ;
ClearAllKeywords ( ) ;
}
else MakeNewMaterial ( "AllIn1Vfx" ) ;
}
}
if ( ! rendererExists )
{
MissingRenderer ( ) ;
}
SetSceneDirty ( ) ;
return rendererExists ;
}
public void ClearAllKeywords ( )
{
SetKeyword ( "FOG_ON" ) ;
SetKeyword ( "SCREENDISTORTION_ON" ) ;
SetKeyword ( "DISTORTUSECOL_ON" ) ;
SetKeyword ( "DISTORTONLYBACK_ON" ) ;
SetKeyword ( "SHAPE1SCREENUV_ON" ) ;
SetKeyword ( "SHAPE2SCREENUV_ON" ) ;
SetKeyword ( "SHAPE3SCREENUV_ON" ) ;
SetKeyword ( "SHAPEDEBUG_ON" ) ;
SetKeyword ( "SHAPE1CONTRAST_ON" ) ;
SetKeyword ( "SHAPE1DISTORT_ON" ) ;
SetKeyword ( "SHAPE1ROTATE_ON" ) ;
SetKeyword ( "SHAPE1SHAPECOLOR_ON" ) ;
SetKeyword ( "SHAPE2_ON" ) ;
SetKeyword ( "SHAPE2CONTRAST_ON" ) ;
SetKeyword ( "SHAPE2DISTORT_ON" ) ;
SetKeyword ( "SHAPE2ROTATE_ON" ) ;
SetKeyword ( "SHAPE2SHAPECOLOR_" ) ;
SetKeyword ( "SHAPE3_ON" ) ;
SetKeyword ( "SHAPE3CONTRAST_ON" ) ;
SetKeyword ( "SHAPE3DISTORT_ON" ) ;
SetKeyword ( "SHAPE3ROTATE_ON" ) ;
SetKeyword ( "SHAPE3SHAPECOLOR_" ) ;
SetKeyword ( "GLOW_ON" ) ;
SetKeyword ( "GLOWTEX_ON" ) ;
SetKeyword ( "SOFTPART_ON" ) ;
SetKeyword ( "DEPTHGLOW_ON" ) ;
SetKeyword ( "MASK_ON" ) ;
SetKeyword ( "COLORRAMP_ON" ) ;
SetKeyword ( "COLORRAMPGRAD_ON" ) ;
SetKeyword ( "COLORGRADING_ON" ) ;
SetKeyword ( "HSV_ON" ) ;
SetKeyword ( "BLUR_ON" ) ;
SetKeyword ( "BLURISHD_ON" ) ;
SetKeyword ( "POSTERIZE_ON" ) ;
SetKeyword ( "FADE_ON" ) ;
SetKeyword ( "FADEBURN_ON" ) ;
SetKeyword ( "PIXELATE_ON" ) ;
SetKeyword ( "DISTORT_ON" ) ;
SetKeyword ( "SHAKEUV_ON" ) ;
SetKeyword ( "WAVEUV_ON" ) ;
SetKeyword ( "ROUNDWAVEUV_ON" ) ;
SetKeyword ( "TWISTUV_ON" ) ;
SetKeyword ( "DOODLE_ON" ) ;
SetKeyword ( "OFFSETSTREAM_ON" ) ;
SetKeyword ( "TEXTURESCROLL_ON" ) ;
SetKeyword ( "VERTOFFSET_ON" ) ;
SetKeyword ( "RIM_ON" ) ;
SetKeyword ( "BACKFACETINT_ON" ) ;
SetKeyword ( "POLARUV_ON" ) ;
SetKeyword ( "POLARUVDISTORT_ON" ) ;
SetKeyword ( "SHAPE1MASK_ON" ) ;
SetKeyword ( "TRAILWIDTH_ON" ) ;
SetKeyword ( "LIGHTANDSHADOW_ON" ) ;
SetKeyword ( "SHAPETEXOFFSET_ON" ) ;
SetKeyword ( "SHAPEWEIGHTS_ON" ) ;
SetKeyword ( "ALPHACUTOFF_ON" ) ;
SetKeyword ( "ALPHASMOOTHSTEP_ON" ) ;
SetKeyword ( "ALPHAFADE_ON" ) ;
SetKeyword ( "ALPHAFADEUSESHAPE1_" ) ;
SetKeyword ( "ALPHAFADEUSEREDCHAN" ) ;
SetKeyword ( "ALPHAFADETRANSPAREN" ) ;
SetKeyword ( "ALPHAFADEINPUTSTREA" ) ;
SetKeyword ( "CAMDISTFADE_ON" ) ;
SetSceneDirty ( ) ;
}
private void SetKeyword ( string keyword , bool state = false )
{
if ( destroyed ) return ;
if ( currMaterial = = null )
{
FindCurrMaterial ( ) ;
if ( currMaterial = = null )
{
MissingRenderer ( ) ;
return ;
}
}
if ( ! state ) currMaterial . DisableKeyword ( keyword ) ;
else currMaterial . EnableKeyword ( keyword ) ;
}
private void FindCurrMaterial ( )
{
Renderer sr = GetComponent < Renderer > ( ) ;
if ( sr ! = null )
{
currMaterial = GetComponent < Renderer > ( ) . sharedMaterial ;
matAssigned = true ;
}
else
{
Graphic img = GetComponent < Graphic > ( ) ;
if ( img ! = null )
{
currMaterial = img . material ;
matAssigned = true ;
}
}
}
public void CleanMaterial ( )
{
Renderer sr = GetComponent < Renderer > ( ) ;
if ( sr ! = null )
{
sr . sharedMaterial = new Material ( Shader . Find ( "Sprites/Default" ) ) ;
matAssigned = false ;
}
else
{
Graphic img = GetComponent < Graphic > ( ) ;
if ( img ! = null )
{
img . material = new Material ( Shader . Find ( "Sprites/Default" ) ) ;
matAssigned = false ;
}
}
SetSceneDirty ( ) ;
}
public bool SaveMaterial ( )
{
#if UNITY_EDITOR
string path = AllIn1VfxWindow . GetMaterialSavePath ( ) ;
path + = "/" ;
if ( ! System . IO . Directory . Exists ( path ) )
{
EditorUtility . DisplayDialog ( "The desired save folder doesn't exist" ,
"Go to Window -> AllIn1VfxWindow and set a valid folder" , "Ok" ) ;
return false ;
}
path + = gameObject . name ;
string fullPath = path + ".mat" ;
if ( System . IO . File . Exists ( fullPath ) )
{
SaveMaterialWithOtherName ( path ) ;
}
else DoSaving ( fullPath ) ;
SetSceneDirty ( ) ;
return true ;
#else
return false ;
#endif
}
private void SaveMaterialWithOtherName ( string path , int i = 1 )
{
int number = i ;
string newPath = path + "_" + number . ToString ( ) ;
string fullPath = newPath + ".mat" ;
if ( System . IO . File . Exists ( fullPath ) )
{
number + + ;
SaveMaterialWithOtherName ( path , number ) ;
}
else
{
DoSaving ( fullPath ) ;
}
}
private void DoSaving ( string fileName )
{
#if UNITY_EDITOR
bool rendererExists = false ;
Renderer sr = GetComponent < Renderer > ( ) ;
Material matToSave = null ;
Material createdMat = null ;
if ( sr ! = null )
{
rendererExists = true ;
matToSave = sr . sharedMaterial ;
}
else
{
Graphic img = GetComponent < Graphic > ( ) ;
if ( img ! = null )
{
rendererExists = true ;
matToSave = img . material ;
}
}
if ( ! rendererExists )
{
MissingRenderer ( ) ;
return ;
}
else
{
createdMat = new Material ( matToSave ) ;
currMaterial = createdMat ;
AssetDatabase . CreateAsset ( createdMat , fileName ) ;
AllIn1VfxWindow . SceneViewNotificationAndLog ( fileName + " has been saved!" ) ;
EditorGUIUtility . PingObject ( AssetDatabase . LoadAssetAtPath ( fileName , typeof ( Material ) ) ) ;
}
if ( sr ! = null )
{
sr . material = createdMat ;
}
else
{
Graphic img = GetComponent < Graphic > ( ) ;
img . material = createdMat ;
}
#endif
}
public void SetSceneDirty ( )
{
#if UNITY_EDITOR
if ( ! Application . isPlaying ) EditorSceneManager . MarkAllScenesDirty ( ) ;
//If you get an error here please delete the code block below
#if UNITY_2021_2_OR_NEWER
var prefabStage = UnityEditor . SceneManagement . PrefabStageUtility . GetCurrentPrefabStage ( ) ;
#else
var prefabStage = UnityEditor . Experimental . SceneManagement . PrefabStageUtility . GetCurrentPrefabStage ( ) ;
#endif
if ( prefabStage ! = null ) EditorSceneManager . MarkSceneDirty ( prefabStage . scene ) ;
//Until here
#endif
}
private void MissingRenderer ( )
{
#if UNITY_EDITOR
EditorUtility . DisplayDialog ( "Missing Renderer" , "This GameObject (" +
gameObject . name +
") has no Renderer or UI Graphic component. This AllIn1Vfx component will be removed." ,
"Ok" ) ;
destroyed = true ;
DestroyImmediate ( this ) ;
#endif
}
#if UNITY_EDITOR
public bool ApplyMaterialToHierarchy ( )
{
Renderer sr = GetComponent < Renderer > ( ) ;
Graphic img = GetComponent < Graphic > ( ) ;
Material matToApply = null ;
if ( sr ! = null ) matToApply = sr . sharedMaterial ;
else if ( img ! = null )
{
matToApply = img . material ;
}
else
{
MissingRenderer ( ) ;
return false ;
}
List < Transform > children = new List < Transform > ( ) ;
GetAllChildren ( transform , ref children ) ;
foreach ( Transform t in children )
{
sr = t . gameObject . GetComponent < Renderer > ( ) ;
if ( sr ! = null ) sr . material = matToApply ;
else
{
img = t . gameObject . GetComponent < Graphic > ( ) ;
if ( img ! = null ) img . material = matToApply ;
}
}
return true ;
}
public void CheckIfValidTarget ( )
{
Renderer sr = GetComponent < Renderer > ( ) ;
Graphic img = GetComponent < Graphic > ( ) ;
if ( sr = = null & & img = = null ) MissingRenderer ( ) ;
}
private void GetAllChildren ( Transform parent , ref List < Transform > transforms )
{
foreach ( Transform child in parent )
{
transforms . Add ( child ) ;
GetAllChildren ( child , ref transforms ) ;
}
}
public bool RenderToImage ( )
{
if ( currMaterial = = null )
{
FindCurrMaterial ( ) ;
if ( currMaterial = = null )
{
MissingRenderer ( ) ;
return false ;
}
}
Texture tex = currMaterial . GetTexture ( "_MainTex" ) ;
if ( tex ! = null ) RenderAndSaveTexture ( currMaterial , tex ) ;
else
{
SpriteRenderer sr = GetComponent < SpriteRenderer > ( ) ;
Graphic i = GetComponent < Graphic > ( ) ;
if ( sr ! = null ) tex = sr . sprite . texture ;
else if ( i ! = null ) tex = i . mainTexture ;
if ( tex ! = null ) RenderAndSaveTexture ( currMaterial , tex ) ;
else
EditorUtility . DisplayDialog ( "No valid target texture found" ,
"All In 1 VFX component couldn't find a valid Main Texture in this GameObject (" +
gameObject . name +
"). This means that the material you are using has no Main Texture or that the texture couldn't be reached through the Renderer component you are using." +
" Please make sure to have a valid Main Texture in the Material" , "Ok" ) ;
}
return tex ! = null ;
}
private void RenderAndSaveTexture ( Material targetMaterial , Texture targetTexture )
{
float scaleSlider = 1 ;
if ( PlayerPrefs . HasKey ( "All1VfxRenderImagesScale" ) )
scaleSlider = PlayerPrefs . GetFloat ( "All1VfxRenderImagesScale" ) ;
RenderTexture renderTarget = new RenderTexture ( ( int ) ( targetTexture . width * scaleSlider ) ,
( int ) ( targetTexture . height * scaleSlider ) , 0 , RenderTextureFormat . ARGB32 ) ;
Graphics . Blit ( targetTexture , renderTarget , targetMaterial ) ;
Texture2D resultTex = new Texture2D ( renderTarget . width , renderTarget . height , TextureFormat . ARGB32 , false ) ;
resultTex . ReadPixels ( new Rect ( 0 , 0 , renderTarget . width , renderTarget . height ) , 0 , 0 ) ;
resultTex . Apply ( ) ;
string path = AllIn1VfxWindow . GetRenderImageSavePath ( ) ;
path + = "/" ;
if ( ! System . IO . Directory . Exists ( path ) )
{
EditorUtility . DisplayDialog ( "The desired Material to Image Save Path doesn't exist" ,
"Go to Window -> AllIn1VfxWindow and set a valid folder" , "Ok" ) ;
return ;
}
string fullPath = path + gameObject . name + ".png" ;
if ( System . IO . File . Exists ( fullPath ) ) fullPath = GetNewValidPath ( path + gameObject . name ) ;
string pingPath = fullPath ;
string fileName = fullPath . Replace ( path , "" ) ;
fileName = fileName . Replace ( ".png" , "" ) ;
fullPath = EditorUtility . SaveFilePanel ( "Save Render Image" , path , fileName , "png" ) ;
if ( fullPath . Length = = 0 ) return ;
byte [ ] bytes = resultTex . EncodeToPNG ( ) ;
File . WriteAllBytes ( pingPath , bytes ) ;
AssetDatabase . ImportAsset ( pingPath ) ;
AssetDatabase . Refresh ( ) ;
DestroyImmediate ( resultTex ) ;
EditorGUIUtility . PingObject ( AssetDatabase . LoadAssetAtPath ( pingPath , typeof ( Texture ) ) ) ;
AllIn1VfxWindow . SceneViewNotificationAndLog ( "Render Image saved to: " + fullPath + " with scale: " + scaleSlider +
" (it can be changed in Window -> AllIn1VfxWindow)" ) ;
}
private string GetNewValidPath ( string path , int i = 1 )
{
int number = i ;
string newPath = path + "_" + number . ToString ( ) ;
string fullPath = newPath + ".png" ;
if ( System . IO . File . Exists ( fullPath ) )
{
number + + ;
fullPath = GetNewValidPath ( path , number ) ;
}
return fullPath ;
}
public void AddHelperAndPlaceUnderAll1VfxMainComponent ( )
{
AllIn1ParticleHelperComponent psHelper = GetComponent < AllIn1ParticleHelperComponent > ( ) ;
if ( psHelper ! = null ) return ;
psHelper = gameObject . AddComponent < AllIn1ParticleHelperComponent > ( ) ;
Component [ ] components = GetComponents ( typeof ( Component ) ) ;
int all1ComponentIndex = - 1 ;
bool rendererHasAppeared = false ;
for ( int i = 0 ; i < components . Length ; i + + )
{
if ( components [ i ] . GetType ( ) . FullName . Contains ( "ParticleSystemRenderer" ) ) rendererHasAppeared = true ;
if ( components [ i ] . GetType ( ) . FullName . Contains ( "AllIn1VfxComponent" ) )
{
all1ComponentIndex = i ;
break ;
}
}
if ( all1ComponentIndex < = - 1 ) return ;
int upTimes = components . Length - 2 - all1ComponentIndex ;
if ( ! rendererHasAppeared ) upTimes - = 1 ; //Takes into account invisible particle Renderer component
if ( upTimes > 0 )
for ( int i = 0 ; i < upTimes ; i + + )
UnityEditorInternal . ComponentUtility . MoveComponentUp ( psHelper ) ;
}
[ContextMenu("Move component to the top of Inspector")]
public void MoveComponentToTheTop ( )
{
Component [ ] components = GetComponents ( typeof ( Component ) ) ;
int upTimes = components . Length - 2 ;
if ( upTimes > 0 )
for ( int i = 0 ; i < upTimes ; i + + )
UnityEditorInternal . ComponentUtility . MoveComponentUp ( this ) ;
}
[ContextMenu("Delete all All1Vfx Components in Hierarchy")]
private void DeleteAllParticleHelpersInHierarchy ( )
{
StartCoroutine ( DeleteAllChildAll1VfxComponentsCR ( ) ) ;
StartCoroutine ( DelayedDestroyCR ( ) ) ;
}
[ContextMenu("Delete child All1Vfx Components")]
private void DeleteChildParticleHelpers ( )
{
StartCoroutine ( DeleteAllChildAll1VfxComponentsCR ( ) ) ;
}
private IEnumerator DelayedDestroyCR ( )
{
yield return null ;
DestroyImmediate ( this ) ;
}
private IEnumerator DeleteAllChildAll1VfxComponentsCR ( )
{
yield return null ;
AllIn1VfxComponent [ ] helpers = gameObject . GetComponentsInChildren < AllIn1VfxComponent > ( ) ;
for ( int i = 0 ; i < helpers . Length ; i + + )
if ( ! helpers [ i ] . gameObject . Equals ( gameObject ) )
DestroyImmediate ( helpers [ i ] ) ;
}
#endif
}
}