CapersProject/Assets/Plugins/AllIn1VfxToolkit/Scripts/AllIn1VfxComponent.cs
SweetJJuya 11bc3b60ca 임시
2025-02-10 14:47:48 +09:00

680 lines
23 KiB
C#

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