补齐备份工程打开依赖
This commit is contained in:
@@ -0,0 +1,128 @@
|
||||
// WaterCausticsModules
|
||||
// Copyright (c) 2021 Masataka Hakozaki
|
||||
|
||||
#if WCE_URP
|
||||
using System.Collections.Generic;
|
||||
using MH.WaterCausticsModules.Effect;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Rendering;
|
||||
|
||||
namespace MH.WaterCausticsModules {
|
||||
[ExecuteAlways]
|
||||
[DisallowMultipleComponent]
|
||||
[AddComponentMenu ("")]
|
||||
internal class AtOnce : MonoBehaviour {
|
||||
private WaterCausticsEffect _summoner;
|
||||
private MeshRenderer _render;
|
||||
internal MeshRenderer render => _render;
|
||||
private void setRenderEnable (bool isOn) {
|
||||
if (_render && _render.enabled != isOn) _render.enabled = isOn;
|
||||
}
|
||||
|
||||
private bool _inited;
|
||||
private AtOnce init (WaterCausticsEffect summoner, Material mat) {
|
||||
_inited = true;
|
||||
_summoner = summoner;
|
||||
var mf = gameObject.AddComponent<MeshFilter> ();
|
||||
mf.sharedMesh = getMesh ();
|
||||
_render = gameObject.AddComponent<MeshRenderer> ();
|
||||
_render.sharedMaterial = mat;
|
||||
_render.shadowCastingMode = ShadowCastingMode.Off;
|
||||
_render.lightProbeUsage = LightProbeUsage.Off;
|
||||
_render.reflectionProbeUsage = ReflectionProbeUsage.Off;
|
||||
_render.allowOcclusionWhenDynamic = true;
|
||||
_render.receiveShadows = true;
|
||||
updateTransform ();
|
||||
// -- HideFlags --
|
||||
gameObject.hideFlags = HideFlags.HideAndDontSave | HideFlags.HideInInspector;
|
||||
// gameObject.hideFlags &= (~HideFlags.HideInHierarchy); // デバッグ用 Hierarchyで表示
|
||||
// ---------------
|
||||
return this;
|
||||
}
|
||||
|
||||
private void OnDisable () {
|
||||
setRenderEnable (false);
|
||||
}
|
||||
|
||||
private void OnDestroy () {
|
||||
destroy (ref __mesh);
|
||||
}
|
||||
|
||||
private void LateUpdate () {
|
||||
if (!_summoner || !_summoner.isActiveAndEnabled || _summoner.method != Method.AtOnce) {
|
||||
setRenderEnable (false);
|
||||
} else {
|
||||
setRenderEnable (true);
|
||||
updateTransform ();
|
||||
}
|
||||
}
|
||||
|
||||
private void updateTransform () {
|
||||
if (gameObject.layer != _summoner.gameObject.layer)
|
||||
gameObject.layer = _summoner.gameObject.layer;
|
||||
var sumTra = _summoner.transform;
|
||||
if (transform.parent != sumTra.parent)
|
||||
transform.SetParent (sumTra.parent, worldPositionStays : false);
|
||||
if (transform.localToWorldMatrix != sumTra.localToWorldMatrix) {
|
||||
transform.localPosition = sumTra.localPosition;
|
||||
transform.localRotation = sumTra.localRotation;
|
||||
transform.localScale = sumTra.localScale;
|
||||
}
|
||||
}
|
||||
|
||||
private void Update () {
|
||||
bool isLeaked = (!_inited || !_summoner || _summoner.atOnce != this);
|
||||
if (isLeaked) destroy (gameObject);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------- Mesh
|
||||
private Mesh __mesh;
|
||||
private Mesh getMesh () {
|
||||
if (!__mesh) {
|
||||
Mesh m = new Mesh ();
|
||||
m.name = "WCEMeshForAtOnce";
|
||||
m.vertices = new Vector3 [] { new Vector3 (-.5f, -.5f, -.5f), new Vector3 (.5f, -.5f, -.5f), new Vector3 (-.5f, .5f, -.5f), new Vector3 (.5f, .5f, -.5f), new Vector3 (-.5f, -.5f, .5f), new Vector3 (.5f, -.5f, .5f), new Vector3 (-.5f, .5f, .5f), new Vector3 (.5f, .5f, .5f), /* */ Vector3.zero, Vector3.zero, Vector3.zero, Vector3.zero, Vector3.zero, Vector3.zero, Vector3.zero, Vector3.zero };
|
||||
m.triangles = new int [] { 2, 6, 7, 2, 7, 3, 0, 2, 3, 0, 3, 1, 1, 3, 7, 1, 7, 5, 0, 4, 6, 0, 6, 2, 4, 5, 7, 4, 7, 6, 0, 1, 5, 0, 5, 4, /* */ 15, 8, 9, 15, 9, 10, 15, 10, 11, 15, 11, 12, 15, 12, 13, 15, 13, 14 };
|
||||
m.bounds = new Bounds (Vector3.zero, Vector3.one);
|
||||
m.hideFlags = HideFlags.HideAndDontSave;
|
||||
m.UploadMeshData (markNoLongerReadable: true);
|
||||
__mesh = m;
|
||||
}
|
||||
return __mesh;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------- Static
|
||||
|
||||
static internal AtOnce Create (WaterCausticsEffect summoner, Material mat) {
|
||||
var name = "(WCE Renderer) (Deletable)";
|
||||
var go = new GameObject (name);
|
||||
go.SetActive (false); // ← Flags設定時にOnEnable,OnDisableが呼ばれる不具合の回避
|
||||
var a = go.AddComponent<AtOnce> ().init (summoner, mat);
|
||||
go.SetActive (true);
|
||||
return a;
|
||||
}
|
||||
|
||||
static internal void OnSummonerDestroyed (ref AtOnce a) {
|
||||
if (a == null) return;
|
||||
destroy (a.gameObject);
|
||||
a = null;
|
||||
}
|
||||
|
||||
static private void destroy<T> (ref T o) where T : Object {
|
||||
if (o == null) return;
|
||||
destroy (o);
|
||||
o = null;
|
||||
}
|
||||
|
||||
static private void destroy (Object o) {
|
||||
if (o == null) return;
|
||||
if (Application.isPlaying)
|
||||
Destroy (o);
|
||||
else
|
||||
DestroyImmediate (o);
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------
|
||||
}
|
||||
}
|
||||
#endif // End of WCE_URP
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 22b1121aa1f7879478a6b6b90e1a9738
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: eb81f73566a5654488dbc4e168ae6b26
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,97 @@
|
||||
// WaterCausticsModules
|
||||
// Copyright (c) 2021 Masataka Hakozaki
|
||||
|
||||
#if UNITY_EDITOR && (!WCE_URP || WCE_DEVELOPMENT)
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
#pragma warning disable 162
|
||||
|
||||
namespace MH.WaterCausticsModules {
|
||||
/*------------------------------------------------------------------------
|
||||
URP10.4以上のパッケージを持っていない場合にEffectモジュールを削除。
|
||||
initializeOnLoad と インポート時に削除を試す
|
||||
-------------------------------------------------------------------------*/
|
||||
public class CheckRenderPipeline : AssetPostprocessor {
|
||||
static private readonly string classFileName = $"{typeof(CheckRenderPipeline).Name}.cs";
|
||||
|
||||
#if WCE_DEVELOPMENT
|
||||
[MenuItem ("WCM/TestDialog/DeleteEffectModuleDialog")]
|
||||
static void dialogTest () => showDialogAndWarning ();
|
||||
static private readonly bool isDeveloping = true;
|
||||
#else
|
||||
static private readonly bool isDeveloping = false;
|
||||
#endif
|
||||
|
||||
[InitializeOnLoadMethod]
|
||||
private static void initializeOnLoad () {
|
||||
EditorApplication.delayCall += delayCall;
|
||||
}
|
||||
private static void delayCall () {
|
||||
if (isDeveloping) return;
|
||||
if (findAsset<EffectModuleRef> (out var asset, out var path)) {
|
||||
if (asset.effectModule) {
|
||||
var folderPath = AssetDatabase.GetAssetPath (asset.effectModule);
|
||||
if (!string.IsNullOrEmpty (folderPath) && folderPath.EndsWith (Constant.EFFECT_FOLDER_NAME)) {
|
||||
deleteEffectFolder (folderPath);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static string s_folderPath;
|
||||
static void OnPostprocessAllAssets (string [] imported, string [] deleted, string [] moved, string [] movedFrom) {
|
||||
if (isDeveloping) return;
|
||||
if (findAsset<EffectModuleRef> (out var asset, out var path) && asset.effectModule) {
|
||||
var folderPath = AssetDatabase.GetAssetPath (asset.effectModule);
|
||||
if (!string.IsNullOrEmpty (folderPath) && folderPath.EndsWith (Constant.EFFECT_FOLDER_NAME)) {
|
||||
if (imported.Any (a => a.StartsWith (folderPath))) {
|
||||
// Shaderファイルなどを先に削除 ※Shader Error回避
|
||||
deleteWithoutMat (folderPath);
|
||||
// フォルダの削除はDelayCallで行う ※MaterialPostprocessorでのNullエラー回避
|
||||
s_folderPath = folderPath;
|
||||
EditorApplication.delayCall += () => deleteEffectFolder (s_folderPath);
|
||||
} else {
|
||||
deleteEffectFolder (folderPath);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void deleteWithoutMat (string folderPath) {
|
||||
string [] guids = AssetDatabase.FindAssets ("", new [] { folderPath });
|
||||
string [] paths = guids.Select (guid => AssetDatabase.GUIDToAssetPath (guid)).Where (p => p.EndsWith (".shader") || p.EndsWith (".asset") || p.EndsWith (".lighting")).ToArray ();
|
||||
#if UNITY_2020_1_OR_NEWER
|
||||
AssetDatabase.DeleteAssets (paths, new List<string> ());
|
||||
#else
|
||||
foreach (var p in paths) AssetDatabase.DeleteAsset (p);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void deleteEffectFolder (string folderPath) {
|
||||
if (isDeveloping || string.IsNullOrEmpty (folderPath)) return;
|
||||
if (AssetDatabase.DeleteAsset (folderPath)) {
|
||||
AssetDatabase.Refresh ();
|
||||
showDialogAndWarning ();
|
||||
}
|
||||
}
|
||||
|
||||
static void showDialogAndWarning () {
|
||||
// ----- Dialog表示
|
||||
EditorUtility.DisplayDialog ("Effect module removed.", $"The Effect module of this asset was removed.\n\nBecause the UniversalRP package {Constant.REQUIRE_URP_VER} could not be detected in this project.\n\nSee the Manual for details.\n\n\n({Constant.ASSET_NAME})", "OK");
|
||||
}
|
||||
|
||||
static private bool findAsset<T> (out T asset, out string path) where T : Object {
|
||||
asset = null;
|
||||
path = null;
|
||||
var guids = AssetDatabase.FindAssets ($"t:{typeof (T).ToString()}", new [] { "Assets" }); // ※フォルダ名の最後にスラッシュがあると古いUnityでエラーになるので注意
|
||||
if (guids.Length == 0) return false;
|
||||
path = AssetDatabase.GUIDToAssetPath (guids [0]);
|
||||
asset = AssetDatabase.LoadAssetAtPath<T> (path);
|
||||
return asset != null;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,13 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 4373c16da8bab7841b9c9f883fd8ca5c
|
||||
labels:
|
||||
- WaterCausticsModules
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,67 @@
|
||||
// WaterCausticsModules
|
||||
// Copyright (c) 2021 Masataka Hakozaki
|
||||
|
||||
#if UNITY_EDITOR && WCE_URP
|
||||
|
||||
using System.Collections.Generic;
|
||||
using UnityEditor;
|
||||
using UnityEditor.Build;
|
||||
using UnityEditor.Build.Reporting;
|
||||
using UnityEditor.Rendering;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Rendering;
|
||||
|
||||
namespace MH.WaterCausticsModules {
|
||||
/*------------------------------------------------------------------------
|
||||
Previewウィンドウでエフェクトを無効化
|
||||
-------------------------------------------------------------------------*/
|
||||
public class DisableInPreviewWindow : IPreprocessBuildWithReport, IPostprocessBuildWithReport {
|
||||
private static readonly string KEYWORD = "_WCE_DISABLED";
|
||||
public int callbackOrder => 1;
|
||||
public void OnPreprocessBuild (BuildReport report) {
|
||||
// ビルド前処理
|
||||
disableEvent ();
|
||||
}
|
||||
|
||||
public void OnPostprocessBuild (BuildReport report) {
|
||||
// ビルド後処理
|
||||
enableEvent ();
|
||||
}
|
||||
|
||||
[InitializeOnLoadMethod]
|
||||
static void OnInitialize () {
|
||||
// Editor起動直後、プレイ開始時
|
||||
enableEvent ();
|
||||
}
|
||||
|
||||
static private void enableEvent () {
|
||||
WaterCausticsEffectFeature.onCamRender -= onEnqueue;
|
||||
WaterCausticsEffectFeature.onCamRender += onEnqueue;
|
||||
}
|
||||
|
||||
static private void disableEvent () {
|
||||
Shader.DisableKeyword (KEYWORD);
|
||||
WaterCausticsEffectFeature.onCamRender -= onEnqueue;
|
||||
}
|
||||
|
||||
static private void onEnqueue (Camera cam) {
|
||||
if (cam.cameraType == CameraType.Preview)
|
||||
Shader.EnableKeyword (KEYWORD);
|
||||
else
|
||||
Shader.DisableKeyword (KEYWORD);
|
||||
}
|
||||
|
||||
public class ShaderPreprocessor : IPreprocessShaders {
|
||||
// シェーダバリアント削除
|
||||
public int callbackOrder => 1;
|
||||
public void OnProcessShader (Shader shader, ShaderSnippetData snippet, IList<ShaderCompilerData> data) {
|
||||
var deleteKeyword = new ShaderKeyword (DisableInPreviewWindow.KEYWORD);
|
||||
for (var i = data.Count - 1; i >= 0; --i)
|
||||
if (data [i].shaderKeywordSet.IsEnabled (deleteKeyword))
|
||||
data.RemoveAt (i);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 8326956518b565e44a9cb612c6b7f963
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,17 @@
|
||||
%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: 276d321c87e0f494fb5e61d87eb50ad6, type: 3}
|
||||
m_Name: EffectModuleRef
|
||||
m_EditorClassIdentifier:
|
||||
m_effectModule: {fileID: 102900000, guid: 557c32d7360c26949947ac9dd8c308fc, type: 3}
|
||||
m_customFunc: {fileID: 102900000, guid: 5c458e7b6a8f6024aba7bed0ab7b3320, type: 3}
|
||||
m_packageForASE: {fileID: 102900000, guid: cd1a5fad241143647aa5403add1f9fd8, type: 3}
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 9e71d80f209a88447bb8a57499210fd2
|
||||
NativeFormatImporter:
|
||||
externalObjects: {}
|
||||
mainObjectFileID: 11400000
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,25 @@
|
||||
// WaterCausticsModules
|
||||
// Copyright (c) 2021 Masataka Hakozaki
|
||||
|
||||
#if UNITY_EDITOR
|
||||
using UnityEngine;
|
||||
|
||||
namespace MH.WaterCausticsModules {
|
||||
#if WCE_DEVELOPMENT
|
||||
[CreateAssetMenu]
|
||||
#endif
|
||||
public class EffectModuleRef : ScriptableObject {
|
||||
// WaterCausticEffectフォルダ
|
||||
[SerializeField] private Object m_effectModule;
|
||||
internal Object effectModule => m_effectModule;
|
||||
|
||||
// ShaderFunctionsフォルダ
|
||||
[SerializeField] private Object m_customFunc;
|
||||
internal Object customFunc => m_customFunc;
|
||||
|
||||
// ForAmplifyShaderEditor.unitypackageファイル
|
||||
[SerializeField] private Object m_packageForASE;
|
||||
internal Object packageForASE => m_packageForASE;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 276d321c87e0f494fb5e61d87eb50ad6
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,50 @@
|
||||
// WaterCausticsModules
|
||||
// Copyright (c) 2021 Masataka Hakozaki
|
||||
|
||||
#if UNITY_EDITOR && WCE_URP && AMPLIFY_SHADER_EDITOR
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
#pragma warning disable 162
|
||||
|
||||
namespace MH.WaterCausticsModules {
|
||||
/*------------------------------------------------------------------------
|
||||
AmplifyShaderEditorがある環境でアセットがインポートされた際、
|
||||
AmplifyShaderEditor用のカスタムファンクションパッケージを自動インポート
|
||||
-------------------------------------------------------------------------*/
|
||||
public class ImportPackageForASE {
|
||||
#if WCE_DEVELOPMENT
|
||||
static private readonly bool isDeveloping = true;
|
||||
#else
|
||||
static private readonly bool isDeveloping = false;
|
||||
#endif
|
||||
|
||||
[InitializeOnLoadMethod]
|
||||
public static void registerCallback () {
|
||||
AssetDatabase.importPackageCompleted -= importCompleted;
|
||||
AssetDatabase.importPackageCompleted += importCompleted;
|
||||
}
|
||||
|
||||
static void importCompleted (string packageName) {
|
||||
if (isDeveloping) return;
|
||||
if (Constant.CheckPackageName (packageName) && findAsset<EffectModuleRef> (out var asset, out var path) && asset.packageForASE) {
|
||||
string packagePath = AssetDatabase.GetAssetPath (asset.packageForASE);
|
||||
if (packagePath != null && packagePath.EndsWith (Constant.ASE_PACKAGE_NAME)) {
|
||||
AssetDatabase.ImportPackage (packagePath, false);
|
||||
AssetDatabase.DeleteAsset (packagePath);
|
||||
AssetDatabase.Refresh ();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static private bool findAsset<T> (out T asset, out string path) where T : Object {
|
||||
asset = null;
|
||||
path = null;
|
||||
var guids = AssetDatabase.FindAssets ($"t:{typeof (T).ToString()}", new [] { "Assets" });
|
||||
if (guids.Length == 0) return false;
|
||||
path = AssetDatabase.GUIDToAssetPath (guids [0]);
|
||||
asset = AssetDatabase.LoadAssetAtPath<T> (path);
|
||||
return asset != null;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: abb96ab8cc4602440a3c0f2ddea9415e
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,54 @@
|
||||
// WaterCausticsModules
|
||||
// Copyright (c) 2021 Masataka Hakozaki
|
||||
|
||||
#if UNITY_EDITOR && WCE_URP
|
||||
using System.Collections.Generic;
|
||||
using UnityEditor.Build;
|
||||
using UnityEditor.Rendering;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Rendering;
|
||||
|
||||
namespace MH.WaterCausticsModules {
|
||||
/*------------------------------------------------------------------------
|
||||
ビルド時シェーダバリアント削除
|
||||
-------------------------------------------------------------------------*/
|
||||
public class OptimizeShader : IPreprocessShaders {
|
||||
public int callbackOrder => 1;
|
||||
|
||||
private readonly ShaderKeyword [] delKeys = {
|
||||
new ShaderKeyword ("WCE_DEBUG_NORMAL"),
|
||||
new ShaderKeyword ("WCE_DEBUG_DEPTH"),
|
||||
new ShaderKeyword ("WCE_DEBUG_FACING"),
|
||||
new ShaderKeyword ("WCE_DEBUG_CAUSTICS"),
|
||||
new ShaderKeyword ("WCE_DEBUG_AREA"),
|
||||
#if !WCE_URP_12_0 // URP12より下の場合
|
||||
new ShaderKeyword ("_GBUFFER_NORMALS_OCT"),
|
||||
new ShaderKeyword ("_LIGHT_LAYERS"),
|
||||
new ShaderKeyword ("_LIGHT_COOKIES"),
|
||||
#endif
|
||||
#if !WCE_URP_14_0 // URP14より下の場合
|
||||
new ShaderKeyword ("_FORWARD_PLUS"),
|
||||
#endif
|
||||
};
|
||||
|
||||
private bool hasDelKey (ShaderKeywordSet set) {
|
||||
foreach (var key in delKeys)
|
||||
if (set.IsEnabled (key))
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
public void OnProcessShader (Shader shader, ShaderSnippetData snippet, IList<ShaderCompilerData> data) {
|
||||
// シェーダ名チェック
|
||||
if (!shader.name.StartsWith (Constant.SHADER_NAME_HEADER)) return;
|
||||
// キーを持っているか確認 & 削除
|
||||
for (var i = data.Count - 1; i >= 0; --i) {
|
||||
if (hasDelKey (data [i].shaderKeywordSet))
|
||||
data.RemoveAt (i);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: cacb7892edc3def4f8111ae95a40c233
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,40 @@
|
||||
// WaterCausticsModules
|
||||
// Copyright (c) 2021 Masataka Hakozaki
|
||||
|
||||
#if UNITY_EDITOR && WCE_URP
|
||||
using System.Linq;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
|
||||
namespace MH.WaterCausticsModules {
|
||||
/*------------------------------------------------------------------------
|
||||
「missing SubGraph references」エラーを防ぐため、このスクリプトが移動した
|
||||
ことを検知した際にShaderFunctionsフォルダを再インポート。
|
||||
-------------------------------------------------------------------------*/
|
||||
public class ReimportFunctions : AssetPostprocessor {
|
||||
static private readonly string classFileName = $"{typeof (ReimportFunctions).Name}.cs";
|
||||
static void OnPostprocessAllAssets (string [] imported, string [] deleted, string [] moved, string [] movedFrom) {
|
||||
// ※移動時と名称変更時、フォルダは importedAssetsとmovedAssetsに入るので注意、アセットはmovedAssetsのみ
|
||||
if (moved.Any (a => a.EndsWith (classFileName)) && !imported.Any (a => a.EndsWith (classFileName))) {
|
||||
if (findAsset<EffectModuleRef> (out var asset, out var path) && asset.customFunc) {
|
||||
var folderPath = AssetDatabase.GetAssetPath (asset.customFunc);
|
||||
if (!string.IsNullOrEmpty (folderPath) && moved.Any (a => a == folderPath)) {
|
||||
AssetDatabase.ImportAsset (folderPath, ImportAssetOptions.ImportRecursive);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static private bool findAsset<T> (out T asset, out string path) where T : Object {
|
||||
asset = null;
|
||||
path = null;
|
||||
var guids = AssetDatabase.FindAssets ($"t:{typeof (T).ToString()}", new [] { "Assets" });
|
||||
if (guids.Length == 0) return false;
|
||||
path = AssetDatabase.GUIDToAssetPath (guids [0]);
|
||||
asset = AssetDatabase.LoadAssetAtPath<T> (path);
|
||||
return asset != null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 262d8e92d9439494bbb7bb9d66dee10a
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,15 @@
|
||||
%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: 71d38c23289312844bc6e88159ed75c7, type: 3}
|
||||
m_Name: WaterCausticsEffectData
|
||||
m_EditorClassIdentifier:
|
||||
m_autoManageFeature: 1
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 062a4f28f6d145a4798a42cbe2bf6992
|
||||
NativeFormatImporter:
|
||||
externalObjects: {}
|
||||
mainObjectFileID: 11400000
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,47 @@
|
||||
// WaterCausticsModules
|
||||
// Copyright (c) 2021 Masataka Hakozaki
|
||||
|
||||
#if UNITY_EDITOR && WCE_URP
|
||||
using System.IO;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
|
||||
namespace MH.WaterCausticsModules {
|
||||
public class WaterCausticsEffectData : ScriptableObject {
|
||||
// ---------------------------------------------------------
|
||||
[SerializeField] internal bool m_autoManageFeature = true;
|
||||
internal bool AutoManageFeature => m_autoManageFeature;
|
||||
|
||||
// ---------------------------------------------------------
|
||||
static private WaterCausticsEffectData _s_ins;
|
||||
static internal WaterCausticsEffectData GetAsset () {
|
||||
if (_s_ins) return _s_ins;
|
||||
if (findAsset<WaterCausticsEffectData> (out var ins, out var path)) return _s_ins = ins;
|
||||
return _s_ins = createAsset<WaterCausticsEffectData> ();
|
||||
}
|
||||
|
||||
static private bool findAsset<T> (out T asset, out string path) where T : Object {
|
||||
asset = null;
|
||||
path = null;
|
||||
var guids = AssetDatabase.FindAssets ($"t:{typeof (T).ToString()}", new [] { "Assets" });
|
||||
if (guids.Length == 0) return false;
|
||||
path = AssetDatabase.GUIDToAssetPath (guids [0]);
|
||||
asset = AssetDatabase.LoadAssetAtPath<T> (path);
|
||||
return asset != null;
|
||||
}
|
||||
|
||||
static private T createAsset<T> () where T : ScriptableObject {
|
||||
T asset = ScriptableObject.CreateInstance<T> ();
|
||||
MonoScript mono = MonoScript.FromScriptableObject (asset);
|
||||
string scriptPath = AssetDatabase.GetAssetPath (mono);
|
||||
string folderPath = Path.GetDirectoryName (scriptPath).Replace ("\\", "/");
|
||||
string path = $"{folderPath}/{Path.GetFileNameWithoutExtension (scriptPath)}.asset";
|
||||
AssetDatabase.CreateAsset (asset, path);
|
||||
AssetDatabase.SaveAssets ();
|
||||
return asset;
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 71d38c23289312844bc6e88159ed75c7
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,935 @@
|
||||
// WaterCausticsModules
|
||||
// Copyright (c) 2021 Masataka Hakozaki
|
||||
|
||||
#if UNITY_EDITOR && WCE_URP
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text.RegularExpressions;
|
||||
using MH.WaterCausticsModules.Effect;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Rendering;
|
||||
using UnityEngine.Rendering.Universal;
|
||||
|
||||
namespace MH.WaterCausticsModules {
|
||||
[CanEditMultipleObjects]
|
||||
[CustomEditor (typeof (WaterCausticsEffect))]
|
||||
public class WaterCausticsEffectEditor : Editor {
|
||||
private SerializedProperty m_method;
|
||||
private SerializedProperty m_normalSrc;
|
||||
private SerializedProperty m_debugInfo;
|
||||
private SerializedProperty m_debugMode;
|
||||
private SerializedProperty m_useLayer;
|
||||
private SerializedProperty m_renderLayerMask;
|
||||
private SerializedProperty m_layerMask;
|
||||
private SerializedProperty m_clipOutside;
|
||||
private SerializedProperty m_texture;
|
||||
private SerializedProperty m_textureChannel;
|
||||
private SerializedProperty m_textureRotation;
|
||||
private SerializedProperty m_texRotSinCos;
|
||||
private SerializedProperty m_useRandomTiling;
|
||||
private SerializedProperty m_tilingSeed;
|
||||
private SerializedProperty m_tilingRotation;
|
||||
private SerializedProperty m_tilingHardness;
|
||||
private SerializedProperty m_intensity;
|
||||
private SerializedProperty m_mainLit;
|
||||
private SerializedProperty m_addLit;
|
||||
private SerializedProperty m_colorShift;
|
||||
private SerializedProperty m_colorShiftDir;
|
||||
private SerializedProperty m_scale;
|
||||
private SerializedProperty m_surfaceY;
|
||||
private SerializedProperty m_surfFadeStart;
|
||||
private SerializedProperty m_surfFadeEnd;
|
||||
private SerializedProperty m_useDepthFade;
|
||||
private SerializedProperty m_depthFadeStart;
|
||||
private SerializedProperty m_depthFadeEnd;
|
||||
private SerializedProperty m_useDistanceFade;
|
||||
private SerializedProperty m_distanceFadeStart;
|
||||
private SerializedProperty m_distanceFadeEnd;
|
||||
private SerializedProperty m_litSaturation;
|
||||
private SerializedProperty m_multiply;
|
||||
private SerializedProperty m_normalAttenRate;
|
||||
private SerializedProperty m_normalAtten;
|
||||
private SerializedProperty m_transparentBackside;
|
||||
private SerializedProperty m_backsideShadow;
|
||||
private SerializedProperty m_shadowIntensity;
|
||||
private SerializedProperty m_receiveShadows;
|
||||
private SerializedProperty m_useMainLit;
|
||||
private SerializedProperty m_useAddLit;
|
||||
private SerializedProperty m_useImageMask;
|
||||
private SerializedProperty m_imageMaskTexture;
|
||||
private SerializedProperty m_stencilRef;
|
||||
private SerializedProperty m_stencilReadMask;
|
||||
private SerializedProperty m_stencilWriteMask;
|
||||
private SerializedProperty m_stencilComp;
|
||||
private SerializedProperty m_stencilPass;
|
||||
private SerializedProperty m_stencilFail;
|
||||
private SerializedProperty m_stencilZFail;
|
||||
private SerializedProperty m_cullMode;
|
||||
private SerializedProperty m_zWriteMode;
|
||||
private SerializedProperty m_zTestMode;
|
||||
private SerializedProperty m_depthOffsetFactor;
|
||||
private SerializedProperty m_depthOffsetUnits;
|
||||
private SerializedProperty m_shader;
|
||||
private SerializedProperty m_noTexture;
|
||||
private SerializedProperty m_useCustomFunc;
|
||||
private SerializedProperty m_renderEvent;
|
||||
private SerializedProperty m_renderEventAdjust;
|
||||
|
||||
private void prepProperties () {
|
||||
if (m_method != null) return;
|
||||
m_method = serializedObject.FindProperty ("m_method");
|
||||
m_normalSrc = serializedObject.FindProperty ("m_normalSrc");
|
||||
m_debugInfo = serializedObject.FindProperty ("m_debugInfo");
|
||||
m_debugMode = serializedObject.FindProperty ("m_debugMode");
|
||||
m_useLayer = serializedObject.FindProperty ("m_useLayer");
|
||||
m_renderLayerMask = serializedObject.FindProperty ("m_renderLayerMask");
|
||||
m_layerMask = serializedObject.FindProperty ("m_layerMask");
|
||||
m_clipOutside = serializedObject.FindProperty ("m_clipOutside");
|
||||
m_texture = serializedObject.FindProperty ("m_texture");
|
||||
m_textureChannel = serializedObject.FindProperty ("m_textureChannel");
|
||||
m_textureRotation = serializedObject.FindProperty ("m_textureRotation");
|
||||
m_texRotSinCos = serializedObject.FindProperty ("m_texRotSinCos");
|
||||
m_useRandomTiling = serializedObject.FindProperty ("m_useRandomTiling");
|
||||
m_tilingSeed = serializedObject.FindProperty ("m_tilingSeed");
|
||||
m_tilingRotation = serializedObject.FindProperty ("m_tilingRotation");
|
||||
m_tilingHardness = serializedObject.FindProperty ("m_tilingHardness");
|
||||
m_intensity = serializedObject.FindProperty ("m_intensity");
|
||||
m_mainLit = serializedObject.FindProperty ("m_mainLit");
|
||||
m_addLit = serializedObject.FindProperty ("m_addLit");
|
||||
m_colorShift = serializedObject.FindProperty ("m_colorShift");
|
||||
m_colorShiftDir = serializedObject.FindProperty ("m_colorShiftDir");
|
||||
m_scale = serializedObject.FindProperty ("m_scale");
|
||||
m_surfaceY = serializedObject.FindProperty ("m_surfaceY");
|
||||
m_surfFadeStart = serializedObject.FindProperty ("m_surfFadeStart");
|
||||
m_surfFadeEnd = serializedObject.FindProperty ("m_surfFadeEnd");
|
||||
m_useDepthFade = serializedObject.FindProperty ("m_useDepthFade");
|
||||
m_depthFadeStart = serializedObject.FindProperty ("m_depthFadeStart");
|
||||
m_depthFadeEnd = serializedObject.FindProperty ("m_depthFadeEnd");
|
||||
m_useDistanceFade = serializedObject.FindProperty ("m_useDistanceFade");
|
||||
m_distanceFadeStart = serializedObject.FindProperty ("m_distanceFadeStart");
|
||||
m_distanceFadeEnd = serializedObject.FindProperty ("m_distanceFadeEnd");
|
||||
m_litSaturation = serializedObject.FindProperty ("m_litSaturation");
|
||||
m_multiply = serializedObject.FindProperty ("m_multiply");
|
||||
m_normalAttenRate = serializedObject.FindProperty ("m_normalAttenRate");
|
||||
m_normalAtten = serializedObject.FindProperty ("m_normalAtten");
|
||||
m_transparentBackside = serializedObject.FindProperty ("m_transparentBackside");
|
||||
m_backsideShadow = serializedObject.FindProperty ("m_backsideShadow");
|
||||
m_shadowIntensity = serializedObject.FindProperty ("m_shadowIntensity");
|
||||
m_receiveShadows = serializedObject.FindProperty ("m_receiveShadows");
|
||||
m_useMainLit = serializedObject.FindProperty ("m_useMainLit");
|
||||
m_useAddLit = serializedObject.FindProperty ("m_useAddLit");
|
||||
m_useImageMask = serializedObject.FindProperty ("m_useImageMask");
|
||||
m_imageMaskTexture = serializedObject.FindProperty ("m_imageMaskTexture");
|
||||
m_stencilRef = serializedObject.FindProperty ("m_stencilRef");
|
||||
m_stencilReadMask = serializedObject.FindProperty ("m_stencilReadMask");
|
||||
m_stencilWriteMask = serializedObject.FindProperty ("m_stencilWriteMask");
|
||||
m_stencilComp = serializedObject.FindProperty ("m_stencilComp");
|
||||
m_stencilPass = serializedObject.FindProperty ("m_stencilPass");
|
||||
m_stencilFail = serializedObject.FindProperty ("m_stencilFail");
|
||||
m_stencilZFail = serializedObject.FindProperty ("m_stencilZFail");
|
||||
m_cullMode = serializedObject.FindProperty ("m_cullMode");
|
||||
m_zWriteMode = serializedObject.FindProperty ("m_zWriteMode");
|
||||
m_zTestMode = serializedObject.FindProperty ("m_zTestMode");
|
||||
m_depthOffsetFactor = serializedObject.FindProperty ("m_depthOffsetFactor");
|
||||
m_depthOffsetUnits = serializedObject.FindProperty ("m_depthOffsetUnits");
|
||||
m_shader = serializedObject.FindProperty ("m_shader");
|
||||
m_noTexture = serializedObject.FindProperty ("m_noTexture");
|
||||
m_useCustomFunc = serializedObject.FindProperty ("m_useCustomFunc");
|
||||
m_renderEvent = serializedObject.FindProperty ("m_renderEvent");
|
||||
m_renderEventAdjust = serializedObject.FindProperty ("m_renderEventAdjust");
|
||||
}
|
||||
|
||||
private SerializedObject _wceData;
|
||||
private SerializedProperty m_autoManageFeature;
|
||||
private SerializedObject prepWceData () {
|
||||
if (_wceData == null)
|
||||
_wceData = new SerializedObject (WaterCausticsEffectData.GetAsset ());
|
||||
if (m_autoManageFeature == null) {
|
||||
m_autoManageFeature = _wceData.FindProperty ("m_autoManageFeature");
|
||||
}
|
||||
_wceData.Update ();
|
||||
return _wceData;
|
||||
}
|
||||
|
||||
static readonly GUIContent [] _cullingEnumStr = {
|
||||
new GUIContent ("Both"),
|
||||
new GUIContent ("Back"),
|
||||
new GUIContent ("Front"),
|
||||
};
|
||||
|
||||
static readonly string descGenFromDepth = "[Generate from Depth] \nGenerate from _CameraDepthTexture generated by the system. This method is not good for smooth surfaces, but it does produce the correct normals.";
|
||||
static readonly string descCamNormalTex = "[Camera Normals Tex] \nSampling _CameraNormalsTexture generated by the system. This is high quality, but may produce strange results with materials that do not support normal output.";
|
||||
|
||||
static readonly GUIContent [] _normalSrcStr = {
|
||||
new GUIContent ("Generate from Depth (LQ)", $"{descGenFromDepth}\n\n{descCamNormalTex}"),
|
||||
new GUIContent ("Camera Normals Tex (HQ)", $"{descGenFromDepth}\n\n{descCamNormalTex}"),
|
||||
};
|
||||
|
||||
static readonly string [] _renderingLayerMaskNamesSpare = { "Layer1", "Layer2", "Layer3", "Layer4", "Layer5", "Layer6", "Layer7", "Layer8", "Layer9", "Layer10", "Layer11", "Layer12", "Layer13", "Layer14", "Layer15", "Layer16", "Layer17", "Layer18", "Layer19", "Layer20", "Layer21", "Layer22", "Layer23", "Layer24", "Layer25", "Layer26", "Layer27", "Layer28", "Layer29", "Layer30", "Layer31", "Layer32", };
|
||||
|
||||
private List<ScriptableRendererData> _rendererDataList;
|
||||
private bool _hasGetRenderData;
|
||||
|
||||
protected virtual void OnEnable () {
|
||||
foreach (var tar in targets.OfType<WaterCausticsEffect> ())
|
||||
tar.VersionCheck ();
|
||||
}
|
||||
|
||||
UniversalRenderPipelineAsset urpAsset => GraphicsSettings.currentRenderPipeline as UniversalRenderPipelineAsset;
|
||||
public override void OnInspectorGUI () {
|
||||
if (urpAsset) {
|
||||
var wceData = prepWceData ();
|
||||
prepProperties ();
|
||||
serializedObject.Update ();
|
||||
using (var check = new EditorGUI.ChangeCheckScope ()) {
|
||||
drawProperties ();
|
||||
serializedObject.ApplyModifiedProperties ();
|
||||
wceData.ApplyModifiedProperties ();
|
||||
if (check.changed) {
|
||||
foreach (var tar in targets.OfType<WaterCausticsEffect> ())
|
||||
tar.OnInspectorChanged ();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// -- URP設定が完了していない場合
|
||||
onInspectorGUI_NotSettingYet ();
|
||||
}
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------
|
||||
readonly Color colorPinkBar = new Color (1f, 0.3f, 0.6f, 0.3f);
|
||||
readonly Color colorPinkContent = new Color (1f, 0.3f, 0.6f, 1f);
|
||||
readonly Color colorGreenContent = new Color (0.4f, 1f, 0.7f, 1f);
|
||||
private float lineH = EditorGUIUtility.singleLineHeight + 2;
|
||||
readonly float SPACE_SUB_TOP_5 = 5f;
|
||||
readonly float SPACE_SUB_BTM_12 = 12f;
|
||||
readonly float SPACE_MAIN_TOP_7 = 7f;
|
||||
readonly float SPACE_MAIN_BTM_5 = 5f;
|
||||
private Color _defaultGUIColor;
|
||||
|
||||
private void setLabelAreaWidth (float labelWidthMin, float valWidthMin) {
|
||||
if (EditorGUIUtility.labelWidth < labelWidthMin)
|
||||
EditorGUIUtility.labelWidth = labelWidthMin;
|
||||
if (EditorGUIUtility.currentViewWidth - EditorGUIUtility.labelWidth < valWidthMin)
|
||||
EditorGUIUtility.labelWidth = EditorGUIUtility.currentViewWidth - valWidthMin;
|
||||
}
|
||||
|
||||
private void drawProperties () {
|
||||
_defaultGUIColor = GUI.color;
|
||||
storeIndentWidth ();
|
||||
EditorGUIUtility.labelWidth += 6;
|
||||
EditorGUI.indentLevel++;
|
||||
setLabelAreaWidth (labelWidthMin: 140f, valWidthMin: 170f);
|
||||
bool isEditingMultiObj = serializedObject.isEditingMultipleObjects;
|
||||
bool isMethodEach = (m_method.enumValueIndex == (int) Method.EachMesh && !m_method.hasMultipleDifferentValues);
|
||||
bool isMethodOnce = (m_method.enumValueIndex == (int) Method.AtOnce && !m_method.hasMultipleDifferentValues);
|
||||
// ---------------------------------------------------------------------------------- System
|
||||
|
||||
// ------ RendererFeature
|
||||
if (!_hasGetRenderData) {
|
||||
_hasGetRenderData = true;
|
||||
WaterCausticsEffectFeatureEditor.GetAllRendererData (out _rendererDataList);
|
||||
if (WaterCausticsEffectData.GetAsset ().AutoManageFeature)
|
||||
WaterCausticsEffectFeatureEditor.AddFeatureToAllRenderers (_rendererDataList, useUndo : false);
|
||||
}
|
||||
bool someRenderNotHasFeature = !WaterCausticsEffectFeatureEditor.CheckAllHasActiveFeature (_rendererDataList);
|
||||
bool currentRenderNotHasFeature = someRenderNotHasFeature && !WaterCausticsEffectFeature.effective;
|
||||
// ----------------------
|
||||
|
||||
if (expandMainGroup (m_method, true, "System", isPink : currentRenderNotHasFeature)) {
|
||||
EditorGUILayout.Space (SPACE_MAIN_TOP_7);
|
||||
|
||||
// ------ RendererFeature
|
||||
if (someRenderNotHasFeature) {
|
||||
EditorGUI.indentLevel -= 1;
|
||||
// labelWarning("To apply this effect, a Renderer Feature needs to be added to a Renderer.", 11);
|
||||
using (new ColorScope (currentRenderNotHasFeature ? colorPinkContent : _defaultGUIColor)) {
|
||||
string str = "To apply this effect, a Renderer Feature needs to be added to a Renderer.";
|
||||
if (currentRenderNotHasFeature)
|
||||
EditorGUILayout.HelpBox ($"The Renderer Feature has not been added or activated in the current Renderer.\n{str}", MessageType.Warning);
|
||||
else
|
||||
EditorGUILayout.HelpBox ($"The Renderer Feature has not been added or activated in some Renderers.\n{str}", MessageType.Warning);
|
||||
EditorGUILayout.Space (2);
|
||||
Rect rect = GUILayoutUtility.GetRect (0, 0);
|
||||
rect.height = lineH;
|
||||
rect.width *= 0.5f;
|
||||
if (GUI.Button (rect, new GUIContent ("Select Renderer", "Search and select RendererData assets."), EditorStyles.miniButton)) {
|
||||
// -- 選択ボタン
|
||||
if (WaterCausticsEffectFeatureEditor.GetAllRendererData (out var list)) {
|
||||
// -- 成功
|
||||
WaterCausticsEffectFeatureEditor.SelectAndPing (list);
|
||||
if (list.Count >= 2) {
|
||||
var pathStr = WaterCausticsEffectFeatureEditor.AssetsToPathStr (list);
|
||||
EditorApplication.delayCall += () => EditorApplication.delayCall += () =>
|
||||
EditorUtility.DisplayDialog ("Multiple found.", $"Multiple RendererData assets found.\n\n{pathStr}", "OK");
|
||||
}
|
||||
} else {
|
||||
// -- 見つからない
|
||||
EditorUtility.DisplayDialog ("Not found.", $"Not found.", "OK");
|
||||
}
|
||||
}
|
||||
rect.x += rect.width;
|
||||
if (GUI.Button (rect, new GUIContent ("Fix It", "Add a Renderer Feature to Renderers."), EditorStyles.miniButton)) {
|
||||
// -- 追加ボタン
|
||||
if (WaterCausticsEffectFeatureEditor.AddFeatureToAllRenderers (useUndo: true)) {
|
||||
// -- 成功
|
||||
} else {
|
||||
// -- 失敗
|
||||
bool showURL = EditorUtility.DisplayDialog ("Failed", "Processing failed. Please add the Renderer Feature to Renderers manually.", "Open URP Manual", "Cancel");
|
||||
if (showURL) Application.OpenURL (Constant.URL_HOW_TO_ADD_FEATURE);
|
||||
}
|
||||
}
|
||||
EditorGUILayout.Space (lineH);
|
||||
using (new ColorScope (_defaultGUIColor)) {
|
||||
EditorGUILayout.Space (1);
|
||||
if (labelLink (new GUIContent ("How to add Renderer Feature to Renderer", Constant.URL_HOW_TO_ADD_FEATURE), 10))
|
||||
Application.OpenURL (Constant.URL_HOW_TO_ADD_FEATURE);
|
||||
EditorGUILayout.Space (4);
|
||||
}
|
||||
EditorGUI.indentLevel += 1;
|
||||
EditorGUILayout.Space (15);
|
||||
}
|
||||
}
|
||||
// ----------------------
|
||||
|
||||
EditorGUILayout.PropertyField (m_method, new GUIContent ("Effect Method", "[At Once]\nDraws the effect at once using the camera's depth and normal texture. It can also be applied to objects with materials that are deformed by shaders. \n\n[Each Mesh]\nDraws effects to each mesh. Masking with layers and the surface to be drawn can be specified. However, it cannot be applied to objects with materials that deform with shaders. For such objects, embed custom function in the shader or use the At Once method."));
|
||||
if (isMethodOnce) {
|
||||
using (new IndentScope (-2f, 0f)) {
|
||||
popup (m_normalSrc, _normalSrcStr, "Normal Data", $"How to get normal vector in world space.\n\n{descGenFromDepth}\n\n{descCamNormalTex}");
|
||||
}
|
||||
}
|
||||
drawBoolAndValue (m_debugInfo, m_debugMode, true, new GUIContent ("Debug Info", "Display data for debugging. This is only valid on the editor.\n\n" +
|
||||
$"[{DebugMode.Normal}]\nDisplays world-space normal data.\n\n" +
|
||||
$"[{DebugMode.Depth}]\nDisplays the depth data.\n\n" +
|
||||
$"[{DebugMode.Facing}]\nDisplays the plane facing the camera as bright.\n\n" +
|
||||
$"[{DebugMode.Caustics}]\nDisplays only caustics effects.\n\n" +
|
||||
$"[{DebugMode.LightArea}]\nDisplays the affected area by each light.\n\n" +
|
||||
$"If some objects are not rendering correctly on At Once method with Camera Normals Tex, the object's material is outputting the wrong normals. Check the normals on this screen and modify the material (shader) of the object."));
|
||||
|
||||
EditorGUILayout.Space (SPACE_SUB_BTM_12);
|
||||
// ---------------------------------------------------------------------------------- Influence Scope
|
||||
if (expandSubGroup (m_useImageMask, true, "Influence Scope")) {
|
||||
EditorGUILayout.Space (SPACE_SUB_TOP_5);
|
||||
selectGameObjectLayer (new GUIContent ("Layer", "The layer in which this effect exists."));
|
||||
if (isMethodEach) {
|
||||
EditorGUILayout.PropertyField (m_layerMask, new GUIContent ("Layer Mask", "Specify the layer on which the effect will be drawn. Objects on unchecked layers will be ignored."));
|
||||
}
|
||||
if (isMethodEach) {
|
||||
EditorGUILayout.PropertyField (m_clipOutside, new GUIContent ("Clip Outside", "Draw effects only inside the volume."));
|
||||
}
|
||||
drawBoolAndValue (m_useImageMask, m_imageMaskTexture, hide : true, new GUIContent ("Image Mask", "Masking with an image."));
|
||||
|
||||
if (isMethodEach) {
|
||||
popup (m_cullMode, _cullingEnumStr, "Render Face", "Which face to draw.");
|
||||
}
|
||||
|
||||
// EditorGUILayout.Space (2);
|
||||
// if (isExpand (m_renderEventAdjust, false, new GUIContent ("Advanced", "Advanced Settings"))) {
|
||||
// using (new IndentScope (0f, 0f)) {
|
||||
EditorGUILayout.PropertyField (m_useCustomFunc, new GUIContent ("Custom Function", "Supports Custom Function for shader. \nTransmits the settings to the WaterCausticsEmissionSync function embedded in the shader. \nTurning this On will copy the settings to a global shader variable. \n\nIf there are multiple effects with this setting On in a scene, the last active effect will be used."));
|
||||
|
||||
{
|
||||
// 描画タイミング設定
|
||||
bool isExpanded = isExpand (m_renderEvent, true, new GUIContent (""));
|
||||
EditorGUILayout.Space (-EditorGUIUtility.singleLineHeight - 2f);
|
||||
string baseTimingName = splitCamelCase (((RenderPassEvent) m_renderEvent.intValue).ToString ());
|
||||
int sysOpqTiming = (int) WaterCausticsEffect.SYS_OPAQUE_TEX_EVENT;
|
||||
string sysOpqName = WaterCausticsEffect.SYS_OPAQUE_TEX_EVENT.ToString ();
|
||||
string sysOpqDesc = $"{sysOpqName}({sysOpqTiming})";
|
||||
string sysOpqDescPlusOne = $"{sysOpqName}+1 ({sysOpqTiming+1})";
|
||||
string defaultTiming = WaterCausticsEffect.RENDER_EVENT.ToString ();
|
||||
int defaultTimingAdj = WaterCausticsEffect.RENDER_EVENT_ADJ;
|
||||
int baseTiming = m_renderEvent.intValue;
|
||||
int adjTiming = m_renderEventAdjust.intValue;
|
||||
int adjusted = baseTiming + adjTiming;
|
||||
bool isHasDifVal = m_renderEvent.hasMultipleDifferentValues || m_renderEventAdjust.hasMultipleDifferentValues;
|
||||
EditorGUILayout.LabelField (new GUIContent ("Draw Timing", $"Specifies the timing of drawing.\n\nTo display this effect on _CameraOpaqueTexture, it must be drawn before {sysOpqDesc}."), new GUIContent (isHasDifVal ? "-" : $"{baseTimingName} {(adjTiming < 0 ? "-" : "+")}{Mathf.Abs(adjTiming)} ({Mathf.Clamp(adjusted, 0, 1000)})"));
|
||||
if (isExpanded) {
|
||||
using (new IndentScope (-2f, 4f)) {
|
||||
EditorGUILayout.PropertyField (m_renderEvent, new GUIContent ($"Render Event", $"Controls when the render executes. \n[Default: {defaultTiming}]"));
|
||||
EditorGUILayout.PropertyField (m_renderEventAdjust, new GUIContent ("Adjustment", $"Controls when the render executes. This number is added to the Draw Timing above. \n[Default: {defaultTimingAdj}]"));
|
||||
bool isEarly = (adjusted <= sysOpqTiming);
|
||||
string warning = isEarly ? $"To use a value between 0 and 1 in the Multiply Color setting, set it after {sysOpqDescPlusOne}." :
|
||||
$"To display this effect on _CameraOpaqueTexture, it must be drawn before {sysOpqDesc}.";
|
||||
EditorGUILayout.HelpBox (new GUIContent (warning, ""), true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (isMethodOnce) {
|
||||
var names = urpAsset.renderingLayerMaskNames;
|
||||
if (names == null) names = _renderingLayerMaskNamesSpare;
|
||||
bitMask (m_renderLayerMask, names, "Render Mask", "Rendering Layer Mask of this effect. It works as same as RenderingLayerMask of MeshRenderer.");
|
||||
}
|
||||
if (isMethodEach) {
|
||||
if (isExpand (m_zTestMode, false, new GUIContent ("Depth Buffer", "Adjust Depth Testing and Depth Offset."))) {
|
||||
using (new IndentScope (0, 2)) {
|
||||
EditorGUILayout.PropertyField (m_zWriteMode, new GUIContent ("ZWrite", "Whether to write depth values to the depth buffer."));
|
||||
EditorGUILayout.PropertyField (m_zTestMode, new GUIContent ("ZTest", "Comparison method with already existing depth values."));
|
||||
EditorGUILayout.PropertyField (m_depthOffsetFactor, new GUIContent ("Offset Factor", "Offset Factor"));
|
||||
EditorGUILayout.PropertyField (m_depthOffsetUnits, new GUIContent ("Offset Units", "Offset Units"));
|
||||
}
|
||||
}
|
||||
EditorGUILayout.Space (2);
|
||||
}
|
||||
if (isExpand (m_stencilRef, false, new GUIContent ("Stencil Buffer", "The Stencil Buffer can be used to limit the objects to be drawn or used for subsequent effects."))) {
|
||||
using (new IndentScope (0, 2)) {
|
||||
EditorGUILayout.PropertyField (m_stencilRef, new GUIContent ("Ref", "Stencil Reference Value"));
|
||||
EditorGUILayout.PropertyField (m_stencilReadMask, new GUIContent ("ReadMask", "Stencil Read Mask"));
|
||||
EditorGUILayout.PropertyField (m_stencilWriteMask, new GUIContent ("WriteMask", "Stencil Write Mask"));
|
||||
EditorGUILayout.PropertyField (m_stencilComp, new GUIContent ("Comp", "Stencil Compare Operation"));
|
||||
EditorGUILayout.PropertyField (m_stencilPass, new GUIContent ("Pass", "Stencil Pass Operation"));
|
||||
EditorGUILayout.PropertyField (m_stencilFail, new GUIContent ("Fail", "Stencil Fail Operation"));
|
||||
EditorGUILayout.PropertyField (m_stencilZFail, new GUIContent ("ZFail", "Stencil Z Fail Operation"));
|
||||
}
|
||||
}
|
||||
// }
|
||||
// }
|
||||
|
||||
}
|
||||
EditorGUILayout.Space (SPACE_SUB_BTM_12);
|
||||
}
|
||||
|
||||
EditorGUILayout.Space (SPACE_MAIN_BTM_5);
|
||||
// ---------------------------------------------------------------------------------- Effect Group
|
||||
bool useTextureWarning = (m_texture.objectReferenceValue == null && isGameObjectOnScene () && !isEditingMultiObj);
|
||||
if (expandMainGroup (m_texture, true, "Caustics Effect", isPink : useTextureWarning && m_texture.isExpanded)) {
|
||||
EditorGUILayout.Space (SPACE_MAIN_TOP_7);
|
||||
|
||||
if (expandSubGroup (m_textureRotation, true, "Texture", isPink : useTextureWarning)) {
|
||||
EditorGUILayout.Space (SPACE_SUB_TOP_5);
|
||||
|
||||
using (new ColorScope (useTextureWarning?colorPinkContent : GUI.color)) {
|
||||
EditorGUILayout.PropertyField (m_texture, new GUIContent ("Caustics Texture", $"Set the RenderTexture specified as the output destination in the {typeof(WaterCausticsTexGenerator).Name}."));
|
||||
if (!m_texture.hasMultipleDifferentValues) {
|
||||
if (useTextureWarning) {
|
||||
EditorGUILayout.Space (1);
|
||||
EditorGUILayout.BeginHorizontal ();
|
||||
GUILayout.FlexibleSpace ();
|
||||
if (GUILayout.Button ("Search from this Scene", EditorStyles.miniButton, GUILayout.Width (150))) {
|
||||
var gen = FindObjectsOfType<WaterCausticsTexGenerator> ().FirstOrDefault (g => g.renderTexture != null);
|
||||
if (gen != null)
|
||||
m_texture.objectReferenceValue = gen.renderTexture;
|
||||
else
|
||||
EditorUtility.DisplayDialog ("Not Found", $"There is no {typeof(WaterCausticsTexGenerator).Name} with active and having RenderTexture in this scene.", "OK");
|
||||
}
|
||||
EditorGUILayout.EndHorizontal ();
|
||||
EditorGUILayout.Space (3);
|
||||
} else {
|
||||
var tex = m_texture.objectReferenceValue as Texture;
|
||||
if (tex != null) {
|
||||
EditorGUILayout.HelpBox ($"{tex.width}x{tex.height} / {tex.graphicsFormat}", MessageType.None);
|
||||
EditorGUILayout.Space (3);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
EditorGUILayout.PropertyField (m_textureChannel, new GUIContent ("Channel", "Channels to be used. Set to R if using R-channel only textures."));
|
||||
using (var check = new EditorGUI.ChangeCheckScope ()) {
|
||||
using (new IndentScope (0f, 0f, 1)) {
|
||||
EditorGUILayout.PropertyField (m_textureRotation, new GUIContent ("Rotation", "Rotate the texture."));
|
||||
drawDirMark (m_textureRotation, true);
|
||||
}
|
||||
if (check.changed) {
|
||||
float rad = m_textureRotation.floatValue * Mathf.Deg2Rad;
|
||||
m_texRotSinCos.vector2Value = new Vector2 (Mathf.Sin (rad), Mathf.Cos (rad));
|
||||
}
|
||||
}
|
||||
EditorGUILayout.PropertyField (m_useRandomTiling, new GUIContent ("Random Tiling", "Use randomized hexagonal tiling. This reduces unnatural repetitions that appear on distant planes."));
|
||||
if (m_useRandomTiling.boolValue) {
|
||||
using (new IndentScope (-2f, 0f)) {
|
||||
EditorGUILayout.PropertyField (m_tilingSeed, new GUIContent ("Seed", "Random seed value."));
|
||||
EditorGUILayout.PropertyField (m_tilingHardness, new GUIContent ("Hardness", "Edge hardness."));
|
||||
EditorGUILayout.PropertyField (m_tilingRotation, new GUIContent ("Rotation", "Rotate tiles randomly."));
|
||||
}
|
||||
}
|
||||
EditorGUILayout.Space (SPACE_SUB_BTM_12);
|
||||
}
|
||||
|
||||
if (expandSubGroup (m_scale, true, "Dimensions")) {
|
||||
EditorGUILayout.Space (SPACE_SUB_TOP_5);
|
||||
|
||||
EditorGUILayout.PropertyField (m_scale, new GUIContent ("Scale", "Texture size at the height of the water surface."));
|
||||
EditorGUILayout.PropertyField (m_surfaceY, new GUIContent ("Water Surface Y", "Height of the water surface. Y-axis. The projected position of the light is calculated with respect to this plane."));
|
||||
|
||||
EditorGUILayout.Space (4);
|
||||
drawStartEndProp (m_surfFadeStart, m_surfFadeEnd, new GUIContent ("Surface Fade", "Attenuates light as it approaches the surface of the water."));
|
||||
EditorGUILayout.PropertyField (m_useDepthFade, new GUIContent ("Depth Fade", "Attenuates light as depth increases."));
|
||||
if (m_useDepthFade.boolValue) {
|
||||
using (new IndentScope (-2f, 0f))
|
||||
drawStartEndProp (m_depthFadeStart, m_depthFadeEnd, new GUIContent ("Range", "Attenuates light as depth increases."));
|
||||
}
|
||||
EditorGUILayout.PropertyField (m_useDistanceFade, new GUIContent ("Distance Fade", "Attenuates light as distance increases."));
|
||||
if (m_useDistanceFade.boolValue) {
|
||||
using (new IndentScope (-2f, 0f))
|
||||
drawStartEndProp (m_distanceFadeStart, m_distanceFadeEnd, new GUIContent ("Range", "Attenuates light as distance increases."));
|
||||
}
|
||||
|
||||
EditorGUILayout.Space (SPACE_SUB_BTM_12);
|
||||
}
|
||||
if (expandSubGroup (m_intensity, true, "Effect")) {
|
||||
EditorGUILayout.Space (SPACE_SUB_TOP_5);
|
||||
|
||||
EditorGUILayout.PropertyField (m_intensity, new GUIContent ("Intensity", "Intensity of effect."));
|
||||
using (new IndentScope (-1f, 1f)) {
|
||||
drawBoolAndValue (m_useMainLit, m_mainLit, hide : true, new GUIContent ("Main Light", "Adjust the intensity of the main light. If the checkbox is Off, the main light calculation is skipped."));
|
||||
drawBoolAndValue (m_useAddLit, m_addLit, hide : true, new GUIContent ("Additional Lights", "Adjust the intensity of the additional lights. If the check box is Off, the calculation of additional lights is skipped."));
|
||||
}
|
||||
EditorGUILayout.Space (2);
|
||||
|
||||
drawBoolAndValue (m_receiveShadows, m_shadowIntensity, hide : true, new GUIContent ("Shadow", "Strength of shadow. If the checkbox is unchecked, the shadow calculation is skipped. \n\nFor the At Once method, \"Transparent Receive Shadows\" in the URP settings must also be set to On."));
|
||||
EditorGUILayout.Space (2);
|
||||
EditorGUILayout.PropertyField (m_colorShift, new GUIContent ("Color Shift", "Amount of RGB channel shift."));
|
||||
if (m_colorShift.floatValue > 0f) {
|
||||
using (new IndentScope (-2f, 0f, 2)) {
|
||||
EditorGUILayout.PropertyField (m_colorShiftDir, new GUIContent ("Direction", "Direction of shift for RGB channels."));
|
||||
drawDirMark (m_colorShiftDir, true);
|
||||
}
|
||||
}
|
||||
EditorGUILayout.Space (2);
|
||||
|
||||
EditorGUILayout.PropertyField (m_litSaturation, new GUIContent ("Light Color", "Color intensity of the light."));
|
||||
EditorGUILayout.Space (2);
|
||||
EditorGUILayout.PropertyField (m_multiply, new GUIContent ("Multiply Color", "Multiply by the screen color and then add. \nIf this value is 1 or 0, it is processed faster because it uses the shader's Blend function. Otherwise, _CameraOpaqueTexture is sampled and multiplied. If the Draw Timing setting is before _CameraOpaqueTexture is drawn, it is processed as 1."));
|
||||
if (!isEditingMultiObj && (m_multiply.floatValue > 0f && m_multiply.floatValue < 1f) &&
|
||||
((m_renderEvent.intValue + m_renderEventAdjust.intValue) <= (int) WaterCausticsEffect.SYS_OPAQUE_TEX_EVENT)
|
||||
) {
|
||||
// 描画タイミングが早すぎる場合警告
|
||||
using (new IndentScope (0f, 0f)) {
|
||||
EditorGUILayout.HelpBox (new GUIContent ("Only 0 or 1 is valid because the Draw Timing is too early.", "Draw Timing in Influence Scope settings is too early and _CameraOpaqueTexture does not exist, so it cannot be drawn with a setting between 0 and 1. Therefore, it is drawn as 1."), true);
|
||||
}
|
||||
}
|
||||
|
||||
EditorGUILayout.Space (3);
|
||||
EditorGUILayout.PropertyField (m_normalAtten, new GUIContent ("Normal Attenuation", "Attenuation due to the angle between the normal and the light ray. \n[Default: 1]")); {
|
||||
using (new IndentScope (-2f, 2f)) {
|
||||
using (new DisableScope (m_normalAtten.floatValue > 0f)) {
|
||||
EditorGUILayout.PropertyField (m_normalAttenRate, new GUIContent ("Rate", "Rate of normal attenuation. How quickly does the light fade. \n[Default: 1.5]"));
|
||||
EditorGUILayout.PropertyField (m_transparentBackside, new GUIContent ("Transparent", "The intensity of light transmitted to the backside. \n[Default: 0]"));
|
||||
}
|
||||
using (new DisableScope (m_receiveShadows.boolValue && (m_normalAtten.floatValue < 1f || m_transparentBackside.floatValue > 0f))) {
|
||||
EditorGUILayout.PropertyField (m_backsideShadow, new GUIContent ("Backside Shadow", "The intensity of shadow on the backside. \n[Default: 0]"));
|
||||
}
|
||||
}
|
||||
}
|
||||
EditorGUILayout.Space (SPACE_SUB_BTM_12);
|
||||
}
|
||||
}
|
||||
|
||||
EditorGUILayout.Space (SPACE_MAIN_BTM_5);
|
||||
// ---------------------------------------------------------------------------------- Advanced Settings
|
||||
if (expandMainGroup (m_backsideShadow, false, "Advanced Settings")) {
|
||||
EditorGUILayout.Space (SPACE_MAIN_TOP_7);
|
||||
|
||||
if (expandSubGroup (m_normalAttenRate, false, "Renderer Feature")) {
|
||||
EditorGUILayout.Space (SPACE_SUB_TOP_5);
|
||||
using (var check = new EditorGUI.ChangeCheckScope ()) {
|
||||
EditorGUILayout.PropertyField (m_autoManageFeature, new GUIContent ("Auto-Management", "Automatically manages Renderer Feature. It automatically adds the Renderer Feature for this effect to all Renderer Data in the project.\n\nIf this is turned off, it is required to manually add the Renderer Feature to the Renderer Data."));
|
||||
if (check.changed && m_autoManageFeature.boolValue == true) {
|
||||
WaterCausticsEffectFeatureEditor.AddFeatureToAllRenderers (useUndo: false);
|
||||
}
|
||||
if (!m_autoManageFeature.boolValue) {
|
||||
EditorGUILayout.Space (1);
|
||||
EditorGUI.indentLevel++;
|
||||
EditorGUILayout.HelpBox ("To apply this effect, a Renderer Feature needs to be added to a Renderer.", MessageType.None);
|
||||
EditorGUILayout.Space (1);
|
||||
if (labelLink (new GUIContent ("How to add Renderer Feature to Renderer", Constant.URL_HOW_TO_ADD_FEATURE), 10, 2))
|
||||
Application.OpenURL (Constant.URL_HOW_TO_ADD_FEATURE);
|
||||
EditorGUI.indentLevel--;
|
||||
}
|
||||
}
|
||||
EditorGUILayout.Space (SPACE_SUB_BTM_12);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
EditorGUILayout.Space (SPACE_SUB_BTM_12);
|
||||
EditorGUILayout.Space (SPACE_MAIN_BTM_5);
|
||||
EditorGUILayout.Space (SPACE_MAIN_BTM_5);
|
||||
EditorGUI.indentLevel--;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------- Parts
|
||||
private string splitCamelCase (string str) {
|
||||
return Regex.Replace (
|
||||
Regex.Replace (str, @"(\P{Ll})(\P{Ll}\p{Ll})", "$1 $2"), @"(\p{Ll})(\P{Ll})", "$1 $2");
|
||||
}
|
||||
|
||||
private float _indentWidth;
|
||||
private void storeIndentWidth () {
|
||||
if (_indentWidth != 0f) return;
|
||||
var x0 = EditorGUI.IndentedRect (Rect.zero).x;
|
||||
EditorGUI.indentLevel++;
|
||||
_indentWidth = EditorGUI.IndentedRect (Rect.zero).x - x0;
|
||||
EditorGUI.indentLevel--;
|
||||
}
|
||||
|
||||
private void drawBoolAndValue (SerializedProperty propBool, SerializedProperty propValue, bool hide, GUIContent label) {
|
||||
EditorGUILayout.PropertyField (propBool, label);
|
||||
var rect = GUILayoutUtility.GetLastRect ();
|
||||
var labelW = EditorGUIUtility.labelWidth;
|
||||
if (!hide || propBool.boolValue) {
|
||||
using (new DisableScope (propBool.boolValue)) {
|
||||
EditorGUIUtility.labelWidth += 25;
|
||||
EditorGUI.PropertyField (rect, propValue, new GUIContent (" "));
|
||||
}
|
||||
}
|
||||
EditorGUIUtility.labelWidth = labelW;
|
||||
}
|
||||
|
||||
private void selectGameObjectLayer (GUIContent label) {
|
||||
var gameObjects = targets.Select (t => (t as WaterCausticsEffect).gameObject).ToArray ();
|
||||
var layers = gameObjects.Select (go => go.layer).Distinct ().ToArray ();
|
||||
using (var check = new EditorGUI.ChangeCheckScope ()) {
|
||||
EditorGUI.showMixedValue = (layers.Length != 1);
|
||||
int newVal = EditorGUILayout.LayerField (label, layers [0]);
|
||||
EditorGUI.showMixedValue = false;
|
||||
if (check.changed) {
|
||||
Undo.RecordObjects (gameObjects, "Changed Layer");
|
||||
foreach (var go in gameObjects) {
|
||||
go.layer = newVal;
|
||||
EditorUtility.SetDirty (go);
|
||||
}
|
||||
if (layers.Length >= 2 && gameObjects.Length == Selection.objects.Length) {
|
||||
// 上部のレイヤー表示Multiple(-)を更新するため選択中の場合は再選択
|
||||
bool isSelected = true;
|
||||
foreach (var o in gameObjects) {
|
||||
if (!Selection.objects.Contains (o)) {
|
||||
isSelected = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (isSelected) {
|
||||
Selection.activeGameObject = null;
|
||||
EditorApplication.delayCall += () => { Selection.objects = gameObjects; };
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void selectLayer (SerializedProperty prop, GUIContent label) {
|
||||
using (var check = new EditorGUI.ChangeCheckScope ()) {
|
||||
EditorGUI.showMixedValue = prop.hasMultipleDifferentValues;
|
||||
var newVal = EditorGUILayout.LayerField (label, prop.intValue);
|
||||
EditorGUI.showMixedValue = false;
|
||||
if (check.changed)
|
||||
prop.intValue = newVal;
|
||||
}
|
||||
}
|
||||
|
||||
private void drawStartEndProp (SerializedProperty propStt, SerializedProperty propEnd, GUIContent label) {
|
||||
EditorGUILayout.LabelField (label);
|
||||
var rect = GUILayoutUtility.GetLastRect ();
|
||||
rect.x += EditorGUIUtility.labelWidth;
|
||||
rect.width -= EditorGUIUtility.labelWidth;
|
||||
drawStartEndPropInRect (rect, propStt, propEnd);
|
||||
}
|
||||
|
||||
|
||||
private void drawStartEndPropInRect (Rect rect, SerializedProperty propStt, SerializedProperty propEnd) {
|
||||
bool isWide = (rect.width > 140);
|
||||
float span = isWide ? 5f : 3f;
|
||||
var rect2 = rect;
|
||||
var rect3 = rect;
|
||||
rect2.width = rect3.width = (rect.width - span) * 0.5f;
|
||||
rect3.x += rect2.width + span;
|
||||
var storeIndent = EditorGUI.indentLevel;
|
||||
EditorGUI.indentLevel = 0;
|
||||
var labelW = EditorGUIUtility.labelWidth;
|
||||
using (var check = new EditorGUI.ChangeCheckScope ()) {
|
||||
EditorGUI.showMixedValue = propStt.hasMultipleDifferentValues;
|
||||
EditorGUIUtility.labelWidth = isWide? 32 : 10;
|
||||
float newStt = EditorGUI.FloatField (rect2, isWide ? "Start" : "S", propStt.floatValue);
|
||||
if (check.changed)
|
||||
propStt.floatValue = Mathf.Clamp (newStt, 0, propEnd.floatValue);
|
||||
}
|
||||
using (var check = new EditorGUI.ChangeCheckScope ()) {
|
||||
EditorGUI.showMixedValue = propEnd.hasMultipleDifferentValues;
|
||||
EditorGUIUtility.labelWidth = isWide ? 26 : 10;
|
||||
float newEnd = EditorGUI.FloatField (rect3, isWide ? "End" : "E", propEnd.floatValue);
|
||||
if (check.changed)
|
||||
propEnd.floatValue = Mathf.Max (newEnd, propStt.floatValue);
|
||||
}
|
||||
EditorGUI.showMixedValue = false;
|
||||
EditorGUIUtility.labelWidth = labelW;
|
||||
EditorGUI.indentLevel = storeIndent;
|
||||
}
|
||||
|
||||
static private Color colorMulAlpha (Color c, float mulAlpha) => new Color (c.r, c.g, c.b, c.a * mulAlpha);
|
||||
|
||||
private void drawDirMark (SerializedProperty prop, bool isActive = true) {
|
||||
EditorGUI.indentLevel--;
|
||||
var rect = EditorGUI.IndentedRect (GUILayoutUtility.GetLastRect ());
|
||||
drawDirMark (rect, prop, isActive);
|
||||
EditorGUI.indentLevel++;
|
||||
}
|
||||
private void drawDirMark (Rect rect, SerializedProperty prop, bool isActive = true) {
|
||||
rect.width = EditorGUIUtility.labelWidth;
|
||||
Vector2 origin = new Vector2 (CIRCLE_R + 1, rect.height * 0.5f);
|
||||
float dir = prop.floatValue;
|
||||
Handles.color = colorMulAlpha (EditorStyles.label.normal.textColor, isActive ? 0.8f : 0.4f);
|
||||
var tmpMatrix = Handles.matrix;
|
||||
GUI.BeginClip (rect, origin, Vector2.zero, false);
|
||||
Handles.matrix = tmpMatrix * Matrix4x4.Scale (Vector3.one * CIRCLE_R);
|
||||
Handles.DrawAAPolyLine (Texture2D.whiteTexture, 1, circlePts);
|
||||
if (!prop.hasMultipleDifferentValues) {
|
||||
Handles.matrix = tmpMatrix * Matrix4x4.Rotate (Quaternion.Euler (0f, 0f, dir)) * Matrix4x4.Scale (Vector3.one * (CIRCLE_R - 0.5f));
|
||||
Handles.DrawAAConvexPolygon (arrowAry);
|
||||
}
|
||||
Handles.matrix = tmpMatrix;
|
||||
GUI.EndClip ();
|
||||
}
|
||||
|
||||
static private Vector2 dirToVec (float dir) => new Vector2 (Mathf.Sin (dir * Mathf.Deg2Rad), -Mathf.Cos (dir * Mathf.Deg2Rad));
|
||||
const float CIRCLE_R = 5f;
|
||||
static readonly private Vector3 [] arrowAry = {
|
||||
dirToVec (0),
|
||||
dirToVec (150f),
|
||||
dirToVec (170f),
|
||||
dirToVec (-170f),
|
||||
dirToVec (-150f),
|
||||
};
|
||||
static readonly private Vector3 [] circlePts = {
|
||||
new Vector3 (-1f, 0f),
|
||||
new Vector3 (-0.87f, -0.5f),
|
||||
new Vector3 (-0.5f, -0.87f),
|
||||
new Vector3 (0f, -1f),
|
||||
new Vector3 (0.5f, -0.87f),
|
||||
new Vector3 (0.87f, -0.5f),
|
||||
new Vector3 (1f, 0f),
|
||||
new Vector3 (0.87f, 0.5f),
|
||||
new Vector3 (0.5f, 0.87f),
|
||||
new Vector3 (0f, 1f),
|
||||
new Vector3 (-0.5f, 0.87f),
|
||||
new Vector3 (-0.87f, 0.5f),
|
||||
new Vector3 (-1f, 0f),
|
||||
};
|
||||
|
||||
bool isGameObjectOnScene () {
|
||||
return (target as Component).gameObject.scene.IsValid ();
|
||||
}
|
||||
|
||||
private void drawRectMain (bool isPink = false) {
|
||||
Color color = isPink ? colorPinkBar : new Color (0f, 0f, 0f, 0.2f);
|
||||
Rect rect = GUILayoutUtility.GetRect (0, 0);
|
||||
rect.height = lineH;
|
||||
rect.x -= _indentWidth + 4;
|
||||
rect.width += _indentWidth + 8;
|
||||
EditorGUI.DrawRect (rect, color);
|
||||
}
|
||||
|
||||
private bool expandMainGroup (SerializedProperty prop, bool defOpen, string label, bool isPink = false) {
|
||||
EditorGUI.indentLevel--;
|
||||
drawRectMain (isPink);
|
||||
bool expand = isExpand (prop, true, new GUIContent (label));
|
||||
EditorGUI.indentLevel++;
|
||||
return expand;
|
||||
}
|
||||
|
||||
private bool expandSubGroup (SerializedProperty prop, bool defOpen, string label, bool isPink = false) {
|
||||
Color color = isPink ? colorPinkBar : colorMulAlpha (EditorStyles.label.normal.textColor, 0.1f);
|
||||
GUILayout.Label (" ");
|
||||
Rect rect = GUILayoutUtility.GetLastRect ();
|
||||
rect.y += 1f;
|
||||
rect.x += 3f;
|
||||
rect.width -= 3f;
|
||||
Rect rect2 = rect;
|
||||
rect2.x -= 14f;
|
||||
rect2.width += 15f;
|
||||
EditorGUI.DrawRect (rect2, color);
|
||||
GUI.Label (rect, label);
|
||||
if (prop == null) {
|
||||
return true;
|
||||
} else {
|
||||
rect.x -= 14;
|
||||
prop.isExpanded = EditorGUI.Foldout (rect, prop.isExpanded != defOpen, " ") != defOpen;
|
||||
return prop.isExpanded != defOpen;
|
||||
}
|
||||
}
|
||||
|
||||
private void popup (SerializedProperty prop, GUIContent [] enumStr, string text, string tooltip) {
|
||||
using (var check = new EditorGUI.ChangeCheckScope ()) {
|
||||
EditorGUI.showMixedValue = prop.hasMultipleDifferentValues;
|
||||
var newVal = EditorGUILayout.Popup (new GUIContent (text, tooltip), prop.enumValueIndex, enumStr);
|
||||
EditorGUI.showMixedValue = false;
|
||||
if (check.changed)
|
||||
prop.enumValueIndex = newVal;
|
||||
}
|
||||
}
|
||||
|
||||
private void popup (SerializedProperty prop, string [] enumStr, string text, string tooltip) {
|
||||
using (var check = new EditorGUI.ChangeCheckScope ()) {
|
||||
EditorGUI.showMixedValue = prop.hasMultipleDifferentValues;
|
||||
var newVal = EditorGUILayout.Popup (new GUIContent (text, tooltip), prop.enumValueIndex, enumStr);
|
||||
EditorGUI.showMixedValue = false;
|
||||
if (check.changed)
|
||||
prop.enumValueIndex = newVal;
|
||||
}
|
||||
}
|
||||
|
||||
private void bitMask (SerializedProperty prop, string [] options, string text, string tooltip) {
|
||||
using (var check = new EditorGUI.ChangeCheckScope ()) {
|
||||
EditorGUI.showMixedValue = prop.hasMultipleDifferentValues;
|
||||
int newVal = EditorGUILayout.MaskField (new GUIContent (text, tooltip), prop.intValue, options);
|
||||
EditorGUI.showMixedValue = false;
|
||||
if (check.changed) {
|
||||
uint uintVal = unchecked ((uint) newVal);
|
||||
prop.longValue = uintVal;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private bool isExpand (SerializedProperty prop, bool isDefaultOpen, GUIContent label) {
|
||||
prop.isExpanded = EditorGUILayout.Foldout (prop.isExpanded != isDefaultOpen, label) != isDefaultOpen;
|
||||
return prop.isExpanded != isDefaultOpen;
|
||||
}
|
||||
|
||||
private bool isExpandMarkOnly (SerializedProperty prop, bool isDefaultOpen, float adjustX = 0f, float adjustY = 0f) {
|
||||
var rect = GUILayoutUtility.GetLastRect ();
|
||||
prop.isExpanded = EditorGUI.Foldout (rect, prop.isExpanded != isDefaultOpen, " ") != isDefaultOpen;
|
||||
return prop.isExpanded != isDefaultOpen;
|
||||
}
|
||||
|
||||
private void drawLine () {
|
||||
Rect r = GUILayoutUtility.GetRect (0, 0);
|
||||
Color col = colorMulAlpha (EditorStyles.label.normal.textColor, 0.09f);
|
||||
EditorGUI.DrawRect (new Rect (r.x + 14f, r.y, r.width - 14f, 1f), col);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------- Scope
|
||||
private class AdjustLabelSpaceWidthScope : GUI.Scope {
|
||||
private readonly float _store;
|
||||
internal AdjustLabelSpaceWidthScope (float adjust) {
|
||||
_store = EditorGUIUtility.labelWidth;
|
||||
EditorGUIUtility.labelWidth += adjust;
|
||||
}
|
||||
protected override void CloseScope () {
|
||||
EditorGUIUtility.labelWidth = _store;
|
||||
}
|
||||
}
|
||||
|
||||
private class LabelAndIndentScope : GUI.Scope {
|
||||
private float _spaceBtm;
|
||||
internal LabelAndIndentScope (GUIContent label, float spaceTop = 0f, float spaceMid = 2f, float spaceBtm = 0f) {
|
||||
_spaceBtm = spaceBtm;
|
||||
EditorGUILayout.Space (spaceTop);
|
||||
EditorGUILayout.LabelField (label);
|
||||
EditorGUILayout.Space (spaceMid);
|
||||
EditorGUI.indentLevel++;
|
||||
}
|
||||
protected override void CloseScope () {
|
||||
EditorGUI.indentLevel--;
|
||||
EditorGUILayout.Space (_spaceBtm);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private class IndentScope : GUI.Scope {
|
||||
private float _spaceBtm;
|
||||
private int _indent;
|
||||
internal IndentScope (float spaceTop = 3f, float spaceBtm = 10f, int indent = 1) {
|
||||
_spaceBtm = spaceBtm;
|
||||
_indent = indent;
|
||||
EditorGUILayout.Space (spaceTop);
|
||||
EditorGUI.indentLevel += indent;
|
||||
}
|
||||
protected override void CloseScope () {
|
||||
EditorGUI.indentLevel -= _indent;
|
||||
EditorGUILayout.Space (_spaceBtm);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private class DisableScope : GUI.Scope {
|
||||
private readonly bool _tmp;
|
||||
internal DisableScope (bool isActive = false) {
|
||||
_tmp = isActive;
|
||||
if (!_tmp) EditorGUI.BeginDisabledGroup (true);
|
||||
}
|
||||
protected override void CloseScope () {
|
||||
if (!_tmp) EditorGUI.EndDisabledGroup ();
|
||||
}
|
||||
}
|
||||
|
||||
private class ColorScope : GUI.Scope {
|
||||
private readonly Color _tmp;
|
||||
internal ColorScope (Color color) {
|
||||
_tmp = GUI.color;
|
||||
GUI.color = color;
|
||||
}
|
||||
protected override void CloseScope () {
|
||||
GUI.color = _tmp;
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------- URPパッケージは在るけれど 設定が完了していない場合
|
||||
private bool isDark => EditorGUIUtility.isProSkin;
|
||||
private GUIStyle _textStyle, _linkUrlStyle, _warningStyle;
|
||||
|
||||
private void prepStyle () {
|
||||
if (_textStyle == null) {
|
||||
_textStyle = new GUIStyle (EditorStyles.label);
|
||||
_textStyle.wordWrap = true;
|
||||
_textStyle.fontSize = 14;
|
||||
|
||||
_linkUrlStyle = new GUIStyle (_textStyle);
|
||||
_linkUrlStyle.wordWrap = false;
|
||||
_linkUrlStyle.normal.textColor = isDark ? new Color (0f, 0.8f, 1f, 1f) : new Color (0f, 0.4f, 0.8f, 1f);
|
||||
_linkUrlStyle.hover.textColor = _linkUrlStyle.normal.textColor + Color.white * (isDark ? 0.3f : 0.2f);
|
||||
_linkUrlStyle.stretchWidth = false;
|
||||
|
||||
_warningStyle = new GUIStyle (_textStyle);
|
||||
_warningStyle.normal.textColor = isDark ? Color.white : new Color (0.8f, 0.1f, 0f, 1f);
|
||||
_warningStyle.normal.background = Texture2D.whiteTexture;
|
||||
}
|
||||
}
|
||||
|
||||
private void onInspectorGUI_NotSettingYet () {
|
||||
prepStyle ();
|
||||
storeIndentWidth ();
|
||||
EditorGUILayout.Space (50);
|
||||
labelWarning ($"UniversalRP setup is not completed.");
|
||||
EditorGUILayout.Space (10);
|
||||
GUILayout.Label ($"Please refer to the Unity manual page to setup, or create a new project with the URP 3D template.", _textStyle);
|
||||
EditorGUILayout.Space (10);
|
||||
var urlA = "https://docs.unity3d.com/Packages/com.unity.render-pipelines.universal@12.0/manual/InstallURPIntoAProject.html";
|
||||
if (labelLink (new GUIContent ("Unity URP Setup Manual", urlA)))
|
||||
Application.OpenURL (urlA);
|
||||
EditorGUILayout.Space (5);
|
||||
var urlB = Constant.URL_MANUAL;
|
||||
if (labelLink (new GUIContent ("Asset Manual", urlB)))
|
||||
Application.OpenURL (urlB);
|
||||
EditorGUILayout.Space (50);
|
||||
}
|
||||
|
||||
void labelWarning (string text, int fontSize = 18) {
|
||||
prepStyle ();
|
||||
_warningStyle.fontSize = fontSize;
|
||||
Color tmp = GUI.backgroundColor;
|
||||
GUI.backgroundColor = isDark ? new Color (1f, 0.3f, 0.6f, 0.4f) : new Color (1f, 0.3f, 0.6f, 0.5f);
|
||||
GUILayout.Label (text, _warningStyle);
|
||||
GUI.backgroundColor = tmp;
|
||||
}
|
||||
|
||||
private bool labelLink (GUIContent label, int fontSize = 14, int indent = 0, params GUILayoutOption [] options) {
|
||||
prepStyle ();
|
||||
_linkUrlStyle.fontSize = fontSize;
|
||||
var rect = GUILayoutUtility.GetRect (label, _linkUrlStyle, options);
|
||||
rect.x += indent * _indentWidth;
|
||||
Handles.BeginGUI ();
|
||||
Handles.color = _linkUrlStyle.normal.textColor;
|
||||
Handles.DrawLine (new Vector3 (rect.xMin, rect.yMax), new Vector3 (rect.xMax, rect.yMax));
|
||||
Handles.color = Color.white;
|
||||
Handles.EndGUI ();
|
||||
EditorGUIUtility.AddCursorRect (rect, MouseCursor.Link);
|
||||
return GUI.Button (rect, label, _linkUrlStyle);
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif // End of WCE_URP
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 5998e4477e64d9b47a7297a804fff2ab
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,207 @@
|
||||
// WaterCausticsModules
|
||||
// Copyright (c) 2021 Masataka Hakozaki
|
||||
|
||||
#if UNITY_EDITOR && WCE_URP
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Rendering;
|
||||
using UnityEngine.Rendering.Universal;
|
||||
|
||||
namespace MH.WaterCausticsModules {
|
||||
[CustomEditor (typeof (WaterCausticsEffectFeature), true)]
|
||||
public class WaterCausticsEffectFeatureEditor : Editor {
|
||||
private GUIStyle _style;
|
||||
private void init () {
|
||||
_style = new GUIStyle (EditorStyles.label);
|
||||
_style.wordWrap = true;
|
||||
_style.fontSize -= 1;
|
||||
}
|
||||
public override void OnInspectorGUI () {
|
||||
if (_style == null) init ();
|
||||
EditorGUILayout.Space (10);
|
||||
string str = "This Renderer Function is required to apply WaterCausticsEffect.";
|
||||
GUILayout.Label (str, _style);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------
|
||||
// static internal bool AddToCurrentRendererData (bool useUndo) {
|
||||
// if (GetCurrentRendererData (out var dt))
|
||||
// return AddFeatureToRenderer (dt, useUndo);
|
||||
// return false;
|
||||
// }
|
||||
|
||||
// static internal bool GetCurrentRendererData (out ScriptableRendererData dt) {
|
||||
// dt = null;
|
||||
// try {
|
||||
// var urpAsset = GraphicsSettings.currentRenderPipeline as UniversalRenderPipelineAsset;
|
||||
// var propertyInfo = typeof (UniversalRenderPipelineAsset).GetProperty ("scriptableRendererData", System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic);
|
||||
// if (propertyInfo == null) return false;
|
||||
// dt = propertyInfo.GetValue (urpAsset) as ScriptableRendererData;
|
||||
// return dt != null;
|
||||
// } catch { }
|
||||
// return false;
|
||||
// }
|
||||
|
||||
|
||||
public class ModificationProcessor : UnityEditor.AssetModificationProcessor {
|
||||
// WaterCausticsEffectFeatureスクリプトが削除されるとき、登録済みのRendererFeatureを削除
|
||||
// ※フォルダ削除時、中身のパスは渡されないので注意
|
||||
private static AssetDeleteResult OnWillDeleteAsset (string deletePath, RemoveAssetOptions options) {
|
||||
bool isDirectory = File.GetAttributes (deletePath).HasFlag (FileAttributes.Directory);
|
||||
string scriptPath = getScriptPath<WaterCausticsEffectFeature> ();
|
||||
if ((isDirectory && scriptPath.StartsWith (deletePath)) || deletePath == scriptPath) {
|
||||
// RendererFeatureを削除
|
||||
DeleteAllFeatures ();
|
||||
}
|
||||
return AssetDeleteResult.DidNotDelete;
|
||||
}
|
||||
}
|
||||
|
||||
static private string getScriptPath<T> () where T : ScriptableObject {
|
||||
T asset = ScriptableObject.CreateInstance<T> ();
|
||||
MonoScript mono = MonoScript.FromScriptableObject (asset);
|
||||
string path = AssetDatabase.GetAssetPath (mono);
|
||||
if (Application.isPlaying) Destroy (asset);
|
||||
else DestroyImmediate (asset);
|
||||
return path;
|
||||
}
|
||||
|
||||
#if WCE_DEVELOPMENT
|
||||
[MenuItem ("WCM/RendererFeatureTest/DeleteAllFeatures")]
|
||||
#endif
|
||||
static internal void DeleteAllFeatures () {
|
||||
if (GetAllRendererData (out var list))
|
||||
foreach (var dt in list)
|
||||
DeleteFeature (dt);
|
||||
}
|
||||
|
||||
static internal void DeleteFeature (ScriptableRendererData dt) {
|
||||
if (!dt) return;
|
||||
try {
|
||||
// ※ TODO URPのバージョンが上がるたび処理方法に変更がないか要確認
|
||||
if (dt.rendererFeatures.Any (a => a is WaterCausticsEffectFeature)) {
|
||||
if (!EditorUtility.IsPersistent (dt)) return;
|
||||
var feature = dt.rendererFeatures.FirstOrDefault (a => a is WaterCausticsEffectFeature);
|
||||
AssetDatabase.RemoveObjectFromAsset (feature);
|
||||
dt.rendererFeatures.Remove (feature);
|
||||
dt.SetDirty ();
|
||||
EditorUtility.SetDirty (dt);
|
||||
saveAssetSafe (dt);
|
||||
}
|
||||
} catch { }
|
||||
}
|
||||
|
||||
static private void saveAssetSafe (Object o) {
|
||||
// ※AssetDatabase.SaveAssetIfDirty は Unity 2021.1.17、2020.3.16で追加されたので分岐
|
||||
#if !UNITY_2020_3_OR_NEWER || UNITY_2020_3_0 || UNITY_2020_3_1 || UNITY_2020_3_2 || UNITY_2020_3_3 || UNITY_2020_3_4 || UNITY_2020_3_5 || UNITY_2020_3_6 || UNITY_2020_3_7 || UNITY_2020_3_8 || UNITY_2020_3_9 || UNITY_2020_3_10 || UNITY_2020_3_11 || UNITY_2020_3_12 || UNITY_2020_3_13 || UNITY_2020_3_14 || UNITY_2020_3_15 || UNITY_2021_1
|
||||
AssetDatabase.SaveAssets ();
|
||||
#else
|
||||
AssetDatabase.SaveAssetIfDirty (o);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
static internal bool AddFeatureToRenderer (ScriptableRendererData dt, bool useUndo) {
|
||||
if (!dt) return false;
|
||||
try {
|
||||
if (dt.rendererFeatures.Any (a => a is WaterCausticsEffectFeature)) {
|
||||
// -- すでにある場合 アクティブ化
|
||||
var feature = dt.rendererFeatures.FirstOrDefault (a => a is WaterCausticsEffectFeature) as WaterCausticsEffectFeature;
|
||||
//if (!feature.isActive) {
|
||||
//if (useUndo) Undo.RegisterCompleteObjectUndo (feature, "Feature Set Active");
|
||||
//feature.SetActive (true);
|
||||
//EditorUtility.SetDirty (feature);
|
||||
//saveAssetSafe (dt);
|
||||
//}
|
||||
WaterCausticsEffectFeature.OnAddedByScript ();
|
||||
return true;
|
||||
} else {
|
||||
// -- まだ無い場合
|
||||
// ※ TODO URPのバージョンが上がるたび処理方法に変更がないか要確認 10.9, 12.1, 14.0 OK
|
||||
if (!EditorUtility.IsPersistent (dt)) return false;
|
||||
var validateMethod = dt.GetType ().GetMethod ("ValidateRendererFeatures", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance);
|
||||
if (validateMethod == null) return false;
|
||||
var feature = ScriptableRendererFeature.CreateInstance<WaterCausticsEffectFeature> ();
|
||||
feature.name = typeof (WaterCausticsEffect).Name;
|
||||
if (useUndo) {
|
||||
Undo.RegisterCreatedObjectUndo (feature, "Add Renderer Feature");
|
||||
Undo.RegisterCompleteObjectUndo (dt, "Add Renderer Feature");
|
||||
}
|
||||
AssetDatabase.AddObjectToAsset (feature, dt);
|
||||
dt.rendererFeatures.Add (feature);
|
||||
validateMethod.Invoke (dt, null);
|
||||
dt.SetDirty ();
|
||||
EditorUtility.SetDirty (dt);
|
||||
saveAssetSafe (dt);
|
||||
WaterCausticsEffectFeature.OnAddedByScript ();
|
||||
return true;
|
||||
}
|
||||
} catch { }
|
||||
return false;
|
||||
}
|
||||
|
||||
static internal bool CheckAllHasActiveFeature (List<ScriptableRendererData> list) {
|
||||
return list != null && !list.Any (a => checkHasActiveFeature (a) == false);
|
||||
}
|
||||
|
||||
static internal bool checkHasActiveFeature (ScriptableRendererData dt) {
|
||||
return dt != null && dt.rendererFeatures.Any (a => a is WaterCausticsEffectFeature && a.isActive);
|
||||
}
|
||||
|
||||
static internal bool AddFeatureToAllRenderers (out List<ScriptableRendererData> list, bool useUndo) {
|
||||
if (GetAllRendererData (out list))
|
||||
return AddFeatureToAllRenderers (list, useUndo);
|
||||
return false;
|
||||
}
|
||||
|
||||
#if WCE_DEVELOPMENT
|
||||
[MenuItem ("WCM/RendererFeatureTest/AddFeatureToAllRenderers")]
|
||||
#endif
|
||||
static internal bool AddFeatureToAllRenderers () {
|
||||
return AddFeatureToAllRenderers (useUndo: true);
|
||||
|
||||
}
|
||||
static internal bool AddFeatureToAllRenderers (bool useUndo) {
|
||||
if (GetAllRendererData (out var list))
|
||||
return AddFeatureToAllRenderers (list, useUndo);
|
||||
return false;
|
||||
}
|
||||
|
||||
static internal bool AddFeatureToAllRenderers (List<ScriptableRendererData> list, bool useUndo) {
|
||||
if (list == null) return false;
|
||||
bool result = true;
|
||||
foreach (var dt in list)
|
||||
result &= AddFeatureToRenderer (dt, useUndo);
|
||||
return result;
|
||||
}
|
||||
|
||||
static internal bool GetAllRendererData (out List<ScriptableRendererData> list) {
|
||||
list = new List<ScriptableRendererData> ();
|
||||
var guids = AssetDatabase.FindAssets ($"t:{typeof(ScriptableRendererData).ToString()}", new [] { "Assets" });
|
||||
if (guids.Length == 0) return false;
|
||||
foreach (var guid in guids) {
|
||||
var dt = AssetDatabase.LoadAssetAtPath<ScriptableRendererData> (AssetDatabase.GUIDToAssetPath (guid));
|
||||
list.Add (dt);
|
||||
}
|
||||
return list.Count != 0;
|
||||
}
|
||||
|
||||
static internal void SelectAndPing (List<ScriptableRendererData> list) {
|
||||
Selection.objects = list.ToArray ();
|
||||
foreach (var dt in list) EditorGUIUtility.PingObject (dt);
|
||||
}
|
||||
|
||||
static internal string AssetsToPathStr (List<ScriptableRendererData> list) {
|
||||
var str = "";
|
||||
for (int i = 0; i < list.Count; i++)
|
||||
str += $"{i+1}: {AssetDatabase.GetAssetPath (list [i])}\n";
|
||||
return str;
|
||||
}
|
||||
//------------------------------------------------------------------------
|
||||
}
|
||||
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: d8b3f56e6e68f2d4fbdf5ad470a2fa4d
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,48 @@
|
||||
// WaterCausticsModules
|
||||
// Copyright (c) 2021 Masataka Hakozaki
|
||||
|
||||
#if UNITY_EDITOR && WCE_URP
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
|
||||
namespace MH.WaterCausticsModules {
|
||||
public class WaterCausticsEffectMenuItem {
|
||||
[MenuItem ("GameObject/WaterCausticsModules/TexGen and Effect (with RenderTexture Asset)", false, 0)]
|
||||
static public void CreateTexGenAndEffectPair () {
|
||||
var texGen = WaterCausticsTexGeneratorMenuItem.CreateTexGeneratorWithRT ();
|
||||
var effect = createEffectGO ();
|
||||
effect.texture = texGen.renderTexture;
|
||||
}
|
||||
|
||||
[MenuItem ("GameObject/WaterCausticsModules/Effect", false, 3)]
|
||||
static public void CreateEffectGO () {
|
||||
GameObject selectedGO = Selection.activeGameObject;
|
||||
var effect = createEffectGO ();
|
||||
var texGen = selectedGO?.GetComponent<WaterCausticsTexGenerator> ();
|
||||
if (texGen == null)
|
||||
texGen = Object.FindObjectOfType<WaterCausticsTexGenerator> ();
|
||||
if (texGen != null)
|
||||
effect.texture = texGen.renderTexture;
|
||||
}
|
||||
|
||||
static private WaterCausticsEffect createEffectGO () {
|
||||
var go = new GameObject ("WaterCausticsEffect");
|
||||
Undo.RegisterCreatedObjectUndo (go, "Create WaterCausticsEffect");
|
||||
var tra = go.transform;
|
||||
if (Selection.activeGameObject != null) {
|
||||
var baseTra = Selection.activeGameObject.transform;
|
||||
tra.parent = baseTra.parent;
|
||||
tra.SetSiblingIndex (baseTra.GetSiblingIndex () + 1);
|
||||
}
|
||||
tra.localPosition = Vector3.zero;
|
||||
tra.localRotation = Quaternion.identity;
|
||||
tra.localScale = Vector3.one * 3f;
|
||||
Selection.activeObject = go;
|
||||
Selection.activeObject = null;
|
||||
Selection.activeObject = go;
|
||||
return go.AddComponent<WaterCausticsEffect> ();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: cde63416afd7d524cb16551f6e60fa41
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,15 @@
|
||||
fileFormatVersion: 2
|
||||
guid: e975b56feadc05a4a9da076c953ae619
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences:
|
||||
- m_imageMaskTexture: {fileID: 2800000, guid: f88b6df342d5c4f4a969fb6eb4799d3e, type: 3}
|
||||
- m_texture: {instanceID: 0}
|
||||
- m_shader: {fileID: 4800000, guid: 348afebc23c3c6e4c8f05f2ea8f758fc, type: 3}
|
||||
- m_noTexture: {fileID: 2800000, guid: 27623e5a17b6fd44a9af57a733ee993a, type: 3}
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,49 @@
|
||||
// WaterCausticsModules
|
||||
// Copyright (c) 2021 Masataka Hakozaki
|
||||
|
||||
#if WCE_URP
|
||||
using System;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Rendering.Universal;
|
||||
|
||||
namespace MH.WaterCausticsModules {
|
||||
/*------------------------------------------------------------------------
|
||||
This RendererFeature is used to stably apply WaterCausticsEffect to cameras
|
||||
created by other effects.
|
||||
For example, a mirror or water reflection effect may use a temporary camera
|
||||
that is not placed in the scene, and the effect cannot be applied stably.
|
||||
In that case, register this RendererFeature to the RendererData Asset.
|
||||
The effect will be applied stably to all cameras.
|
||||
|
||||
このRendererFeatureは、他のエフェクトで作成されたカメラへWaterCausticsEffect
|
||||
を安定的に適用するために使用します。
|
||||
鏡や水面の反射エフェクトなどではシーンに配置されない一時的なカメラを使用する
|
||||
場合があり、安定してエフェクトを適用出来ません。その場合はこの RendererFeature
|
||||
を RendererData Asset に登録して下さい。安定してエフェクトが適用されるように
|
||||
なります。
|
||||
-------------------------------------------------------------------------*/
|
||||
|
||||
#if UNITY_2021_2_OR_NEWER
|
||||
[DisallowMultipleRendererFeature ("WaterCausticsEffect (Renderer Feature)")]
|
||||
#elif WCE_URP_10_8
|
||||
[DisallowMultipleRendererFeature]
|
||||
#endif
|
||||
[HelpURL (Constant.URL_MANUAL)]
|
||||
public class WaterCausticsEffectFeature : ScriptableRendererFeature {
|
||||
static private WaterCausticsEffectFeature s_ins;
|
||||
static public event Action<Camera> onCamRender;
|
||||
static public event Action<ScriptableRenderer, Camera> onEnqueue;
|
||||
static private int s_lastFrame;
|
||||
static internal bool effective => (s_ins != null && s_ins.isActive && s_lastFrame >= Time.renderedFrameCount - 1);
|
||||
static internal void OnAddedByScript () => s_lastFrame = Time.renderedFrameCount;
|
||||
public override void Create () { }
|
||||
public override void AddRenderPasses (ScriptableRenderer renderer, ref RenderingData rendData) {
|
||||
s_ins = this;
|
||||
s_lastFrame = Time.renderedFrameCount;
|
||||
var cam = rendData.cameraData.camera;
|
||||
onCamRender?.Invoke (cam);
|
||||
onEnqueue?.Invoke (renderer, cam);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 63239fdff9bcf7545bae0204cba6eb96
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
Reference in New Issue
Block a user