Modify: 닐로툰 스크립트 최신버전으로 업데이트
This commit is contained in:
parent
0405f6ccf0
commit
85a03a3cbe
@ -96,16 +96,12 @@ namespace MagicaCloth2
|
||||
|
||||
//=========================================================================================
|
||||
[MenuItem("Tools/Magica Cloth2/Manager information", false)]
|
||||
static void DispClothManagerInfo()
|
||||
static async void DispClothManagerInfo()
|
||||
{
|
||||
if (MagicaManager.IsPlaying() == false)
|
||||
{
|
||||
Debug.Log("This feature is run-time only.");
|
||||
return;
|
||||
}
|
||||
|
||||
StringBuilder allsb = new StringBuilder();
|
||||
|
||||
await ClothEditorManager.InformationLog(allsb);
|
||||
|
||||
var timeManager = MagicaManager.Time;
|
||||
if (timeManager == null)
|
||||
{
|
||||
@ -186,8 +182,15 @@ namespace MagicaCloth2
|
||||
renderManager.InformationLog(allsb);
|
||||
}
|
||||
|
||||
// clipboard
|
||||
//GUIUtility.systemCopyBuffer = allsb.ToString();
|
||||
var preBuildManager = MagicaManager.PreBuild;
|
||||
if (preBuildManager == null)
|
||||
{
|
||||
Debug.LogWarning("PreBuild Manager is null!");
|
||||
}
|
||||
else
|
||||
{
|
||||
preBuildManager.InformationLog(allsb);
|
||||
}
|
||||
|
||||
// file
|
||||
DateTime dt = DateTime.Now;
|
||||
@ -197,5 +200,24 @@ namespace MagicaCloth2
|
||||
sw.Flush();
|
||||
sw.Close();
|
||||
}
|
||||
|
||||
//=========================================================================================
|
||||
// インスペクターのコンテキストメニュー
|
||||
[MenuItem("CONTEXT/MagicaCloth/Rebuild InitData")]
|
||||
private static void SampleMenu(MenuCommand menuCommand)
|
||||
{
|
||||
// 初期化データをクリアして再構築する
|
||||
var cloth = menuCommand.context as MagicaCloth;
|
||||
if (cloth)
|
||||
{
|
||||
cloth.GetSerializeData2().initData.Clear();
|
||||
EditorUtility.SetDirty(cloth);
|
||||
|
||||
// 編集用メッシュの再構築
|
||||
ClothEditorManager.RegisterComponent(cloth, GizmoType.Active, true); // 強制更新
|
||||
|
||||
Develop.Log($"[{cloth.name}] Initialization data rebuilt.");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
// Magica Cloth 2.
|
||||
// Copyright (c) 2023 MagicaSoft.
|
||||
// https://magicasoft.jp
|
||||
using Unity.Mathematics;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
|
||||
@ -10,6 +11,7 @@ namespace MagicaCloth2
|
||||
{
|
||||
// ギズモカラー定義
|
||||
public static readonly Color ColorCollider = new Color(0.0f, 1.0f, 0.0f);
|
||||
public static readonly Color ColorSymmetryCollider = new Color(0.0f, 1.0f, 1.0f);
|
||||
public static readonly Color ColorNonSelectedCollider = new Color(0.5f, 0.3f, 0.0f);
|
||||
public static readonly Color ColorSkinningBone = new Color(1.0f, 0.5f, 0.0f);
|
||||
public static readonly Color ColorWindZone = new Color(1f, 1f, 1f);
|
||||
@ -162,56 +164,142 @@ namespace MagicaCloth2
|
||||
}
|
||||
|
||||
//=========================================================================================
|
||||
public static void DrawCollider(ColliderComponent collider, Quaternion camRot, bool useHandles, bool selected)
|
||||
public static void DrawCollider(ColliderComponent collider, Quaternion camRot, bool selected)
|
||||
{
|
||||
if (collider == null)
|
||||
return;
|
||||
|
||||
var cpos = collider.transform.TransformPoint(collider.center);
|
||||
var crot = collider.transform.rotation;
|
||||
var cscl = Vector3.one * collider.GetScale(); // スケールはx軸のみ(つまり均等スケールのみ)
|
||||
Handles.color = selected ? ColorCollider : ColorCollider * 0.5f;
|
||||
|
||||
// Main
|
||||
var ct = collider.transform;
|
||||
//var cpos = ct.TransformPoint(collider.center);
|
||||
float3 cpos = ct.position;
|
||||
quaternion crot = ct.rotation;
|
||||
float3 cscl = ct.lossyScale;
|
||||
// マイナススケール
|
||||
float3 sclSign = math.sign(cscl);
|
||||
// オフセット
|
||||
cpos += math.mul(crot, collider.center * sclSign) * cscl * sclSign;
|
||||
// カメラ回転をコライダーのローカル回転に変換
|
||||
camRot = Quaternion.Inverse(crot) * camRot;
|
||||
var camRotN = Quaternion.Inverse(crot) * camRot;
|
||||
DrawColliderInternal(collider, camRotN, cpos, crot, cscl, 1.0f);
|
||||
|
||||
// サイズ
|
||||
var size = collider.GetSize();
|
||||
|
||||
if (useHandles)
|
||||
// Symmetry
|
||||
// 実行時と同じ計算をして表示
|
||||
ColliderSymmetryMode? smode = ColliderSymmetryMode.None;
|
||||
Transform symmetryParent = null;
|
||||
if (EditorApplication.isPlaying)
|
||||
{
|
||||
Handles.matrix = Matrix4x4.TRS(cpos, crot, cscl);
|
||||
Handles.color = selected ? ColorCollider : ColorCollider * 0.5f;
|
||||
switch (collider.GetColliderType())
|
||||
{
|
||||
case ColliderManager.ColliderType.Sphere:
|
||||
DrawWireSphere(Vector3.zero, Quaternion.identity, size.x, camRot, true);
|
||||
break;
|
||||
case ColliderManager.ColliderType.CapsuleX_Center:
|
||||
DrawWireCapsule(Vector3.zero, Quaternion.identity, Vector3.right, Vector3.up, size.x, size.y, size.z, true, camRot, true);
|
||||
break;
|
||||
case ColliderManager.ColliderType.CapsuleY_Center:
|
||||
DrawWireCapsule(Vector3.zero, Quaternion.identity, Vector3.up, Vector3.right, size.x, size.y, size.z, true, camRot, true);
|
||||
break;
|
||||
case ColliderManager.ColliderType.CapsuleZ_Center:
|
||||
DrawWireCapsule(Vector3.zero, Quaternion.identity, Vector3.forward, Vector3.up, size.x, size.y, size.z, true, camRot, true);
|
||||
break;
|
||||
case ColliderManager.ColliderType.CapsuleX_Start:
|
||||
DrawWireCapsule(Vector3.zero, Quaternion.identity, Vector3.right, Vector3.up, size.x, size.y, size.z, false, camRot, true);
|
||||
break;
|
||||
case ColliderManager.ColliderType.CapsuleY_Start:
|
||||
DrawWireCapsule(Vector3.zero, Quaternion.identity, Vector3.up, Vector3.right, size.x, size.y, size.z, false, camRot, true);
|
||||
break;
|
||||
case ColliderManager.ColliderType.CapsuleZ_Start:
|
||||
DrawWireCapsule(Vector3.zero, Quaternion.identity, Vector3.forward, Vector3.up, size.x, size.y, size.z, false, camRot, true);
|
||||
break;
|
||||
case ColliderManager.ColliderType.Plane:
|
||||
DrawWireCube(Vector3.zero, Quaternion.identity, new Vector3(1.0f, 0.0f, 1.0f) * 1.0f, true);
|
||||
break;
|
||||
}
|
||||
smode = collider.ActiveSymmetryMode;
|
||||
symmetryParent = collider.ActiveSymmetryTarget;
|
||||
}
|
||||
else
|
||||
if (smode.HasValue == false || smode == ColliderSymmetryMode.None)
|
||||
smode = collider.CalcSymmetryMode(out symmetryParent);
|
||||
if (smode != ColliderSymmetryMode.None && symmetryParent)
|
||||
{
|
||||
float3 lpos = ct.localPosition;
|
||||
//float3 lerot = ct.localEulerAngles;
|
||||
float3 lerot = MathUtility.ToEuler(ct.localRotation);
|
||||
float3 lscl = ct.localScale;
|
||||
float3 center = collider.center;
|
||||
switch (smode)
|
||||
{
|
||||
case ColliderSymmetryMode.X_Symmetry:
|
||||
lpos.x = -lpos.x;
|
||||
center.x = -center.x;
|
||||
lerot.y = -lerot.y;
|
||||
lerot.z = -lerot.z;
|
||||
break;
|
||||
case ColliderSymmetryMode.Y_Symmetry:
|
||||
lpos.y = -lpos.y;
|
||||
center.y = -center.y;
|
||||
lerot.x = -lerot.x;
|
||||
lerot.z = -lerot.z;
|
||||
break;
|
||||
case ColliderSymmetryMode.Z_Symmetry:
|
||||
lpos.z = -lpos.z;
|
||||
center.z = -center.z;
|
||||
lerot.x = -lerot.x;
|
||||
lerot.y = -lerot.y;
|
||||
break;
|
||||
case ColliderSymmetryMode.XYZ_Symmetry:
|
||||
lpos = -lpos;
|
||||
center = -center;
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
// 方向性
|
||||
float direction = 1.0f;
|
||||
if (collider is MagicaCapsuleCollider)
|
||||
{
|
||||
var ccol = collider as MagicaCapsuleCollider;
|
||||
if (smode == ColliderSymmetryMode.X_Symmetry && ccol.direction == MagicaCapsuleCollider.Direction.X)
|
||||
direction = -1.0f;
|
||||
else if (smode == ColliderSymmetryMode.Y_Symmetry && ccol.direction == MagicaCapsuleCollider.Direction.Y)
|
||||
direction = -1.0f;
|
||||
else if (smode == ColliderSymmetryMode.Z_Symmetry && ccol.direction == MagicaCapsuleCollider.Direction.Z)
|
||||
direction = -1.0f;
|
||||
else if (smode == ColliderSymmetryMode.XYZ_Symmetry)
|
||||
direction = -1.0f;
|
||||
}
|
||||
else if (collider is MagicaPlaneCollider)
|
||||
{
|
||||
switch (smode)
|
||||
{
|
||||
case ColliderSymmetryMode.Y_Symmetry:
|
||||
case ColliderSymmetryMode.XYZ_Symmetry:
|
||||
direction = -1.0f;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// シンメトリーの親
|
||||
float3 ppos = symmetryParent.position;
|
||||
quaternion prot = symmetryParent.rotation;
|
||||
float3 pscl = symmetryParent.lossyScale;
|
||||
|
||||
// マイナススケール
|
||||
sclSign = math.sign(pscl);
|
||||
float3 sclEulerSign = 1;
|
||||
if (pscl.x < 0 || pscl.y < 0 || pscl.z < 0)
|
||||
sclEulerSign = sclSign * -1;
|
||||
|
||||
// シンメトリーコライダーの姿勢
|
||||
float3 wpos = MathUtility.TransformPoint(lpos, ppos, prot, pscl);
|
||||
quaternion wrot = math.mul(prot, quaternion.Euler(math.radians(lerot * sclEulerSign)));
|
||||
float3 wscl = pscl * lscl;
|
||||
wpos += math.mul(wrot, center * sclSign) * wscl * sclSign;
|
||||
|
||||
// カメラ回転をコライダーのローカル回転に変換
|
||||
var camRotS = Quaternion.Inverse(wrot) * camRot;
|
||||
|
||||
Handles.color = selected ? ColorSymmetryCollider : ColorSymmetryCollider * 0.5f;
|
||||
DrawColliderInternal(collider, camRotS, wpos, wrot, wscl, direction);
|
||||
}
|
||||
}
|
||||
|
||||
static void DrawColliderInternal(ColliderComponent collider, Quaternion camRot, Vector3 cpos, Quaternion crot, Vector3 cscl, float direction)
|
||||
{
|
||||
var size = collider.GetSize();
|
||||
Handles.matrix = Matrix4x4.TRS(cpos, crot, cscl);
|
||||
if (collider is MagicaSphereCollider)
|
||||
{
|
||||
DrawWireSphere(Vector3.zero, Quaternion.identity, size.x, camRot, true);
|
||||
}
|
||||
else if (collider is MagicaPlaneCollider)
|
||||
{
|
||||
DrawWireCube(Vector3.zero, Quaternion.identity, new Vector3(1.0f, 0.0f, 1.0f) * 1.0f, true);
|
||||
DrawLine(Vector3.zero, Vector3.up * 0.25f * direction, true);
|
||||
}
|
||||
else if (collider is MagicaCapsuleCollider)
|
||||
{
|
||||
var c = collider as MagicaCapsuleCollider;
|
||||
var ldir = c.GetLocalDir() * direction;
|
||||
var lup = c.GetLocalUp();
|
||||
DrawWireCapsule(Vector3.zero, Quaternion.identity, ldir, lup, size.x, size.y, size.z, c.alignedOnCenter, camRot, true);
|
||||
}
|
||||
}
|
||||
|
||||
@ -300,23 +388,6 @@ namespace MagicaCloth2
|
||||
Gizmos.matrix = Matrix4x4.identity;
|
||||
}
|
||||
|
||||
//public static void DrawWireSphere(
|
||||
// Vector3 pos, Quaternion rot, Vector3 scl, float radius,
|
||||
// Quaternion camRot, bool useHandles
|
||||
// )
|
||||
//{
|
||||
// if(useHandles)
|
||||
// {
|
||||
// Handles.matrix = Matrix4x4.TRS(pos, rot, scl);
|
||||
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
|
||||
// }
|
||||
//}
|
||||
|
||||
|
||||
#if false
|
||||
/// <summary>
|
||||
/// ワイヤーボックスを描画する
|
||||
|
||||
BIN
Assets/External/NiloToonURP/CHANGELOG.md
(Stored with Git LFS)
vendored
BIN
Assets/External/NiloToonURP/CHANGELOG.md
(Stored with Git LFS)
vendored
Binary file not shown.
@ -10,7 +10,8 @@ namespace NiloToon.NiloToonURP
|
||||
{
|
||||
public class NiloToonEditor_AutoGeneratePrefabVariantAndAssets : Editor
|
||||
{
|
||||
[MenuItem("Window/NiloToonURP/Create Nilo Prefab Variant and Materials", priority = 0)]
|
||||
[MenuItem("Window/NiloToonURP/[Prefab] Create NiloToon Prefab Variant and Materials", priority = 0)]
|
||||
[MenuItem("Assets/NiloToon/[Prefab] Create NiloToon Prefab Variant and Materials", priority = 1100 + 0)]
|
||||
static void CreatePrefabVariantAndCloneMaterials()
|
||||
{
|
||||
// Get the selected prefab
|
||||
@ -186,7 +187,8 @@ namespace NiloToon.NiloToonURP
|
||||
EditorUtility.DisplayDialog("Success", "Prefab variant created with cloned materials.", "OK");
|
||||
}
|
||||
|
||||
[MenuItem("Window/NiloToonURP/Create Nilo Prefab Variant and Materials", priority = 0, validate = true)]
|
||||
[MenuItem("Window/NiloToonURP/[Prefab] Create NiloToon Prefab Variant and Materials", priority = 0, validate = true)]
|
||||
[MenuItem("Assets/NiloToon/[Prefab] Create NiloToon Prefab Variant and Materials", priority = 1100 + 0, validate = true)]
|
||||
public static bool ValidateCreatePrefabVariantAndCloneMaterials()
|
||||
{
|
||||
var allselectedObjects = Selection.objects;
|
||||
|
||||
@ -307,45 +307,41 @@ namespace NiloToon.NiloToonURP
|
||||
matOriginal.shader.name.Contains("Overlay");
|
||||
bool isOutl = matOriginal.shader.name.Contains("Outline");
|
||||
bool isTransparentQueue = matOriginal.renderQueue > 2500;
|
||||
bool isZWrite = matOriginal.GetFloat("_ZWrite") > 0.5f;
|
||||
|
||||
if (!isCutout && !isTransparent && !isOutl && !isTransparentQueue)
|
||||
niloToonSurfaceTypePresetIDArray[i] = NiloToonSurfaceTypePreset.Opaque;
|
||||
else if (!isCutout && !isTransparent && !isOutl && isTransparentQueue)
|
||||
niloToonSurfaceTypePresetIDArray[i] =
|
||||
NiloToonSurfaceTypePreset.TransparentQueueTransparent_ZWrite;
|
||||
else if (!isCutout && !isTransparent && isOutl && !isTransparentQueue)
|
||||
niloToonSurfaceTypePresetIDArray[i] = NiloToonSurfaceTypePreset.Opaque_Outline;
|
||||
else if (!isCutout && !isTransparent && isOutl && isTransparentQueue)
|
||||
niloToonSurfaceTypePresetIDArray[i] = NiloToonSurfaceTypePreset.Transparent_ZWrite_Outline;
|
||||
else if (!isCutout && isTransparent && !isOutl && !isTransparentQueue)
|
||||
niloToonSurfaceTypePresetIDArray[i] = NiloToonSurfaceTypePreset.Transparent_ZWrite;
|
||||
else if (!isCutout && isTransparent && !isOutl && isTransparentQueue)
|
||||
niloToonSurfaceTypePresetIDArray[i] = NiloToonSurfaceTypePreset.Transparent;
|
||||
else if (!isCutout && isTransparent && isOutl && !isTransparentQueue)
|
||||
niloToonSurfaceTypePresetIDArray[i] = NiloToonSurfaceTypePreset.Transparent_ZWrite_Outline;
|
||||
else if (!isCutout && isTransparent && isOutl && isTransparentQueue)
|
||||
niloToonSurfaceTypePresetIDArray[i] =
|
||||
NiloToonSurfaceTypePreset.TransparentQueueTransparent_ZWrite;
|
||||
else if (isCutout && !isTransparent && !isOutl && !isTransparentQueue)
|
||||
niloToonSurfaceTypePresetIDArray[i] = NiloToonSurfaceTypePreset.CutoutOpaque;
|
||||
else if (isCutout && !isTransparent && !isOutl && isTransparentQueue)
|
||||
niloToonSurfaceTypePresetIDArray[i] = NiloToonSurfaceTypePreset.CutoutOpaque;
|
||||
else if (isCutout && !isTransparent && isOutl && !isTransparentQueue)
|
||||
niloToonSurfaceTypePresetIDArray[i] = NiloToonSurfaceTypePreset.CutoutOpaque_Outline;
|
||||
else if (isCutout && !isTransparent && isOutl && isTransparentQueue)
|
||||
niloToonSurfaceTypePresetIDArray[i] =
|
||||
NiloToonSurfaceTypePreset.CutoutTransparentQueueTransparent_ZWrite_Outline;
|
||||
else if (isCutout && isTransparent && !isOutl && !isTransparentQueue)
|
||||
niloToonSurfaceTypePresetIDArray[i] =
|
||||
NiloToonSurfaceTypePreset.CutoutTransparentQueueTransparent_ZWrite;
|
||||
else if (isCutout && isTransparent && !isOutl && isTransparentQueue)
|
||||
niloToonSurfaceTypePresetIDArray[i] = NiloToonSurfaceTypePreset.CutoutTransparent;
|
||||
else if (isCutout && isTransparent && isOutl && !isTransparentQueue)
|
||||
niloToonSurfaceTypePresetIDArray[i] =
|
||||
NiloToonSurfaceTypePreset.CutoutTransparent_ZWrite_Outline;
|
||||
else if (isCutout && isTransparent && isOutl && isTransparentQueue)
|
||||
niloToonSurfaceTypePresetIDArray[i] =
|
||||
NiloToonSurfaceTypePreset.CutoutTransparentQueueTransparent_ZWrite_Outline;
|
||||
// if ZWrite is off, we treat the material as transparent
|
||||
if (!isCutout && !isTransparent && !isOutl && !isTransparentQueue && isZWrite) niloToonSurfaceTypePresetIDArray[i] = NiloToonSurfaceTypePreset.Opaque; // 1
|
||||
else if (!isCutout && !isTransparent && !isOutl && !isTransparentQueue && !isZWrite) niloToonSurfaceTypePresetIDArray[i] = NiloToonSurfaceTypePreset.Transparent; // 2
|
||||
else if (!isCutout && !isTransparent && !isOutl && isTransparentQueue && isZWrite) niloToonSurfaceTypePresetIDArray[i] = NiloToonSurfaceTypePreset.TransparentQueueTransparent_ZWrite; // 3
|
||||
else if (!isCutout && !isTransparent && !isOutl && isTransparentQueue && !isZWrite) niloToonSurfaceTypePresetIDArray[i] = NiloToonSurfaceTypePreset.Transparent; // 4
|
||||
else if (!isCutout && !isTransparent && isOutl && !isTransparentQueue && isZWrite) niloToonSurfaceTypePresetIDArray[i] = NiloToonSurfaceTypePreset.Opaque_Outline; // 5
|
||||
else if (!isCutout && !isTransparent && isOutl && !isTransparentQueue && !isZWrite) niloToonSurfaceTypePresetIDArray[i] = NiloToonSurfaceTypePreset.Transparent; // 6
|
||||
else if (!isCutout && !isTransparent && isOutl && isTransparentQueue && isZWrite) niloToonSurfaceTypePresetIDArray[i] = NiloToonSurfaceTypePreset.Transparent_ZWrite_Outline; // 7
|
||||
else if (!isCutout && !isTransparent && isOutl && isTransparentQueue && !isZWrite) niloToonSurfaceTypePresetIDArray[i] = NiloToonSurfaceTypePreset.Transparent; // 8
|
||||
else if (!isCutout && isTransparent && !isOutl && !isTransparentQueue && isZWrite) niloToonSurfaceTypePresetIDArray[i] = NiloToonSurfaceTypePreset.Transparent_ZWrite; // 9
|
||||
else if (!isCutout && isTransparent && !isOutl && !isTransparentQueue && !isZWrite) niloToonSurfaceTypePresetIDArray[i] = NiloToonSurfaceTypePreset.Transparent; // 10
|
||||
else if (!isCutout && isTransparent && !isOutl && isTransparentQueue && isZWrite) niloToonSurfaceTypePresetIDArray[i] = NiloToonSurfaceTypePreset.Transparent_ZWrite; // 11
|
||||
else if (!isCutout && isTransparent && !isOutl && isTransparentQueue && !isZWrite) niloToonSurfaceTypePresetIDArray[i] = NiloToonSurfaceTypePreset.Transparent; // 12
|
||||
else if (!isCutout && isTransparent && isOutl && !isTransparentQueue && isZWrite) niloToonSurfaceTypePresetIDArray[i] = NiloToonSurfaceTypePreset.Transparent_ZWrite_Outline; // 13
|
||||
else if (!isCutout && isTransparent && isOutl && !isTransparentQueue && !isZWrite) niloToonSurfaceTypePresetIDArray[i] = NiloToonSurfaceTypePreset.Transparent; // 14
|
||||
else if (!isCutout && isTransparent && isOutl && isTransparentQueue && isZWrite) niloToonSurfaceTypePresetIDArray[i] = NiloToonSurfaceTypePreset.TransparentQueueTransparent_ZWrite; // 15
|
||||
else if (!isCutout && isTransparent && isOutl && isTransparentQueue && !isZWrite) niloToonSurfaceTypePresetIDArray[i] = NiloToonSurfaceTypePreset.Transparent; // 16
|
||||
else if ( isCutout && !isTransparent && !isOutl && !isTransparentQueue && isZWrite) niloToonSurfaceTypePresetIDArray[i] = NiloToonSurfaceTypePreset.CutoutOpaque; // 17
|
||||
else if ( isCutout && !isTransparent && !isOutl && !isTransparentQueue && !isZWrite) niloToonSurfaceTypePresetIDArray[i] = NiloToonSurfaceTypePreset.CutoutTransparent; // 18
|
||||
else if ( isCutout && !isTransparent && !isOutl && isTransparentQueue && isZWrite) niloToonSurfaceTypePresetIDArray[i] = NiloToonSurfaceTypePreset.CutoutOpaque; // 19
|
||||
else if ( isCutout && !isTransparent && !isOutl && isTransparentQueue && !isZWrite) niloToonSurfaceTypePresetIDArray[i] = NiloToonSurfaceTypePreset.CutoutTransparent; // 20
|
||||
else if ( isCutout && !isTransparent && isOutl && !isTransparentQueue && isZWrite) niloToonSurfaceTypePresetIDArray[i] = NiloToonSurfaceTypePreset.CutoutOpaque_Outline; // 21
|
||||
else if ( isCutout && !isTransparent && isOutl && !isTransparentQueue && !isZWrite) niloToonSurfaceTypePresetIDArray[i] = NiloToonSurfaceTypePreset.CutoutTransparent; // 22
|
||||
else if ( isCutout && !isTransparent && isOutl && isTransparentQueue && isZWrite) niloToonSurfaceTypePresetIDArray[i] = NiloToonSurfaceTypePreset.CutoutTransparentQueueTransparent_ZWrite_Outline; // 23
|
||||
else if ( isCutout && !isTransparent && isOutl && isTransparentQueue && !isZWrite) niloToonSurfaceTypePresetIDArray[i] = NiloToonSurfaceTypePreset.CutoutTransparent; // 24
|
||||
else if ( isCutout && isTransparent && !isOutl && !isTransparentQueue && isZWrite) niloToonSurfaceTypePresetIDArray[i] = NiloToonSurfaceTypePreset.CutoutTransparentQueueTransparent_ZWrite; // 25
|
||||
else if ( isCutout && isTransparent && !isOutl && !isTransparentQueue && !isZWrite) niloToonSurfaceTypePresetIDArray[i] = NiloToonSurfaceTypePreset.CutoutTransparent; // 26
|
||||
else if ( isCutout && isTransparent && !isOutl && isTransparentQueue && isZWrite) niloToonSurfaceTypePresetIDArray[i] = NiloToonSurfaceTypePreset.CutoutTransparent_ZWrite; // 27
|
||||
else if ( isCutout && isTransparent && !isOutl && isTransparentQueue && !isZWrite) niloToonSurfaceTypePresetIDArray[i] = NiloToonSurfaceTypePreset.CutoutTransparent; // 28
|
||||
else if ( isCutout && isTransparent && isOutl && !isTransparentQueue && isZWrite) niloToonSurfaceTypePresetIDArray[i] = NiloToonSurfaceTypePreset.CutoutTransparent_ZWrite_Outline; // 29
|
||||
else if ( isCutout && isTransparent && isOutl && !isTransparentQueue && !isZWrite) niloToonSurfaceTypePresetIDArray[i] = NiloToonSurfaceTypePreset.CutoutTransparent; // 30
|
||||
else if ( isCutout && isTransparent && isOutl && isTransparentQueue && isZWrite) niloToonSurfaceTypePresetIDArray[i] = NiloToonSurfaceTypePreset.CutoutTransparentQueueTransparent_ZWrite_Outline; //31
|
||||
else if ( isCutout && isTransparent && isOutl && isTransparentQueue && !isZWrite) niloToonSurfaceTypePresetIDArray[i] = NiloToonSurfaceTypePreset.CutoutTransparent; // 32
|
||||
}
|
||||
|
||||
// since there are many model's texture that alpha is not used for transparency(e.g. store special data that is not alpha),
|
||||
@ -516,7 +512,7 @@ namespace NiloToon.NiloToonURP
|
||||
};
|
||||
string[] IsEyeBanNames = { "brown" }; // avoid "brown" treated as eye due to "brow"
|
||||
|
||||
string[] IsMouthTargetNames = { "mouth", "oral", "tongue", "kuchi", ".ha" };
|
||||
string[] IsMouthTargetNames = { "mouth", "oral", "tongue", "kuchi", ".ha", "kounai", "shita" };
|
||||
string[] IsMouthBanNames = { ".hada" };
|
||||
|
||||
string[] IsTeethTargetNames = { "teeth", "tooth" };
|
||||
@ -540,6 +536,8 @@ namespace NiloToon.NiloToonURP
|
||||
IsFaceFinalTargetNames = IsFaceFinalTargetNames.Concat(IsMouthTargetNames).ToArray();
|
||||
IsFaceFinalTargetNames = IsFaceFinalTargetNames.Concat(IsTeethTargetNames).ToArray();
|
||||
|
||||
string[] IsFaceExactTargetNames = new string[]{ "me", "ha"};
|
||||
|
||||
string[] IsFaceFinalBanNames = new string[] { };
|
||||
IsFaceFinalBanNames = IsFaceFinalBanNames.Concat(IsFaceBanNames).ToArray();
|
||||
IsFaceFinalBanNames = IsFaceFinalBanNames.Concat(IsEyeBanNames).ToArray();
|
||||
@ -561,6 +559,9 @@ namespace NiloToon.NiloToonURP
|
||||
IsFaceFinalTargetNames.Where(x => x != "face" && x != "head").ToList();
|
||||
IsNoOutlineFinalTargetNames.Concat(IsNoOutlineTargetNames);
|
||||
|
||||
List<string> IsNoOutlineExactTargetNames = new List<string>();
|
||||
IsNoOutlineExactTargetNames.Concat(IsFaceExactTargetNames);
|
||||
|
||||
List<string> IsNoOutlineFinalBanNames = IsFaceFinalBanNames.ToList();
|
||||
IsNoOutlineFinalBanNames.Concat(IsNoOutlineBanNames);
|
||||
|
||||
@ -573,6 +574,11 @@ namespace NiloToon.NiloToonURP
|
||||
isNoOutline |= NiloToonUtils.NameHasKeyword(mat.name, keyword);
|
||||
}
|
||||
|
||||
foreach (var keyword in IsNoOutlineExactTargetNames)
|
||||
{
|
||||
isNoOutline |= NiloToonUtils.NameEqualsKeywordIgnoreCase(mat.name, keyword);
|
||||
}
|
||||
|
||||
foreach (var keyword in IsNoOutlineFinalBanNames)
|
||||
{
|
||||
isNoOutline &= !NiloToonUtils.NameHasKeyword(mat.name, keyword);
|
||||
@ -642,11 +648,11 @@ namespace NiloToon.NiloToonURP
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
if (originalMatClone.shader == VRMBRPMToon00Shader)
|
||||
{
|
||||
const float niloToonWidthRelativeToMToon00 = 4;
|
||||
const float niloToonWidthRelativeToMToon00 = 12; //12~18 is good
|
||||
mat.SetFloat("_OutlineWidthExtraMultiplier", niloToonWidthRelativeToMToon00);
|
||||
|
||||
// extra check to limit any unexpected large outline width
|
||||
float maxFinalWidth = 0.6f; // 0.6 is NiloToon's default outline width
|
||||
float maxFinalWidth = 0.5f; // 0.5 is NiloToon's default outline width
|
||||
float finalWidth = Mathf.Min(maxFinalWidth,
|
||||
mat.GetFloat("_OutlineWidth") * niloToonWidthRelativeToMToon00);
|
||||
mat.SetFloat("_OutlineWidth", finalWidth / niloToonWidthRelativeToMToon00);
|
||||
@ -662,7 +668,7 @@ namespace NiloToon.NiloToonURP
|
||||
mat.SetFloat("_OutlineWidthExtraMultiplier", niloToonWidthRelativeToMToon10);
|
||||
|
||||
// extra check to limit any unexpected large outline width
|
||||
float maxFinalWidth = 0.6f; // 0.6 is NiloToon's default outline width
|
||||
float maxFinalWidth = 0.5f; // 0.5 is NiloToon's default outline width
|
||||
float finalWidth = Mathf.Min(maxFinalWidth,
|
||||
mat.GetFloat("_OutlineWidth") * niloToonWidthRelativeToMToon10);
|
||||
mat.SetFloat("_OutlineWidth", finalWidth / niloToonWidthRelativeToMToon10);
|
||||
@ -865,6 +871,11 @@ namespace NiloToon.NiloToonURP
|
||||
isFace |= NiloToonUtils.NameHasKeyword(mat.name, keyword);
|
||||
}
|
||||
|
||||
foreach (var keyword in IsFaceExactTargetNames)
|
||||
{
|
||||
isFace |= NiloToonUtils.NameEqualsKeywordIgnoreCase(mat.name,keyword);
|
||||
}
|
||||
|
||||
foreach (var keyword in IsFaceFinalBanNames)
|
||||
{
|
||||
isFace &= !NiloToonUtils.NameHasKeyword(mat.name, keyword);
|
||||
@ -1377,7 +1388,7 @@ namespace NiloToon.NiloToonURP
|
||||
toNiloToonMat.SetFloat("_OutlineWidthExtraMultiplier", niloToonWidthRelativeTolilToon);
|
||||
|
||||
// extra check to limit any unexpected large outline width
|
||||
float maxFinalWidth = 0.6f; // 0.6 is NiloToon's default outline width
|
||||
float maxFinalWidth = 0.5f; // 0.5 is NiloToon's default outline width
|
||||
float finalWidth = Mathf.Min(maxFinalWidth, _OutlineWidth * niloToonWidthRelativeTolilToon);
|
||||
toNiloToonMat.SetFloat("_OutlineWidth", finalWidth / niloToonWidthRelativeTolilToon);
|
||||
|
||||
@ -1797,7 +1808,8 @@ namespace NiloToon.NiloToonURP
|
||||
}
|
||||
|
||||
#if UNITY_EDITOR
|
||||
[MenuItem("Window/NiloToonURP/Convert Selected Materials to NiloToon", priority = 2)]
|
||||
[MenuItem("Window/NiloToonURP/[Material] Convert Selected Materials to NiloToon", priority = 2)]
|
||||
[MenuItem("Assets/NiloToon/[Material] Convert Selected Materials to NiloToon", priority = 1100 + 2)]
|
||||
public static void ConvertSelectedMaterialsToNiloToon_Character()
|
||||
{
|
||||
var allselectedObjects = Selection.objects;
|
||||
@ -1817,7 +1829,8 @@ namespace NiloToon.NiloToonURP
|
||||
AutoConvertMaterialsToNiloToon(allInputMaterials);
|
||||
}
|
||||
|
||||
[MenuItem("Window/NiloToonURP/Convert Selected Materials to NiloToon", priority = 2, validate = true)]
|
||||
[MenuItem("Window/NiloToonURP/[Material] Convert Selected Materials to NiloToon", priority = 2, validate = true)]
|
||||
[MenuItem("Assets/NiloToon/[Material] Convert Selected Materials to NiloToon", priority = 1100 + 2, validate = true)]
|
||||
public static bool ValidateConvertSelectedMaterialsToNiloToon_Character()
|
||||
{
|
||||
var allselectedObjects = Selection.objects;
|
||||
|
||||
@ -7,7 +7,9 @@ using System.IO;
|
||||
using System.Collections;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using System;
|
||||
|
||||
namespace NiloToon.NiloToonURP
|
||||
{
|
||||
@ -15,16 +17,30 @@ namespace NiloToon.NiloToonURP
|
||||
{
|
||||
private string ffmpegPath;
|
||||
private string inputFilePath = string.Empty;
|
||||
private string customSuffix = "(BakedMotionBlur)_<fps>_<shutterspeed>"; // Custom suffix for the output file
|
||||
private int crf = 0; // Default CRF value
|
||||
private string customSuffix = "(BakedMotionBlur)_<fps>_<shutterspeed>_<codec>"; // Custom suffix for the output file
|
||||
private int crf = 0; // Default CRF value (0 is lossless for CRF)
|
||||
private List<float> fpsOptions = new List<float>(); // List of possible FPS options
|
||||
private int selectedFPSIndex = 0; // Default FPS index
|
||||
private float inputVideoFPS = 0.0f; // FPS of the input video
|
||||
private double inputVideoDuration = 0.0; // Duration of the input video in seconds
|
||||
private int totalFrames = 0; // Total number of frames in the output video
|
||||
private float cameraExposureDuration = 1f / 48f; // 180 shutter angle in terms of 24fps
|
||||
private float motionBlurAmount = 1;
|
||||
|
||||
private string ffmpegArgumentsTemplate =
|
||||
"-vf \"{0}format=yuv420p\" -r {1} -c:v libx264 -preset veryslow -crf {2} -pix_fmt yuv420p -x264opts \"keyint=12:min-keyint=1:ref=1:bframes=0:qcomp=0.8:aq-strength=0.5:direct=auto:fast-pskip=0:deblock=-2,-2\"";
|
||||
private string ffmpegArgumentsTemplate_H264 =
|
||||
"-vf \"{0}format=yuv420p\" -r {1} -c:v libx264 -preset veryslow -crf {2} -pix_fmt yuv420p -x264opts \"keyint=1:ref=4:bframes=0\"";
|
||||
|
||||
private string ffmpegArgumentsTemplate_H265 =
|
||||
"-vf \"{0}format=yuv420p\" -r {1} -c:v libx265 -preset veryslow -x265-params \"crf={2}:keyint=1:no-open-gop=1\" -pix_fmt yuv420p";
|
||||
|
||||
private string ffmpegArgumentsTemplate_H265_10bit =
|
||||
"-vf \"{0}format=yuv420p10le\" -r {1} -c:v libx265 -preset veryslow -x265-params \"crf={2}:keyint=1:no-open-gop=1\" -pix_fmt yuv420p10le";
|
||||
|
||||
private string ffmpegArgumentsTemplate_ProRes_422HQ =
|
||||
"-vf \"{0}\" -r {1} -c:v prores_ks -profile:v 3 -pix_fmt yuv422p10le"; // ProRes 422 HQ
|
||||
|
||||
private string ffmpegArgumentsTemplate_ProRes =
|
||||
"-vf \"{0}\" -r {1} -c:v prores_ks -profile:v 5 -pix_fmt yuv444p10le"; // ProRes 4444 XQ
|
||||
|
||||
private Process ffmpegProcess;
|
||||
private Coroutine coroutine;
|
||||
@ -36,6 +52,13 @@ namespace NiloToon.NiloToonURP
|
||||
|
||||
private Vector2 scrollPosition;
|
||||
|
||||
private string[] codecOptions = new string[] { "H.264", "H.265 (8-bit)", "H.265 (10-bit)", "ProRes 422 HQ", "ProRes 4444 XQ" };
|
||||
private int selectedCodecIndex = 3; // Default to ProRes 422 HQ
|
||||
|
||||
// Added variables for logging interval and process timing
|
||||
private DateTime lastLogTime = DateTime.MinValue;
|
||||
private DateTime processStartTime;
|
||||
|
||||
[MenuItem("Window/NiloToonURP/MotionBlur Video Baker", priority = 10000)]
|
||||
public static void ShowWindow()
|
||||
{
|
||||
@ -43,29 +66,53 @@ namespace NiloToon.NiloToonURP
|
||||
window.LoadFFmpegPath(); // Load the FFmpeg path when the window is opened
|
||||
}
|
||||
|
||||
private bool ClickableLink(string text, string url)
|
||||
{
|
||||
GUIStyle linkStyle = new GUIStyle(GUI.skin.label)
|
||||
{
|
||||
richText = true,
|
||||
normal = { textColor = Color.cyan },
|
||||
hover = { textColor = Color.cyan },
|
||||
alignment = TextAnchor.MiddleLeft
|
||||
};
|
||||
|
||||
Rect rect = GUILayoutUtility.GetRect(new GUIContent(text), linkStyle, GUILayout.Height(20));
|
||||
EditorGUIUtility.AddCursorRect(rect, MouseCursor.Link);
|
||||
|
||||
if (GUI.Button(rect, $"{text}", linkStyle))
|
||||
{
|
||||
Application.OpenURL(url);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private void OnGUI()
|
||||
{
|
||||
scrollPosition = EditorGUILayout.BeginScrollView(scrollPosition);
|
||||
|
||||
// 960fps will make cinemachine not working correctly, so we suggest max at 900fps
|
||||
|
||||
// 960fps may make cinemachine not working correctly, so we suggest max at 900fps
|
||||
EditorGUILayout.HelpBox(
|
||||
"[Purpose of this tool]\n" +
|
||||
"Bake 480-900 fps video with zero or little motion blur -> 24/30/60 fps video with cinematic motion blur & AA produced by sub frame merging\n\n" +
|
||||
"[How to use?]\n" +
|
||||
"1.Locate your own ffmpeg.exe (download from ffmpeg.org)\n" +
|
||||
"2.Prepare a video with 480~900FPS (e.g., Record using Unity's Recorder with a high custom FPS)\n" +
|
||||
"3.Select that video as Input Video, wait for analysis\n" +
|
||||
"4.(optional)Adjust other settings if needed\n" +
|
||||
"5.Click 'Bake now!', this tool will bake cinematic motion blur & AA to a 24/30/60 fps output video (H.264)", MessageType.Info);
|
||||
"[Purpose of this tool]\n" +
|
||||
"Import a 480-960 fps short video, bake to a 24/30/60 fps video with high-quality motion blur & AA produced by sub-frame accumulation, similar to UnrealEngine Movie Render Queue's temporal sampling AA\n\n" +
|
||||
"[How to use?]\n" +
|
||||
"1. Locate your own ffmpeg.exe (download the latest from ffmpeg.org)\n" +
|
||||
"2. Select a 480~960FPS video as Input Video(e.g., set NiloToonMotionBlurVolume = 0.5~0.25 intensity, then record using Unity's Recorder with 480~960 FPS into ProRes422LT or higher)\n" +
|
||||
"3. Click 'Bake now!', this tool will bake motion blur & AA into a result 24/30/60 fps output video", MessageType.Info);
|
||||
|
||||
// add here
|
||||
ClickableLink("Online Document", "https://docs.google.com/document/d/1iEh1E5xLXnXuICM0ElV3F3x_J2LND9Du2SSKzcIuPXw/edit?tab=t.0#heading=h.tkl2vd8auzt9");
|
||||
ClickableLink("Download FFmpeg", "https://ffmpeg.org");
|
||||
|
||||
GUI.enabled = ffmpegProcess == null;
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
// FFmpeg Path
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
GUILayout.Label("FFmpeg Path", EditorStyles.boldLabel);
|
||||
EditorGUILayout.BeginHorizontal();
|
||||
ffmpegPath = EditorGUILayout.TextField("Path",ffmpegPath);
|
||||
ffmpegPath = EditorGUILayout.TextField("Path", ffmpegPath);
|
||||
if (GUILayout.Button("...", GUILayout.Width(60)))
|
||||
{
|
||||
string selectedPath = EditorUtility.OpenFilePanel("Select FFmpeg Executable", "", "exe");
|
||||
@ -84,21 +131,21 @@ namespace NiloToon.NiloToonURP
|
||||
GUILayout.Label("Input Video", EditorStyles.boldLabel);
|
||||
|
||||
EditorGUILayout.BeginHorizontal();
|
||||
inputFilePath = EditorGUILayout.TextField("Path",inputFilePath);
|
||||
inputFilePath = EditorGUILayout.TextField("Path", inputFilePath);
|
||||
if (GUILayout.Button("...", GUILayout.Width(30)) && ffmpegProcess == null)
|
||||
{
|
||||
string newPath = EditorUtility.OpenFilePanel("Select Input File", "", "mov,mp4");
|
||||
if (!string.IsNullOrEmpty(newPath))
|
||||
{
|
||||
inputFilePath = newPath;
|
||||
ExtractVideoFPS(inputFilePath); // Extract the FPS of the selected video
|
||||
ExtractVideoInfo(inputFilePath); // Extract the FPS and duration of the selected video
|
||||
}
|
||||
}
|
||||
EditorGUILayout.EndHorizontal();
|
||||
|
||||
if (inputVideoFPS < 480)
|
||||
{
|
||||
EditorGUILayout.HelpBox("Expect a video with 480~900FPS", MessageType.Info);
|
||||
EditorGUILayout.HelpBox("Expect a video with 480~960FPS", MessageType.Info);
|
||||
}
|
||||
|
||||
// Display error message if input video path is invalid
|
||||
@ -108,7 +155,7 @@ namespace NiloToon.NiloToonURP
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
// input video fps
|
||||
// Input Video FPS
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
if (inputVideoFPS > 0 && File.Exists(inputFilePath))
|
||||
{
|
||||
@ -118,11 +165,14 @@ namespace NiloToon.NiloToonURP
|
||||
GUILayout.Space(25);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
// output video (suffix,fps,CRF)
|
||||
// Output Video Settings
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
GUILayout.Label("Output Video", EditorStyles.boldLabel);
|
||||
|
||||
// Codec Selection
|
||||
selectedCodecIndex = EditorGUILayout.Popup(new GUIContent("Codec"), selectedCodecIndex, codecOptions);
|
||||
|
||||
if (fpsOptions.Count > 0)
|
||||
{
|
||||
selectedFPSIndex = Mathf.Clamp(selectedFPSIndex, 0, fpsOptions.Count - 1);
|
||||
@ -130,7 +180,6 @@ namespace NiloToon.NiloToonURP
|
||||
if (newSelectedFPSIndex != selectedFPSIndex)
|
||||
{
|
||||
selectedFPSIndex = newSelectedFPSIndex;
|
||||
|
||||
UnityEngine.Debug.Log($"Selected FPS: {GetOutputFPS()}"); // Log the selected FPS
|
||||
}
|
||||
}
|
||||
@ -140,63 +189,78 @@ namespace NiloToon.NiloToonURP
|
||||
}
|
||||
|
||||
motionBlurAmount = EditorGUILayout.Slider("Motion Blur", motionBlurAmount, 0f, 4f);
|
||||
crf = EditorGUILayout.IntSlider("CRF", crf, 0, 51);
|
||||
|
||||
EditorGUILayout.HelpBox(
|
||||
"CRF (Constant Rate Factor) controls the quality of the video. Lower values mean higher quality and larger file sizes. The range is from 0 (lossless) to 51 (worst quality).",
|
||||
MessageType.Info);
|
||||
// CRF Slider (Only for codecs that support it)
|
||||
if (selectedCodecIndex != 3 && selectedCodecIndex != 4) // Not ProRes
|
||||
{
|
||||
crf = EditorGUILayout.IntSlider(new GUIContent("CRF", "For lossless encoding, set CRF to 0. Higher values reduce quality."), crf, 0, 51);
|
||||
if (crf == 0)
|
||||
{
|
||||
EditorGUILayout.HelpBox("CRF is set to 0: Lossless encoding. This results in the highest quality and largest file size.", MessageType.Info);
|
||||
}
|
||||
else
|
||||
{
|
||||
EditorGUILayout.HelpBox("CRF controls the quality of the video. Lower values mean higher quality and larger file sizes.", MessageType.Info);
|
||||
}
|
||||
}
|
||||
|
||||
customSuffix = EditorGUILayout.TextField("Suffix", customSuffix);
|
||||
|
||||
|
||||
// Open Destination Folder Button
|
||||
GUI.enabled = !string.IsNullOrEmpty(inputFilePath) && File.Exists(inputFilePath);
|
||||
if (GUILayout.Button("Open Destination Folder"))
|
||||
{
|
||||
string currentOutputFilePath = GenerateOutputFilePath(inputFilePath, customSuffix);
|
||||
string folder = Path.GetDirectoryName(currentOutputFilePath);
|
||||
if (Directory.Exists(folder))
|
||||
{
|
||||
OpenFolder(folder);
|
||||
}
|
||||
else
|
||||
{
|
||||
EditorUtility.DisplayDialog("Folder Not Found", "The destination folder does not exist.", "OK");
|
||||
}
|
||||
}
|
||||
GUI.enabled = ffmpegProcess == null;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
// output video info
|
||||
// Output Video Info
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
if (fpsOptions.Count > 0)
|
||||
{
|
||||
Generate_tmixFilters(inputVideoFPS);
|
||||
|
||||
|
||||
EditorGUILayout.Space(10);
|
||||
EditorGUILayout.LabelField("Output info:", EditorStyles.boldLabel);
|
||||
EditorGUILayout.HelpBox(
|
||||
$"- TMix Frame Count: {currenttmixFrameCount}\n" +
|
||||
$"- Shutter Angle in terms of 24fps: {GetShutterAngleInTermsOf24fps()} degrees (~180 is a good default for cinematic output)\n" +
|
||||
$"- Shutter Speed: {GetShutterSpeedDisplayString()} (~1/48 is a good default for cinematic output)"
|
||||
$"- Temporal Sample(TMix) Count: {currenttmixFrameCount} (>=16 is good for cinematic output)\n" +
|
||||
$"- Shutter Angle in terms of 24fps: {GetShutterAngleInTermsOf24fps()} degrees (~180 is a good default for cinematic output)\n" +
|
||||
$"- Shutter Speed: {GetShutterSpeedDisplayString()} (~1/48 is a good default for cinematic output)"
|
||||
, MessageType.Info);
|
||||
|
||||
// check if shutter angle is too small
|
||||
if (currenttmixFrameCount < Mathf.CeilToInt(inputVideoFPS / GetOutputFPS()/ 2))
|
||||
// Check if shutter angle is too small
|
||||
if (currenttmixFrameCount < Mathf.CeilToInt(inputVideoFPS / GetOutputFPS() / 2))
|
||||
{
|
||||
EditorGUILayout.HelpBox(
|
||||
$"Current Shutter Angle for {GetOutputFPS()}fps is < 180, while it is not wrong, it may produce not enough motion blur"
|
||||
, MessageType.Warning);
|
||||
}
|
||||
|
||||
// it is ok to go over 360, so don't give warning.
|
||||
// for example, 60fps output with 1/48th shutter speed
|
||||
/*
|
||||
// check if shutter angle is too big
|
||||
if (currenttmixFrameCount > (inputVideoFPS / GetOutputFPS()))
|
||||
{
|
||||
EditorGUILayout.HelpBox(
|
||||
$"Current Shutter Angle is too large, it may produce too much motion blur"
|
||||
, MessageType.Warning);
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
GUILayout.Space(25);
|
||||
|
||||
|
||||
EditorGUILayout.LabelField("Extra note:", EditorStyles.boldLabel);
|
||||
EditorGUILayout.HelpBox(
|
||||
$"- Make sure Project Settings > VFX > Fixed Time Step is using '1/fps of recorder' when recording\n" +
|
||||
$"- Do not record in 960fps or higher, it may break cinemachine's camera movement"
|
||||
$"- If fps is high (e.g., 900fps or higher), it may break cinemachine's camera movement\n" +
|
||||
$"- Example input video: 1440p 960fps, or 2160p 480fps"
|
||||
, MessageType.Info);
|
||||
|
||||
GUI.enabled = true;
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
// Bake button
|
||||
// Bake Button
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
// Disable the "Bake Now!" button if any condition is not met
|
||||
GUI.enabled = ffmpegProcess == null && ValidatePaths() && fpsOptions.Count > 0;
|
||||
if (GUILayout.Button("Bake now!") && ffmpegProcess == null && ValidatePaths() && fpsOptions.Count > 0)
|
||||
@ -236,7 +300,7 @@ namespace NiloToon.NiloToonURP
|
||||
{
|
||||
CancelFFmpegProcess();
|
||||
}
|
||||
|
||||
|
||||
EditorGUILayout.EndScrollView();
|
||||
}
|
||||
|
||||
@ -279,6 +343,7 @@ namespace NiloToon.NiloToonURP
|
||||
{
|
||||
return (float)currenttmixFrameCount / (inputVideoFPS / 24f) * 360f;
|
||||
}
|
||||
|
||||
private float GetShutterSpeed()
|
||||
{
|
||||
return (1f / 24f) * (GetShutterAngleInTermsOf24fps() / 360f);
|
||||
@ -286,17 +351,38 @@ namespace NiloToon.NiloToonURP
|
||||
|
||||
private string GetShutterSpeedDisplayString()
|
||||
{
|
||||
return $"1/{1 / GetShutterSpeed()}s";
|
||||
return $"1/{FormatNumber(1 / GetShutterSpeed())}s";
|
||||
}
|
||||
|
||||
private string GetShutterSpeedFileNameString()
|
||||
{
|
||||
return $"OneOver{1 / GetShutterSpeed()}s";
|
||||
return $"OneOver{FormatNumber(1 / GetShutterSpeed())}s";
|
||||
}
|
||||
|
||||
// Helper method to format numbers without unnecessary trailing zeros
|
||||
private string FormatNumber(double number)
|
||||
{
|
||||
if (number % 1 == 0)
|
||||
return number.ToString("0");
|
||||
else
|
||||
return number.ToString("0.##");
|
||||
}
|
||||
|
||||
private string GenerateOutputFilePath(string inputPath, string suffix)
|
||||
{
|
||||
suffix = suffix.Replace("<fps>", $"{GetOutputFPS()}fps");
|
||||
suffix = suffix.Replace("<shutterspeed>", $"{GetShutterSpeedFileNameString()}");
|
||||
|
||||
// Handle codec placeholder
|
||||
if (suffix.Contains("<codec>"))
|
||||
{
|
||||
// Get codec name and format it for filename
|
||||
string codecName = codecOptions[selectedCodecIndex];
|
||||
codecName = codecName.Replace(" ", "").Replace("(", "").Replace(")", "").Replace(".", "").Replace("-", "");
|
||||
|
||||
suffix = suffix.Replace("<codec>", codecName);
|
||||
}
|
||||
|
||||
string directory = Path.GetDirectoryName(inputPath);
|
||||
string filenameWithoutExtension = Path.GetFileNameWithoutExtension(inputPath);
|
||||
string extension = Path.GetExtension(inputPath);
|
||||
@ -306,30 +392,62 @@ namespace NiloToon.NiloToonURP
|
||||
private IEnumerator StartFFmpegProcessCoroutine(string outputFilePath, float selectedFPS)
|
||||
{
|
||||
string tmixFilters = Generate_tmixFilters(inputVideoFPS);
|
||||
string ffmpegArguments = string.Format(ffmpegArgumentsTemplate, tmixFilters, selectedFPS, crf);
|
||||
|
||||
// Record start time
|
||||
processStartTime = DateTime.Now;
|
||||
|
||||
// Calculate totalFrames here, based on the selected output FPS and the input video duration
|
||||
if (selectedFPS > 0 && inputVideoDuration > 0)
|
||||
{
|
||||
totalFrames = (int)(selectedFPS * inputVideoDuration);
|
||||
UnityEngine.Debug.Log($"Calculated Total Output Frames (using output video FPS {selectedFPS}): {totalFrames}");
|
||||
}
|
||||
else
|
||||
{
|
||||
totalFrames = 0;
|
||||
UnityEngine.Debug.LogError("Failed to calculate total frames due to invalid output FPS or video duration.");
|
||||
}
|
||||
|
||||
// Log start of baking process with output file name
|
||||
UnityEngine.Debug.Log($"Baking started. Output file: {outputFilePath}");
|
||||
|
||||
// Select the FFmpeg arguments template based on the selected codec
|
||||
string ffmpegArgumentsTemplate = GetFFmpegArgumentsTemplate();
|
||||
|
||||
// Prepare the FFmpeg arguments
|
||||
string ffmpegArguments = "";
|
||||
|
||||
if (selectedCodecIndex == 0 || selectedCodecIndex == 1 || selectedCodecIndex == 2) // H.264, H.265
|
||||
{
|
||||
ffmpegArguments = string.Format(ffmpegArgumentsTemplate, tmixFilters, selectedFPS, crf);
|
||||
}
|
||||
else if (selectedCodecIndex == 3 || selectedCodecIndex == 4) // ProRes
|
||||
{
|
||||
ffmpegArguments = string.Format(ffmpegArgumentsTemplate, tmixFilters, selectedFPS);
|
||||
}
|
||||
|
||||
// Use '-hide_banner' to suppress unnecessary output
|
||||
ProcessStartInfo processStartInfo = new ProcessStartInfo
|
||||
{
|
||||
FileName = ffmpegPath,
|
||||
Arguments = $"-i \"{inputFilePath}\" {ffmpegArguments} \"{outputFilePath}\"",
|
||||
RedirectStandardOutput = true,
|
||||
RedirectStandardError = true,
|
||||
UseShellExecute = false, // must be false
|
||||
Arguments = $"-hide_banner -i \"{inputFilePath}\" {ffmpegArguments} \"{outputFilePath}\"",
|
||||
RedirectStandardOutput = false, // Do not redirect standard output
|
||||
RedirectStandardError = true, // Redirect standard error to capture errors and progress
|
||||
UseShellExecute = false, // Must be false
|
||||
CreateNoWindow = true
|
||||
};
|
||||
|
||||
ffmpegProcess = new Process
|
||||
{
|
||||
StartInfo = processStartInfo
|
||||
StartInfo = processStartInfo,
|
||||
EnableRaisingEvents = true
|
||||
};
|
||||
ffmpegProcess.OutputDataReceived += (sender, args) => HandleFFmpegOutput(args.Data);
|
||||
ffmpegProcess.ErrorDataReceived += (sender, args) => HandleFFmpegOutput(args.Data);
|
||||
|
||||
ffmpegProcess.ErrorDataReceived += FfmpegProcess_ErrorDataReceived;
|
||||
ffmpegProcess.Start();
|
||||
ffmpegProcess.BeginOutputReadLine();
|
||||
ffmpegProcess.BeginErrorReadLine();
|
||||
|
||||
// Wait for the process to exit while updating the progress bar
|
||||
// Wait for the process to exit
|
||||
while (!ffmpegProcess.HasExited)
|
||||
{
|
||||
yield return null;
|
||||
@ -338,27 +456,247 @@ namespace NiloToon.NiloToonURP
|
||||
ffmpegProcess.WaitForExit();
|
||||
ffmpegProcess = null;
|
||||
|
||||
// Close the progress bar when the process exits
|
||||
EditorUtility.ClearProgressBar();
|
||||
// Calculate elapsed time
|
||||
TimeSpan elapsedTime = DateTime.Now - processStartTime;
|
||||
|
||||
// Log completion message
|
||||
string timeSpent = $"Time spent = {elapsedTime.Hours} hours {elapsedTime.Minutes} minutes {elapsedTime.Seconds} seconds, video completed ({Path.GetFileName(outputFilePath)}).";
|
||||
UnityEngine.Debug.Log(timeSpent);
|
||||
}
|
||||
|
||||
private void FfmpegProcess_ErrorDataReceived(object sender, DataReceivedEventArgs e)
|
||||
{
|
||||
if (!string.IsNullOrEmpty(e.Data))
|
||||
{
|
||||
string data = e.Data;
|
||||
HandleFFmpegOutput(data);
|
||||
}
|
||||
}
|
||||
|
||||
private void HandleFFmpegOutput(string data)
|
||||
{
|
||||
// Parse FFmpeg output to extract meaningful information
|
||||
if (IsCriticalFfmpegMessage(data))
|
||||
{
|
||||
UnityEngine.Debug.LogError("FFmpeg Error: " + data);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Parse progress information
|
||||
// FFmpeg outputs progress in lines like: "frame=123 fps=45 q=28.0 size=1234kB time=00:00:05.12 bitrate=1976.3kbits/s speed=1.23x"
|
||||
|
||||
if (data.StartsWith("frame="))
|
||||
{
|
||||
// Regular expression to parse the progress line
|
||||
var progressMatch = Regex.Match(data, @"frame=\s*(\d+)\s.*?time=\s*(\S+)\s.*?speed=\s*([\d\.]+)x");
|
||||
|
||||
if (progressMatch.Success)
|
||||
{
|
||||
string frameStr = progressMatch.Groups[1].Value;
|
||||
string timeStr = progressMatch.Groups[2].Value;
|
||||
string speedStr = progressMatch.Groups[3].Value;
|
||||
|
||||
if (int.TryParse(frameStr, out int currentFrame))
|
||||
{
|
||||
float percentage = 0f;
|
||||
if (totalFrames > 0)
|
||||
{
|
||||
percentage = (float)currentFrame / totalFrames * 100f;
|
||||
percentage = Mathf.Clamp(percentage, 0f, 100f);
|
||||
}
|
||||
|
||||
// Only log if at least 2 seconds have passed since last log
|
||||
if ((DateTime.Now - lastLogTime).TotalSeconds >= 2)
|
||||
{
|
||||
TimeSpan elapsedTime = DateTime.Now - processStartTime;
|
||||
|
||||
string estimatedTimeRemainingString = "Unknown";
|
||||
if (percentage > 0)
|
||||
{
|
||||
double estimatedTotalSeconds = elapsedTime.TotalSeconds / (percentage / 100);
|
||||
TimeSpan estimatedRemainingTime = TimeSpan.FromSeconds(estimatedTotalSeconds - elapsedTime.TotalSeconds);
|
||||
|
||||
estimatedTimeRemainingString = $"{(int)estimatedRemainingTime.TotalHours}h {estimatedRemainingTime.Minutes}m {estimatedRemainingTime.Seconds}s";
|
||||
}
|
||||
|
||||
string elapsedTimeString = $"{(int)elapsedTime.TotalHours}h {elapsedTime.Minutes}m {elapsedTime.Seconds}s";
|
||||
|
||||
string logMessage = $"Frame {currentFrame}/{totalFrames} ({percentage:F1}%), Processed time: {elapsedTimeString}, Estimated time remaining: {estimatedTimeRemainingString}, Speed {speedStr}x";
|
||||
|
||||
UnityEngine.Debug.Log(logMessage);
|
||||
|
||||
lastLogTime = DateTime.Now;
|
||||
}
|
||||
}
|
||||
// Optionally, handle other outputs or suppress less important messages
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private bool IsCriticalFfmpegMessage(string message)
|
||||
{
|
||||
if (string.IsNullOrEmpty(message))
|
||||
return false;
|
||||
|
||||
// Check if message contains 'Error' or 'Invalid' etc.
|
||||
string lowerMessage = message.ToLowerInvariant();
|
||||
return lowerMessage.Contains("error") || lowerMessage.Contains("invalid") || lowerMessage.Contains("failed");
|
||||
}
|
||||
|
||||
private void CancelFFmpegProcess()
|
||||
{
|
||||
if (ffmpegProcess != null && !ffmpegProcess.HasExited)
|
||||
{
|
||||
ffmpegProcess.Kill();
|
||||
ffmpegProcess.WaitForExit(); // Ensure the process has completely exited
|
||||
ffmpegProcess = null;
|
||||
if (coroutine != null)
|
||||
{
|
||||
EditorCoroutine.StopCoroutine(coroutine);
|
||||
coroutine = null;
|
||||
}
|
||||
|
||||
UnityEngine.Debug.Log("FFmpeg process cancelled.");
|
||||
|
||||
// Delete the incomplete output file
|
||||
if (File.Exists(outputFilePath))
|
||||
{
|
||||
try
|
||||
{
|
||||
File.Delete(outputFilePath);
|
||||
UnityEngine.Debug.Log("Incomplete output file deleted.");
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
UnityEngine.Debug.LogError($"Failed to delete incomplete output file: {e.Message}");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void ExtractVideoInfo(string videoPath)
|
||||
{
|
||||
inputVideoFPS = 0f;
|
||||
inputVideoDuration = 0.0;
|
||||
|
||||
ProcessStartInfo processStartInfo = new ProcessStartInfo
|
||||
{
|
||||
FileName = ffmpegPath,
|
||||
Arguments = $"-hide_banner -i \"{videoPath}\"",
|
||||
RedirectStandardOutput = false, // FFmpeg outputs video information to standard error stream
|
||||
RedirectStandardError = true, // Redirect standard error stream
|
||||
UseShellExecute = false,
|
||||
CreateNoWindow = true
|
||||
};
|
||||
|
||||
Process process = new Process
|
||||
{
|
||||
StartInfo = processStartInfo
|
||||
};
|
||||
|
||||
process.ErrorDataReceived += ProcessOutputHandler;
|
||||
|
||||
process.Start();
|
||||
process.BeginErrorReadLine();
|
||||
process.WaitForExit();
|
||||
|
||||
// After processing, check if Duration was successfully extracted
|
||||
if (inputVideoDuration <= 0)
|
||||
{
|
||||
UnityEngine.Debug.LogError("Failed to extract Duration from the input video.");
|
||||
}
|
||||
}
|
||||
|
||||
private void ProcessOutputHandler(object sender, DataReceivedEventArgs e)
|
||||
{
|
||||
if (string.IsNullOrEmpty(e.Data))
|
||||
return;
|
||||
|
||||
// UnityEngine.Debug.Log("FFmpeg Output: " + e.Data); // Optionally log output
|
||||
|
||||
// Extract FPS (input video FPS)
|
||||
var matchFPS = Regex.Match(e.Data, @"Video:.*?(\d+(\.\d+)?) fps");
|
||||
if (matchFPS.Success)
|
||||
{
|
||||
if (float.TryParse(matchFPS.Groups[1].Value, NumberStyles.Float, CultureInfo.InvariantCulture, out float fps))
|
||||
{
|
||||
inputVideoFPS = fps;
|
||||
UnityEngine.Debug.Log("Input Video FPS: " + inputVideoFPS);
|
||||
UpdateFPSOptions(inputVideoFPS);
|
||||
}
|
||||
}
|
||||
|
||||
// Extract duration
|
||||
var matchDuration = Regex.Match(e.Data, @"Duration: (\d+):(\d+):(\d+(\.\d+)?)");
|
||||
if (matchDuration.Success)
|
||||
{
|
||||
int hours = int.Parse(matchDuration.Groups[1].Value);
|
||||
int minutes = int.Parse(matchDuration.Groups[2].Value);
|
||||
double seconds = double.Parse(matchDuration.Groups[3].Value, CultureInfo.InvariantCulture);
|
||||
inputVideoDuration = hours * 3600 + minutes * 60 + seconds;
|
||||
UnityEngine.Debug.Log("Input Video Duration: " + inputVideoDuration + " seconds");
|
||||
}
|
||||
}
|
||||
|
||||
private void UpdateFPSOptions(float inputFPS)
|
||||
{
|
||||
fpsOptions.Clear();
|
||||
float[] supportedOutputFPS = { 23.976f, 24f, 25f, 29.97f, 30f, 48f, 50f, 59.94f, 60f, 72f, 90f, 100f, 120f, 144f, 240f };
|
||||
|
||||
foreach (var fps in supportedOutputFPS)
|
||||
{
|
||||
if (inputFPS >= fps * 2)
|
||||
{
|
||||
fpsOptions.Add(fps);
|
||||
}
|
||||
}
|
||||
|
||||
// Find index of 60 fps or closest lower value if 60 is not available
|
||||
int index60 = fpsOptions.FindIndex(fps => fps >= 60);
|
||||
selectedFPSIndex = index60 >= 0 ? index60 : fpsOptions.Count - 1;
|
||||
}
|
||||
|
||||
private string GetFFmpegArgumentsTemplate()
|
||||
{
|
||||
switch (selectedCodecIndex)
|
||||
{
|
||||
case 0: // H.264
|
||||
return ffmpegArgumentsTemplate_H264;
|
||||
case 1: // H.265 (8-bit)
|
||||
return ffmpegArgumentsTemplate_H265;
|
||||
case 2: // H.265 (10-bit)
|
||||
return ffmpegArgumentsTemplate_H265_10bit;
|
||||
case 3: // ProRes 422 HQ
|
||||
return ffmpegArgumentsTemplate_ProRes_422HQ;
|
||||
case 4: // ProRes 4444 XQ
|
||||
return ffmpegArgumentsTemplate_ProRes;
|
||||
default:
|
||||
return ffmpegArgumentsTemplate_H264;
|
||||
}
|
||||
}
|
||||
|
||||
private string Generate_tmixFilters(float inputVideoFPS)
|
||||
{
|
||||
int numberOfTMixFrames = Mathf.FloorToInt(inputVideoFPS * cameraExposureDuration * motionBlurAmount);
|
||||
|
||||
// ensure at least 1 frame when motionBlurAmount is 0
|
||||
numberOfTMixFrames = Mathf.Max(numberOfTMixFrames, 1);
|
||||
|
||||
currenttmixFrameCount = numberOfTMixFrames;
|
||||
|
||||
if (currenttmixFrameCount == 0)
|
||||
{
|
||||
return "";
|
||||
}
|
||||
|
||||
#if METHOD1
|
||||
|
||||
#if METHOD1
|
||||
string weightString = string.Join(" ", Enumerable.Repeat("1", numberOfTMixFrames));
|
||||
#endif
|
||||
|
||||
#if METHOD2
|
||||
#endif
|
||||
|
||||
#if METHOD2
|
||||
// [2-way expo falloff]
|
||||
|
||||
|
||||
// Generate exponential falloff weights
|
||||
List<int> weights = new List<int>();
|
||||
int centerFrame = numberOfTMixFrames / 2;
|
||||
@ -376,10 +714,9 @@ namespace NiloToon.NiloToonURP
|
||||
|
||||
string weightString = string.Join(" ", weights);
|
||||
//-------------------------------------------------------------------------------------------------------
|
||||
#endif
|
||||
|
||||
|
||||
#if METHOD3
|
||||
#endif
|
||||
|
||||
#if METHOD3
|
||||
//-------------------------------------------------------------------------------------------------------
|
||||
// [1-way expo falloff]
|
||||
|
||||
@ -402,17 +739,17 @@ namespace NiloToon.NiloToonURP
|
||||
|
||||
// Ensure no weight is zero
|
||||
weights = weights.Select(w => Mathf.Max(w, 1)).ToList();
|
||||
|
||||
|
||||
string weightString = string.Join(" ", weights);
|
||||
//-------------------------------------------------------------------------------------------------------
|
||||
#endif
|
||||
|
||||
#if METHOD4
|
||||
#endif
|
||||
|
||||
#if METHOD4
|
||||
string weightString = GenerateGaussianWeights(numberOfTMixFrames);
|
||||
#endif
|
||||
#endif
|
||||
return $"tmix=frames={numberOfTMixFrames}:weights='{weightString}',";
|
||||
}
|
||||
|
||||
|
||||
private string GenerateGaussianWeights(int numberOfTMixFrames)
|
||||
{
|
||||
numberOfTMixFrames = Mathf.Min(40, Mathf.Max(1, numberOfTMixFrames));
|
||||
@ -428,7 +765,7 @@ namespace NiloToon.NiloToonURP
|
||||
weights.Add(weight);
|
||||
sum += weight;
|
||||
}
|
||||
|
||||
|
||||
const int scale = 1000;
|
||||
List<int> scaledWeights = weights.Select(w => (int)Mathf.Round(w / sum * scale)).ToList();
|
||||
|
||||
@ -443,104 +780,19 @@ namespace NiloToon.NiloToonURP
|
||||
return string.Join(" ", scaledWeights);
|
||||
}
|
||||
|
||||
private void CancelFFmpegProcess()
|
||||
// New method to open the folder directly
|
||||
private void OpenFolder(string folderPath)
|
||||
{
|
||||
if (ffmpegProcess != null && !ffmpegProcess.HasExited)
|
||||
{
|
||||
ffmpegProcess.Kill();
|
||||
ffmpegProcess.WaitForExit(); // Ensure the process has completely exited
|
||||
ffmpegProcess = null;
|
||||
if (coroutine != null)
|
||||
{
|
||||
EditorCoroutine.StopCoroutine(coroutine);
|
||||
coroutine = null;
|
||||
}
|
||||
|
||||
EditorUtility.ClearProgressBar();
|
||||
UnityEngine.Debug.Log("FFmpeg process cancelled.");
|
||||
|
||||
// Delete the incomplete output file
|
||||
if (File.Exists(outputFilePath))
|
||||
{
|
||||
try
|
||||
{
|
||||
File.Delete(outputFilePath);
|
||||
UnityEngine.Debug.Log("Incomplete output file deleted.");
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
UnityEngine.Debug.LogError($"Failed to delete incomplete output file: {e.Message}");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void HandleFFmpegOutput(string data)
|
||||
{
|
||||
UnityEngine.Debug.Log(data);
|
||||
}
|
||||
|
||||
private void ExtractVideoFPS(string videoPath)
|
||||
{
|
||||
ProcessStartInfo processStartInfo = new ProcessStartInfo
|
||||
{
|
||||
FileName = ffmpegPath,
|
||||
Arguments = $"-i \"{videoPath}\" -vcodec copy -f null -",
|
||||
RedirectStandardOutput = true,
|
||||
RedirectStandardError = true,
|
||||
UseShellExecute = false,
|
||||
CreateNoWindow = true
|
||||
};
|
||||
|
||||
Process process = new Process
|
||||
{
|
||||
StartInfo = processStartInfo
|
||||
};
|
||||
|
||||
process.OutputDataReceived += ProcessOutputHandler;
|
||||
process.ErrorDataReceived += ProcessOutputHandler;
|
||||
|
||||
process.Start();
|
||||
process.BeginOutputReadLine();
|
||||
process.BeginErrorReadLine();
|
||||
process.WaitForExit();
|
||||
}
|
||||
|
||||
private void ProcessOutputHandler(object sender, DataReceivedEventArgs e)
|
||||
{
|
||||
if (string.IsNullOrEmpty(e.Data))
|
||||
return;
|
||||
|
||||
UnityEngine.Debug.Log("FFmpeg Output: " + e.Data); // Log the output to debug
|
||||
|
||||
// Example of how to parse the FPS from FFmpeg output
|
||||
// Look for a line containing "fps" and extract the value
|
||||
var match = Regex.Match(e.Data, @"(\d+(\.\d+)?) fps");
|
||||
if (match.Success)
|
||||
{
|
||||
if (float.TryParse(match.Groups[1].Value, out float fps))
|
||||
{
|
||||
inputVideoFPS = fps;
|
||||
UnityEngine.Debug.Log("Extracted FPS: " + inputVideoFPS); // Log the extracted FPS
|
||||
UpdateFPSOptions(inputVideoFPS); // Update FPS options based on extracted FPS
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void UpdateFPSOptions(float inputFPS)
|
||||
{
|
||||
fpsOptions.Clear();
|
||||
float[] supportedOutputFPS = { 24, 25, 30, 50, 60 };
|
||||
|
||||
foreach (var fps in supportedOutputFPS)
|
||||
{
|
||||
if (inputFPS >= fps * 2)
|
||||
{
|
||||
fpsOptions.Add(fps);
|
||||
}
|
||||
}
|
||||
|
||||
selectedFPSIndex = fpsOptions.Count - 1; // Set the highest FPS
|
||||
#if UNITY_EDITOR_WIN
|
||||
folderPath = folderPath.Replace('/', '\\'); // Ensure correct path separator on Windows
|
||||
System.Diagnostics.Process.Start("explorer.exe", folderPath);
|
||||
#elif UNITY_EDITOR_OSX
|
||||
System.Diagnostics.Process.Start("open", folderPath);
|
||||
#elif UNITY_EDITOR_LINUX
|
||||
System.Diagnostics.Process.Start("xdg-open", folderPath);
|
||||
#else
|
||||
Application.OpenURL("file://" + folderPath);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -85,7 +85,11 @@ namespace NiloToon.NiloToonURP
|
||||
Mesh mesh = null;
|
||||
switch (renderer)
|
||||
{
|
||||
case MeshRenderer mr: mesh = mr.GetComponent<MeshFilter>().sharedMesh; break;
|
||||
case MeshRenderer mr:
|
||||
MeshFilter mf = mr.GetComponent<MeshFilter>();
|
||||
if(!mf) continue;
|
||||
mesh = mf.sharedMesh;
|
||||
break;
|
||||
case SkinnedMeshRenderer smr: mesh = smr.sharedMesh; ; break;
|
||||
default:
|
||||
break; // do nothing if not a supported renderer(e.g. particle system's renderer)
|
||||
@ -112,7 +116,11 @@ namespace NiloToon.NiloToonURP
|
||||
Mesh mesh = null;
|
||||
switch (renderer)
|
||||
{
|
||||
case MeshRenderer mr: mesh = mr.GetComponent<MeshFilter>().sharedMesh; break;
|
||||
case MeshRenderer mr:
|
||||
MeshFilter mf = mr.GetComponent<MeshFilter>();
|
||||
if(!mf) continue;
|
||||
mesh = mf.sharedMesh;
|
||||
break;
|
||||
case SkinnedMeshRenderer smr: mesh = smr.sharedMesh; break;
|
||||
default:
|
||||
break; // do nothing if not a supported renderer(e.g. particle system's renderer)
|
||||
@ -381,7 +389,8 @@ namespace NiloToon.NiloToonURP
|
||||
public class NiloToonEditorAutoSetupCharacter
|
||||
{
|
||||
#if UNITY_EDITOR
|
||||
[MenuItem("Window/NiloToonURP/Convert selected GameObjects to NiloToon", priority = 1)]
|
||||
[MenuItem("Window/NiloToonURP/[GameObject] Convert Selected GameObjects to NiloToon", priority = 1)]
|
||||
[MenuItem("Assets/NiloToon/[GameObject] Convert Selected GameObjects to NiloToon", priority = 1100 + 1)]
|
||||
public static void SetupSelectedCharacterGameObject()
|
||||
{
|
||||
var allselectedObjects = Selection.objects;
|
||||
@ -394,7 +403,8 @@ namespace NiloToon.NiloToonURP
|
||||
}
|
||||
}
|
||||
|
||||
[MenuItem("Window/NiloToonURP/Convert selected GameObjects to NiloToon", priority = 1, validate = true)]
|
||||
[MenuItem("Window/NiloToonURP/[GameObject] Convert Selected GameObjects to NiloToon", priority = 1, validate = true)]
|
||||
[MenuItem("Assets/NiloToon/[GameObject] Convert Selected GameObjects to NiloToon", priority = 1100 + 1, validate = true)]
|
||||
public static bool ValidateSetupSelectedCharacterGameObject()
|
||||
{
|
||||
var allselectedObjects = Selection.objects;
|
||||
|
||||
@ -108,6 +108,7 @@ namespace NiloToon.NiloToonURP
|
||||
return true;
|
||||
}
|
||||
|
||||
// [It seems that we can't strip a local keyword based on local keyword..?]
|
||||
// In Unity2021.3's build, this section will incorrectly strip some keyword(e.g. _MATCAP_ADD _MATCAP_BLEND _RAMP_LIGHTING_SAMPLE_UVY_TEX _SKIN_MASK_ON _SPECULARHIGHLIGHTS),
|
||||
// we now disable this section for "Unity 2021.3 or later" temporary until bug is fixed.
|
||||
/*
|
||||
@ -242,7 +243,8 @@ namespace NiloToon.NiloToonURP
|
||||
}
|
||||
|
||||
// use targetResultSetting to add keywords that we want to strip to our ignore list
|
||||
private static List<ShaderKeyword> GetStripKeywordList(Shader shader, NiloToonShaderStrippingSettingSO.Settings targetResultSetting)
|
||||
private static List<ShaderKeyword> GetStripKeywordList(Shader shader,
|
||||
NiloToonShaderStrippingSettingSO.Settings targetResultSetting)
|
||||
{
|
||||
List<ShaderKeyword> haveToStripList = new List<ShaderKeyword>();
|
||||
|
||||
@ -251,10 +253,12 @@ namespace NiloToon.NiloToonURP
|
||||
{
|
||||
haveToStripList.Add(new ShaderKeyword("_NILOTOON_DEBUG_SHADING"));
|
||||
}
|
||||
|
||||
if (!targetResultSetting.include_NILOTOON_FORCE_MINIMUM_SHADER)
|
||||
{
|
||||
haveToStripList.Add(new ShaderKeyword("_NILOTOON_FORCE_MINIMUM_SHADER"));
|
||||
}
|
||||
|
||||
if (!targetResultSetting.include_NILOTOON_GLOBAL_ENABLE_SCREENSPACE_OUTLINE)
|
||||
{
|
||||
haveToStripList.Add(new ShaderKeyword("_NILOTOON_GLOBAL_ENABLE_SCREENSPACE_OUTLINE"));
|
||||
@ -264,10 +268,12 @@ namespace NiloToon.NiloToonURP
|
||||
{
|
||||
haveToStripList.Add(new ShaderKeyword("_NILOTOON_GLOBAL_ENABLE_SCREENSPACE_OUTLINE_V2"));
|
||||
}
|
||||
|
||||
if (!targetResultSetting.include_NILOTOON_RECEIVE_URP_SHADOWMAPPING)
|
||||
{
|
||||
haveToStripList.Add(new ShaderKeyword("_NILOTOON_RECEIVE_URP_SHADOWMAPPING"));
|
||||
}
|
||||
|
||||
if (!targetResultSetting.include_NILOTOON_RECEIVE_SELF_SHADOW)
|
||||
{
|
||||
haveToStripList.Add(new ShaderKeyword("_NILOTOON_RECEIVE_SELF_SHADOW"));
|
||||
@ -298,15 +304,58 @@ namespace NiloToon.NiloToonURP
|
||||
{
|
||||
haveToStripList.Add(new ShaderKeyword(shader, "_NILOTOON_DITHER_FADEOUT"));
|
||||
}
|
||||
|
||||
if (!targetResultSetting.include_NILOTOON_DISSOLVE)
|
||||
{
|
||||
haveToStripList.Add(new ShaderKeyword(shader, "_NILOTOON_DISSOLVE"));
|
||||
}
|
||||
|
||||
if (!targetResultSetting.include_NILOTOON_PERCHARACTER_BASEMAP_OVERRIDE)
|
||||
{
|
||||
haveToStripList.Add(new ShaderKeyword(shader, "_NILOTOON_PERCHARACTER_BASEMAP_OVERRIDE"));
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------------------------------------------------------
|
||||
// [strip Fog]
|
||||
// https://docs.unity3d.com/6000.2/Documentation/Manual/urp/shader-stripping-fog.html
|
||||
// We forced dynamic_branch for fog in NiloToonCharacter.shader for Unity6.1 or higher, so no need to strip them now.
|
||||
//haveToStripList.Add(new ShaderKeyword(shader, "FOG_EXP"));
|
||||
//haveToStripList.Add(new ShaderKeyword(shader, "FOG_EXP2"));
|
||||
//haveToStripList.Add(new ShaderKeyword(shader, "FOG_LINEAR"));
|
||||
|
||||
// [strip XR]
|
||||
// By default, Unity adds this set of keywords to all graphics shader programs:
|
||||
// - STEREO_INSTANCING_ON
|
||||
// - STEREO_MULTIVIEW_ON
|
||||
// - STEREO_CUBEMAP_RENDER_ON
|
||||
// - UNITY_SINGLE_PASS_STEREO
|
||||
// we by default strip these keywords since most user are not using NiloToon for XR.
|
||||
// XR user should enable these keyword manually
|
||||
// https://docs.unity3d.com/6000.2/Documentation/Manual/shader-keywords-default.html
|
||||
if (!targetResultSetting.include_STEREO_INSTANCING_ON)
|
||||
{
|
||||
haveToStripList.Add(new ShaderKeyword(shader, "STEREO_INSTANCING_ON")); // safe to strip
|
||||
}
|
||||
if (!targetResultSetting.include_STEREO_MULTIVIEW_ON)
|
||||
{
|
||||
haveToStripList.Add(new ShaderKeyword(shader, "STEREO_MULTIVIEW_ON")); // safe to strip
|
||||
}
|
||||
if (!targetResultSetting.include_STEREO_CUBEMAP_RENDER_ON)
|
||||
{
|
||||
haveToStripList.Add(new ShaderKeyword(shader, "STEREO_CUBEMAP_RENDER_ON")); // safe to strip
|
||||
}
|
||||
if (!targetResultSetting.include_UNITY_SINGLE_PASS_STEREO)
|
||||
{
|
||||
haveToStripList.Add(new ShaderKeyword(shader, "UNITY_SINGLE_PASS_STEREO")); // safe to strip
|
||||
}
|
||||
|
||||
//haveToStripList.Add(new ShaderKeyword(shader, "_RECEIVE_URP_SHADOW")); // confirm not safe to strip a local material keyword
|
||||
//haveToStripList.Add(new ShaderKeyword(shader, "_SCREENSPACE_OUTLINE")); // confirm not safe to strip a local material keyword
|
||||
|
||||
// [URP multi_compile]
|
||||
//haveToStripList.Add(new ShaderKeyword(shader, "_MAIN_LIGHT_SHADOWS_CASCADE")); // safe to strip?
|
||||
//haveToStripList.Add(new ShaderKeyword(shader, "...")); // there are a lot of other keyword
|
||||
//----------------------------------------------------------------------------------------------------------------------------------
|
||||
return haveToStripList;
|
||||
}
|
||||
|
||||
|
||||
@ -1,12 +1,16 @@
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using UnityEditor;
|
||||
using UnityEditor.Build;
|
||||
using UnityEditor.Build.Reporting;
|
||||
using UnityEngine;
|
||||
// using System.Collections.Generic;
|
||||
// using System.IO;
|
||||
// using UnityEditor;
|
||||
// using UnityEditor.Build;
|
||||
// using UnityEditor.Build.Reporting;
|
||||
// using UnityEngine;
|
||||
|
||||
namespace LWGUI
|
||||
{
|
||||
/*
|
||||
/// <summary>
|
||||
/// Used to exclude textures referenced by ImageDrawer in Build
|
||||
/// </summary>
|
||||
public class ExcludeFromBuild : IPreprocessBuildWithReport, IPostprocessBuildWithReport
|
||||
{
|
||||
public static List<string> excludeAssetPaths = new List<string>();
|
||||
@ -106,4 +110,5 @@ namespace LWGUI
|
||||
OutputLogs();
|
||||
}
|
||||
}
|
||||
*/
|
||||
}
|
||||
@ -6,6 +6,9 @@ using UnityEngine;
|
||||
|
||||
namespace LWGUI
|
||||
{
|
||||
/// <summary>
|
||||
/// Used to listen for Shader updates and flush the LWGUI caches
|
||||
/// </summary>
|
||||
public class ShaderModifyListener : AssetPostprocessor
|
||||
{
|
||||
private static void OnPostprocessAllAssets(string[] importedAssets, string[] deletedAssets, string[] movedAssets, string[] movedFromAssetPaths)
|
||||
@ -15,7 +15,8 @@ namespace LWGUI.CustomGUISample
|
||||
[InitializeOnLoadMethod]
|
||||
private static void RegisterEvent()
|
||||
{
|
||||
LWGUI.onDrawCustomFooter += DoCustomFooter;
|
||||
// Register Event
|
||||
// LWGUI.onDrawCustomFooter += DoCustomFooter;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -15,7 +15,8 @@ namespace LWGUI.CustomGUISample
|
||||
[InitializeOnLoadMethod]
|
||||
private static void RegisterEvent()
|
||||
{
|
||||
LWGUI.onDrawCustomHeader += DoCustomHeader;
|
||||
// Register Event
|
||||
// LWGUI.onDrawCustomHeader += DoCustomHeader;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,48 @@
|
||||
using System.Linq;
|
||||
using UnityEngine;
|
||||
using UnityEditor;
|
||||
|
||||
namespace LWGUI
|
||||
{
|
||||
public static class CustomMaterialAssetFinder
|
||||
{
|
||||
public static Material FindMaterialAssetInRendererByMaterialInstance(Renderer renderer, Material materialInstance)
|
||||
{
|
||||
Material materialAsset = null;
|
||||
|
||||
// Find the material asset by name
|
||||
// if (materialAsset == null)
|
||||
// {
|
||||
// var name = materialInstance.name.Replace(" (Instance)", "");
|
||||
// var guids = AssetDatabase.FindAssets("t:Material " + name, new[] { "Assets" }).Select(guid =>
|
||||
// {
|
||||
// var assetPath = AssetDatabase.GUIDToAssetPath(guid);
|
||||
// if (string.IsNullOrEmpty(assetPath) || !assetPath.EndsWith(".mat"))
|
||||
// return null;
|
||||
// else
|
||||
// return guid;
|
||||
// }).ToArray();
|
||||
//
|
||||
// if (guids != null && guids.Length > 0)
|
||||
// {
|
||||
// var matPath = AssetDatabase.GUIDToAssetPath(guids[0]);
|
||||
// Selection.activeObject = AssetDatabase.LoadAssetAtPath<Material>(matPath);
|
||||
//
|
||||
// if (guids.Length > 1)
|
||||
// {
|
||||
// Debug.LogWarning($"LWGUI: Multiple materials with the same name were found, and the first one was selected: { matPath }");
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
return materialAsset;
|
||||
}
|
||||
|
||||
[InitializeOnLoadMethod]
|
||||
private static void RegisterEvent()
|
||||
{
|
||||
// Register Event
|
||||
// Helper.onFindMaterialAssetInRendererByMaterialInstance = FindMaterialAssetInRendererByMaterialInstance;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: d476ea1a49c64eb4a29bca60d1e97c01
|
||||
timeCreated: 1732872239
|
||||
@ -177,57 +177,22 @@ namespace LWGUI
|
||||
// Tips: Use properties to fix null reference errors
|
||||
|
||||
private static GUIStyle _guiStyles_IconButton;
|
||||
|
||||
public static GUIStyle guiStyles_IconButton
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_guiStyles_IconButton == null)
|
||||
{
|
||||
_guiStyles_IconButton = new GUIStyle(EditorStyles.iconButton) { fixedHeight = 0, fixedWidth = 0 };
|
||||
}
|
||||
return _guiStyles_IconButton;
|
||||
}
|
||||
}
|
||||
public static GUIStyle guiStyles_IconButton => _guiStyles_IconButton ?? new GUIStyle(EditorStyles.iconButton) { fixedHeight = 0, fixedWidth = 0 };
|
||||
|
||||
private static GUIStyle _guiStyle_Foldout;
|
||||
|
||||
public static GUIStyle guiStyle_Foldout
|
||||
public static GUIStyle guiStyle_Foldout => _guiStyle_Foldout ?? new GUIStyle(EditorStyles.miniButton)
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_guiStyle_Foldout == null)
|
||||
{
|
||||
_guiStyle_Foldout =
|
||||
new GUIStyle(EditorStyles.miniButton)
|
||||
{
|
||||
contentOffset = new Vector2(22, 0),
|
||||
fixedHeight = 27,
|
||||
alignment = TextAnchor.MiddleLeft,
|
||||
font = EditorStyles.boldLabel.font,
|
||||
fontSize = EditorStyles.boldLabel.fontSize + 1,
|
||||
};
|
||||
}
|
||||
return _guiStyle_Foldout;
|
||||
}
|
||||
}
|
||||
contentOffset = new Vector2(22, 0),
|
||||
fixedHeight = 27,
|
||||
alignment = TextAnchor.MiddleLeft,
|
||||
font = EditorStyles.boldLabel.font,
|
||||
fontSize = EditorStyles.boldLabel.fontSize + 1
|
||||
};
|
||||
|
||||
private static GUIStyle _guiStyle_Helpbox;
|
||||
|
||||
public static GUIStyle guiStyle_Helpbox
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_guiStyle_Helpbox == null)
|
||||
{
|
||||
_guiStyle_Helpbox = new GUIStyle(EditorStyles.helpBox) { fontSize = 12 };
|
||||
}
|
||||
return _guiStyle_Helpbox;
|
||||
}
|
||||
}
|
||||
public static GUIStyle guiStyle_Helpbox => _guiStyle_Helpbox ?? new GUIStyle(EditorStyles.helpBox) { fontSize = 12 };
|
||||
|
||||
private static GUIStyle _guiStyles_ToolbarSearchTextFieldPopup;
|
||||
|
||||
public static GUIStyle guiStyles_ToolbarSearchTextFieldPopup
|
||||
{
|
||||
get
|
||||
@ -359,8 +324,10 @@ namespace LWGUI
|
||||
}
|
||||
}
|
||||
|
||||
private static Texture _logo = AssetDatabase.LoadAssetAtPath<Texture>(AssetDatabase.GUIDToAssetPath("26b9d845eb7b1a747bf04dc84e5bcc2c"));
|
||||
private static GUIContent _logoGuiContent = new GUIContent(string.Empty, _logo,
|
||||
private static Texture _logoCache;
|
||||
private static GUIContent _logoGuiContentCache;
|
||||
private static Texture _logo => _logoCache = _logoCache ?? AssetDatabase.LoadAssetAtPath<Texture>(AssetDatabase.GUIDToAssetPath("26b9d845eb7b1a747bf04dc84e5bcc2c"));
|
||||
private static GUIContent _logoGuiContent => _logoGuiContentCache = _logoGuiContentCache ?? new GUIContent(string.Empty, _logo,
|
||||
"LWGUI (Light Weight Shader GUI)\n\n"
|
||||
+ "A Lightweight, Flexible, Powerful Unity Shader GUI system.\n\n"
|
||||
+ "Copyright (c) Jason Ma");
|
||||
@ -386,23 +353,38 @@ namespace LWGUI
|
||||
private static Material _copiedMaterial;
|
||||
private static List<string> _copiedProps = new List<string>();
|
||||
|
||||
private static Texture _iconCopy = AssetDatabase.LoadAssetAtPath<Texture>(AssetDatabase.GUIDToAssetPath("9cdef444d18d2ce4abb6bbc4fed4d109"));
|
||||
private static Texture _iconPaste = AssetDatabase.LoadAssetAtPath<Texture>(AssetDatabase.GUIDToAssetPath("8e7a78d02e4c3574998524a0842a8ccb"));
|
||||
private static Texture _iconSelect = AssetDatabase.LoadAssetAtPath<Texture>(AssetDatabase.GUIDToAssetPath("6f44e40b24300974eb607293e4224ecc"));
|
||||
private static Texture _iconCheckout = AssetDatabase.LoadAssetAtPath<Texture>(AssetDatabase.GUIDToAssetPath("72488141525eaa8499e65e52755cb6d0"));
|
||||
private static Texture _iconExpand = AssetDatabase.LoadAssetAtPath<Texture>(AssetDatabase.GUIDToAssetPath("2382450e7f4ddb94c9180d6634c41378"));
|
||||
private static Texture _iconCollapse = AssetDatabase.LoadAssetAtPath<Texture>(AssetDatabase.GUIDToAssetPath("929b6e5dfacc42b429d715a3e1ca2b57"));
|
||||
private static Texture _iconVisibility = AssetDatabase.LoadAssetAtPath<Texture>(AssetDatabase.GUIDToAssetPath("9576e23a695b35d49a9fc55c9a948b4f"));
|
||||
private const string _iconCopyGUID = "9cdef444d18d2ce4abb6bbc4fed4d109";
|
||||
private const string _iconPasteGUID = "8e7a78d02e4c3574998524a0842a8ccb";
|
||||
private const string _iconSelectGUID = "6f44e40b24300974eb607293e4224ecc";
|
||||
private const string _iconCheckoutGUID = "72488141525eaa8499e65e52755cb6d0";
|
||||
private const string _iconExpandGUID = "2382450e7f4ddb94c9180d6634c41378";
|
||||
private const string _iconCollapseGUID = "929b6e5dfacc42b429d715a3e1ca2b57";
|
||||
private const string _iconVisibilityGUID = "9576e23a695b35d49a9fc55c9a948b4f";
|
||||
|
||||
private static GUIContent _guiContentCopy = new GUIContent("", _iconCopy, "Copy Material Properties");
|
||||
private static GUIContent _guiContentPaste = new GUIContent("", _iconPaste, "Paste Material Properties\n\nRight-click to paste values by type.");
|
||||
private static GUIContent _guiContentSelect = new GUIContent("", _iconSelect, "Select the Material Asset\n\nUsed to jump from a Runtime Material Instance to a Material Asset.");
|
||||
private static GUIContent _guiContentChechout = new GUIContent("", _iconCheckout, "Checkout selected Material Assets");
|
||||
private static GUIContent _guiContentExpand = new GUIContent("", _iconExpand, "Expand All Groups");
|
||||
private static GUIContent _guiContentCollapse = new GUIContent("", _iconCollapse, "Collapse All Groups");
|
||||
private static GUIContent _guiContentVisibility = new GUIContent("", _iconVisibility, "Display Mode");
|
||||
private const string _iconCopyTooltip = "Copy Material Properties";
|
||||
private const string _iconPasteTooltip = "Paste Material Properties\n\nRight-click to paste values by type.";
|
||||
private const string _iconSelectTooltip = "Select the Material Asset\n\nUsed to jump from a Runtime Material Instance to a Material Asset.";
|
||||
private const string _iconCheckoutTooltip = "Checkout selected Material Assets";
|
||||
private const string _iconExpandTooltip = "Expand All Groups";
|
||||
private const string _iconCollapseTooltip = "Collapse All Groups";
|
||||
private const string _iconVisibilityTooltip = "Display Mode";
|
||||
|
||||
private static GUIContent _guiContentCopyCache;
|
||||
private static GUIContent _guiContentPasteCache;
|
||||
private static GUIContent _guiContentSelectCache;
|
||||
private static GUIContent _guiContentChechoutCache;
|
||||
private static GUIContent _guiContentExpandCache;
|
||||
private static GUIContent _guiContentCollapseCache;
|
||||
private static GUIContent _guiContentVisibilityCache;
|
||||
|
||||
private static GUIContent _guiContentCopy => _guiContentCopyCache = _guiContentCopyCache ?? new GUIContent("", AssetDatabase.LoadAssetAtPath<Texture>(AssetDatabase.GUIDToAssetPath(_iconCopyGUID)), _iconCopyTooltip);
|
||||
private static GUIContent _guiContentPaste => _guiContentPasteCache = _guiContentPasteCache ?? new GUIContent("", AssetDatabase.LoadAssetAtPath<Texture>(AssetDatabase.GUIDToAssetPath(_iconPasteGUID)), _iconPasteTooltip);
|
||||
private static GUIContent _guiContentSelect => _guiContentSelectCache = _guiContentSelectCache ?? new GUIContent("", AssetDatabase.LoadAssetAtPath<Texture>(AssetDatabase.GUIDToAssetPath(_iconSelectGUID)), _iconSelectTooltip);
|
||||
private static GUIContent _guiContentChechout => _guiContentChechoutCache = _guiContentChechoutCache ?? new GUIContent("", AssetDatabase.LoadAssetAtPath<Texture>(AssetDatabase.GUIDToAssetPath(_iconCheckoutGUID)), _iconCheckoutTooltip);
|
||||
private static GUIContent _guiContentExpand => _guiContentExpandCache = _guiContentExpandCache ?? new GUIContent("", AssetDatabase.LoadAssetAtPath<Texture>(AssetDatabase.GUIDToAssetPath(_iconExpandGUID)), _iconExpandTooltip);
|
||||
private static GUIContent _guiContentCollapse => _guiContentCollapseCache = _guiContentCollapseCache ?? new GUIContent("", AssetDatabase.LoadAssetAtPath<Texture>(AssetDatabase.GUIDToAssetPath(_iconCollapseGUID)), _iconCollapseTooltip);
|
||||
private static GUIContent _guiContentVisibility => _guiContentVisibilityCache = _guiContentVisibilityCache ?? new GUIContent("", AssetDatabase.LoadAssetAtPath<Texture>(AssetDatabase.GUIDToAssetPath(_iconVisibilityGUID)), _iconVisibilityTooltip);
|
||||
|
||||
private static string[] _materialInstanceNameEnd = new[] { "_Instantiated (Instance)", " (Instance)", "_Instantiated" };
|
||||
|
||||
private enum CopyMaterialValueMask
|
||||
{
|
||||
@ -547,44 +529,9 @@ namespace LWGUI
|
||||
}
|
||||
else
|
||||
{
|
||||
// Get Material Asset name
|
||||
var name = material.name;
|
||||
foreach (var nameEnd in _materialInstanceNameEnd)
|
||||
if (FindMaterialAssetByMaterialInstance(material, metaDatas, out var materialAsset))
|
||||
{
|
||||
if (name.EndsWith(nameEnd))
|
||||
{
|
||||
name = name.Substring(0, name.Length - nameEnd.Length);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Get path
|
||||
var guids = AssetDatabase.FindAssets("t:Material " + name);
|
||||
var paths = guids.Select(((guid, i) =>
|
||||
{
|
||||
var filePath = AssetDatabase.GUIDToAssetPath(guid);
|
||||
var fileName = System.IO.Path.GetFileNameWithoutExtension(filePath);
|
||||
return (fileName == name && filePath.EndsWith(".mat")) ? filePath : null;
|
||||
})).Where((s => !string.IsNullOrEmpty(s))).ToArray();
|
||||
|
||||
// Select Asset
|
||||
if (paths.Length == 0)
|
||||
{
|
||||
Debug.LogError("LWGUI: Can not find Material Assets with name: " + name);
|
||||
}
|
||||
else if (paths.Length > 1)
|
||||
{
|
||||
var str = string.Empty;
|
||||
foreach (string path in paths)
|
||||
{
|
||||
str += "\n" + path;
|
||||
}
|
||||
Debug.LogWarning("LWGUI: Multiple Material Assets with the same name have been found, select only the first one:" + str);
|
||||
Selection.activeObject = AssetDatabase.LoadAssetAtPath<Material>(paths[0]);
|
||||
}
|
||||
else
|
||||
{
|
||||
Selection.activeObject = AssetDatabase.LoadAssetAtPath<Material>(paths[0]);
|
||||
Selection.activeObject = materialAsset;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -631,16 +578,16 @@ namespace LWGUI
|
||||
if (GUI.Button(buttonRect, _guiContentVisibility, Helper.guiStyles_IconButton))
|
||||
{
|
||||
// Build Display Mode Menu Items
|
||||
string[] displayModeMenus = new[]
|
||||
var displayModeMenus = new[]
|
||||
{
|
||||
"Show All Advanced Properties (" + displayModeData.advancedCount + " of " + perShaderData.propStaticDatas.Count + ")",
|
||||
"Show All Hidden Properties (" + displayModeData.hiddenCount + " of " + perShaderData.propStaticDatas.Count + ")",
|
||||
"Show Only Modified Properties (" + perMaterialData.modifiedCount + " of " + perShaderData.propStaticDatas.Count + ")",
|
||||
"Show Only Modified Properties by Group (" + perMaterialData.modifiedCount + " of " + perShaderData.propStaticDatas.Count + ")",
|
||||
};
|
||||
bool[] enabled = new[] { true, true, true, true };
|
||||
bool[] separator = new bool[4];
|
||||
int[] selected = new[]
|
||||
var enabled = new[] { true, true, true, true };
|
||||
var separator = new bool[4];
|
||||
var selected = new[]
|
||||
{
|
||||
displayModeData.showAllAdvancedProperties ? 0 : -1,
|
||||
displayModeData.showAllHiddenProperties ? 1 : -1,
|
||||
@ -682,20 +629,46 @@ namespace LWGUI
|
||||
toolBarRect.xMin += 2;
|
||||
}
|
||||
|
||||
public static Func<Renderer, Material, Material> onFindMaterialAssetInRendererByMaterialInstance;
|
||||
|
||||
private static bool FindMaterialAssetByMaterialInstance(Material material, LWGUIMetaDatas metaDatas, out Material materialAsset)
|
||||
{
|
||||
materialAsset = null;
|
||||
|
||||
var renderers = metaDatas.perInspectorData.materialEditor.GetMeshRenderersByMaterialEditor();
|
||||
foreach (var renderer in renderers)
|
||||
{
|
||||
if (onFindMaterialAssetInRendererByMaterialInstance != null)
|
||||
{
|
||||
materialAsset = onFindMaterialAssetInRendererByMaterialInstance(renderer, material);
|
||||
}
|
||||
|
||||
if (materialAsset == null)
|
||||
{
|
||||
int index = renderer.materials.ToList().FindIndex(materialInstance => materialInstance == material);
|
||||
if (index >= 0 && index < renderer.sharedMaterials.Length)
|
||||
{
|
||||
materialAsset = renderer.sharedMaterials[index];
|
||||
}
|
||||
}
|
||||
|
||||
if (materialAsset != null && AssetDatabase.Contains(materialAsset))
|
||||
return true;
|
||||
}
|
||||
|
||||
Debug.LogError("LWGUI: Can not find the Material Assets of: " + material.name);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
#region Search Field
|
||||
|
||||
private static readonly int s_TextFieldHash = "EditorTextField".GetHashCode();
|
||||
private static readonly GUIContent[] _searchModeMenus =
|
||||
(new GUIContent[(int)SearchMode.Num]).Select(((guiContent, i) =>
|
||||
{
|
||||
if (i == (int)SearchMode.Num)
|
||||
return null;
|
||||
|
||||
return new GUIContent(((SearchMode)i).ToString());
|
||||
})).ToArray();
|
||||
private static readonly GUIContent[] _searchModeMenus = Enumerable.Range(0, (int)SearchMode.Num - 1).Select(i =>
|
||||
new GUIContent(((SearchMode)i).ToString())).ToArray();
|
||||
|
||||
/// <returns>is has changed?</returns>
|
||||
public static bool DrawSearchField(Rect rect, LWGUIMetaDatas metaDatas)
|
||||
@ -926,11 +899,16 @@ namespace LWGUI
|
||||
menus.AddSeparator("");
|
||||
foreach (var activePresetData in perMaterialData.activePresetDatas)
|
||||
{
|
||||
// Cull self
|
||||
if (activePresetData.property == prop) continue;
|
||||
|
||||
var activePreset = activePresetData.preset;
|
||||
var presetAsset = perShaderData.propStaticDatas[activePresetData.property.name].propertyPresetAsset;
|
||||
var presetPropDisplayName = perShaderData.propStaticDatas[activePresetData.property.name].displayName;
|
||||
var (presetPropStaticData, presetPropDynamicData) = metaDatas.GetPropDatas(activePresetData.property);
|
||||
var presetAsset = presetPropStaticData.propertyPresetAsset;
|
||||
var presetPropDisplayName = presetPropStaticData.displayName;
|
||||
|
||||
// Cull invisible presets
|
||||
if (!presetPropDynamicData.isShowing) continue;
|
||||
|
||||
if (activePreset.GetPropertyValue(prop.name) != null)
|
||||
{
|
||||
|
||||
@ -16,6 +16,7 @@ namespace LWGUI
|
||||
|
||||
|
||||
#region Get Prop Data
|
||||
|
||||
public PropertyStaticData GetPropStaticData(string propName) => perShaderData?.GetPropStaticData(propName);
|
||||
|
||||
public PropertyStaticData GetPropStaticData(MaterialProperty prop) => GetPropStaticData(prop.name);
|
||||
@ -27,15 +28,18 @@ namespace LWGUI
|
||||
public MaterialProperty GetProperty(string propName) => GetPropDynamicData(propName)?.property;
|
||||
|
||||
public MaterialProperty GetDefaultProperty(string propName) => GetPropDynamicData(propName)?.defualtProperty;
|
||||
|
||||
#endregion
|
||||
|
||||
#region Get Data Tuple
|
||||
|
||||
// var (perShaderData, perMaterialData, perInspectorData) =
|
||||
public (PerShaderData, PerMaterialData, PerInspectorData) GetDatas() => (perShaderData, perMaterialData, perInspectorData);
|
||||
|
||||
// var (propStaticData, propDynamicData) =
|
||||
public (PropertyStaticData, PropertyDynamicData) GetPropDatas(MaterialProperty prop) =>
|
||||
(GetPropStaticData(prop), GetPropDynamicData(prop));
|
||||
|
||||
#endregion
|
||||
|
||||
public MaterialProperty[] GetProps() => perMaterialData.props;
|
||||
@ -45,12 +49,6 @@ namespace LWGUI
|
||||
public Shader GetShader() => perShaderData.shader;
|
||||
|
||||
public MaterialEditor GetMaterialEditor() => perInspectorData.materialEditor;
|
||||
|
||||
public void OnValidate()
|
||||
{
|
||||
MaterialEditor.ApplyMaterialPropertyDrawers(GetMaterialEditor()?.targets);
|
||||
MetaDataHelper.ForceUpdateMaterialsMetadataCache(GetMaterialEditor()?.targets);
|
||||
}
|
||||
}
|
||||
|
||||
public class MetaDataHelper
|
||||
@ -167,24 +165,6 @@ namespace LWGUI
|
||||
return str;
|
||||
}
|
||||
|
||||
private static readonly string _tooltipString = "#";
|
||||
private static readonly string _helpboxString = "%";
|
||||
|
||||
public static string GetPropertyDisplayName(Shader shader, MaterialProperty prop)
|
||||
{
|
||||
var tooltipIndex = prop.displayName.IndexOf(_tooltipString, StringComparison.Ordinal);
|
||||
var helpboxIndex = prop.displayName.IndexOf(_helpboxString, StringComparison.Ordinal);
|
||||
var minIndex = tooltipIndex == -1 ? helpboxIndex : tooltipIndex;
|
||||
if (tooltipIndex != -1 && helpboxIndex != -1)
|
||||
minIndex = Mathf.Min(minIndex, helpboxIndex);
|
||||
if (minIndex == -1)
|
||||
return prop.displayName;
|
||||
else if (minIndex == 0)
|
||||
return string.Empty;
|
||||
else
|
||||
return prop.displayName.Substring(0, minIndex);
|
||||
}
|
||||
|
||||
public static bool GetPropertyVisibility(MaterialProperty prop, Material material, LWGUIMetaDatas metaDatas)
|
||||
{
|
||||
bool result = true;
|
||||
@ -218,16 +198,14 @@ namespace LWGUI
|
||||
|
||||
public static bool GetParentPropertyVisibility(PropertyStaticData parentPropStaticData, Material material, LWGUIMetaDatas metaDatas)
|
||||
{
|
||||
bool result = true;
|
||||
|
||||
if (parentPropStaticData != null
|
||||
&& (!metaDatas.GetPropStaticData(parentPropStaticData.name).isExpanding
|
||||
|| !MetaDataHelper.GetPropertyVisibility(metaDatas.GetProperty(parentPropStaticData.name), material, metaDatas)))
|
||||
|| !GetPropertyVisibility(metaDatas.GetProperty(parentPropStaticData.name), material, metaDatas)))
|
||||
{
|
||||
result = false;
|
||||
return false;
|
||||
}
|
||||
|
||||
return result;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -45,6 +45,9 @@ namespace LWGUI
|
||||
|
||||
public static ShaderPropertyPreset GetPresetFile(string presetFileName)
|
||||
{
|
||||
if (string.IsNullOrEmpty(presetFileName))
|
||||
return null;
|
||||
|
||||
if (!_loadedPresets.ContainsKey(presetFileName) || !_loadedPresets[presetFileName])
|
||||
ForceInit();
|
||||
|
||||
@ -60,11 +63,10 @@ namespace LWGUI
|
||||
// For Developers: Call this after a material has modified in code
|
||||
public static void ApplyPresetsInMaterial(Material material)
|
||||
{
|
||||
var props = MaterialEditor.GetMaterialProperties(new[] { material });
|
||||
var props = MaterialEditor.GetMaterialProperties(new UnityEngine.Object[] { material });
|
||||
foreach (var prop in props)
|
||||
{
|
||||
List<MaterialPropertyDrawer> decoratorDrawers;
|
||||
var drawer = ReflectionHelper.GetPropertyDrawer(material.shader, prop, out decoratorDrawers);
|
||||
var drawer = ReflectionHelper.GetPropertyDrawer(material.shader, prop, out _);
|
||||
|
||||
// Apply active preset
|
||||
if (drawer != null && drawer is IBasePresetDrawer)
|
||||
@ -73,9 +75,8 @@ namespace LWGUI
|
||||
if (activePreset != null)
|
||||
activePreset.ApplyToDefaultMaterial(material);
|
||||
}
|
||||
|
||||
}
|
||||
MaterialEditor.ApplyMaterialPropertyDrawers(material);
|
||||
UnityEditorExtension.ApplyMaterialPropertyAndDecoratorDrawers(material);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -2,27 +2,20 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using LWGUI.LwguiGradientEditor;
|
||||
using LWGUI.Runtime.LwguiGradient;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
using Object = UnityEngine.Object;
|
||||
|
||||
namespace LWGUI
|
||||
{
|
||||
public class RampHelper
|
||||
public static class RampHelper
|
||||
{
|
||||
#region RampEditor
|
||||
|
||||
public static readonly string projectPath = Application.dataPath.Substring(0, Application.dataPath.Length - 6);
|
||||
|
||||
public static string lastSavePath
|
||||
{
|
||||
get { return EditorPrefs.GetString("LWGUI_GradientSavePath_" + Application.version, Application.dataPath); }
|
||||
set
|
||||
{
|
||||
if (value.Contains(projectPath))
|
||||
EditorPrefs.SetString("LWGUI_GradientSavePath_" + Application.version, value);
|
||||
}
|
||||
}
|
||||
|
||||
private static readonly GUIContent _iconAdd = new GUIContent(EditorGUIUtility.IconContent("d_Toolbar Plus").image, "Add"),
|
||||
_iconEdit = new GUIContent(EditorGUIUtility.IconContent("editicon.sml").image, "Edit"),
|
||||
@ -30,22 +23,27 @@ namespace LWGUI
|
||||
_iconSave = new GUIContent(EditorGUIUtility.IconContent("SaveActive").image, "Save");
|
||||
|
||||
public static bool RampEditor(
|
||||
Rect buttonRect,
|
||||
MaterialProperty prop,
|
||||
SerializedProperty serializedProperty,
|
||||
bool isLinear,
|
||||
bool isDirty,
|
||||
string defaultFileName,
|
||||
string rootPath,
|
||||
int defaultWidth,
|
||||
int defaultHeight,
|
||||
out Texture2D newTexture,
|
||||
out bool doSave,
|
||||
out bool doDiscard)
|
||||
Rect buttonRect,
|
||||
MaterialProperty prop,
|
||||
ref LwguiGradient gradient,
|
||||
ColorSpace colorSpace,
|
||||
LwguiGradient.ChannelMask viewChannelMask,
|
||||
LwguiGradient.GradientTimeRange timeRange,
|
||||
bool isDirty,
|
||||
string defaultFileName,
|
||||
string rootPath,
|
||||
int defaultWidth,
|
||||
int defaultHeight,
|
||||
out bool doRegisterUndo,
|
||||
out Texture2D newTexture,
|
||||
out bool doSave,
|
||||
out bool doDiscard
|
||||
)
|
||||
{
|
||||
newTexture = null;
|
||||
var hasChange = false;
|
||||
var shouldCreate = false;
|
||||
var doOpenWindow = false;
|
||||
var singleButtonWidth = buttonRect.width * 0.25f;
|
||||
var editRect = new Rect(buttonRect.x + singleButtonWidth * 0, buttonRect.y, singleButtonWidth, buttonRect.height);
|
||||
var saveRect = new Rect(buttonRect.x + singleButtonWidth * 1, buttonRect.y, singleButtonWidth, buttonRect.height);
|
||||
@ -53,38 +51,30 @@ namespace LWGUI
|
||||
var discardRect = new Rect(buttonRect.x + singleButtonWidth * 3, buttonRect.y, singleButtonWidth, buttonRect.height);
|
||||
|
||||
// Edit button event
|
||||
var currEvent = Event.current;
|
||||
if (currEvent.type == EventType.MouseDown && editRect.Contains(currEvent.mousePosition))
|
||||
{
|
||||
// if the current edited texture is null, create new one
|
||||
if (prop.textureValue == null)
|
||||
{
|
||||
shouldCreate = true;
|
||||
currEvent.Use();
|
||||
}
|
||||
else
|
||||
{
|
||||
// Undo.RecordObject(prop.textureValue, "Edit Gradient");
|
||||
}
|
||||
}
|
||||
|
||||
// Gradient Editor
|
||||
if (GUI.enabled)
|
||||
{
|
||||
var gradientPropertyRect = new Rect(editRect.x + 2, editRect.y + 2, editRect.width - 2, editRect.height - 2);
|
||||
EditorGUI.BeginChangeCheck();
|
||||
EditorGUI.PropertyField(gradientPropertyRect, serializedProperty, GUIContent.none);
|
||||
LwguiGradientEditorHelper.GradientEditButton(editRect, _iconEdit, gradient, colorSpace, viewChannelMask, timeRange, () =>
|
||||
{
|
||||
// if the current edited texture is null, create new one
|
||||
if (prop.textureValue == null)
|
||||
{
|
||||
shouldCreate = true;
|
||||
Event.current.Use();
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
doOpenWindow = true;
|
||||
return true;
|
||||
}
|
||||
});
|
||||
if (EditorGUI.EndChangeCheck())
|
||||
{
|
||||
hasChange = true;
|
||||
gradient = LwguiGradientWindow.instance.lwguiGradient;
|
||||
}
|
||||
}
|
||||
|
||||
// Edit button overlay
|
||||
if (currEvent.type == EventType.Repaint)
|
||||
{
|
||||
var isHover = editRect.Contains(currEvent.mousePosition);
|
||||
(new GUIStyle("button")).Draw(editRect, _iconEdit, isHover, false, false, false);
|
||||
doRegisterUndo = doOpenWindow;
|
||||
}
|
||||
|
||||
// Create button
|
||||
@ -101,7 +91,7 @@ namespace LWGUI
|
||||
{
|
||||
//Create texture and save PNG
|
||||
var saveUnityPath = absPath.Replace(projectPath, String.Empty);
|
||||
CreateAndSaveNewGradientTexture(defaultWidth, defaultHeight, saveUnityPath, isLinear);
|
||||
CreateAndSaveNewGradientTexture(defaultWidth, defaultHeight, saveUnityPath, colorSpace == ColorSpace.Linear);
|
||||
// VersionControlHelper.Add(saveUnityPath);
|
||||
//Load created texture
|
||||
newTexture = AssetDatabase.LoadAssetAtPath<Texture2D>(saveUnityPath);
|
||||
@ -120,11 +110,13 @@ namespace LWGUI
|
||||
}
|
||||
|
||||
// Save button
|
||||
var color = GUI.color;
|
||||
if (isDirty) GUI.color = Color.yellow;
|
||||
doSave = GUI.Button(saveRect, _iconSave);
|
||||
GUI.color = color;
|
||||
|
||||
{
|
||||
var color = GUI.color;
|
||||
if (isDirty) GUI.color = Color.yellow;
|
||||
doSave = GUI.Button(saveRect, _iconSave);
|
||||
GUI.color = color;
|
||||
}
|
||||
|
||||
// Discard button
|
||||
doDiscard = GUI.Button(discardRect, _iconDiscard);
|
||||
|
||||
@ -133,17 +125,20 @@ namespace LWGUI
|
||||
|
||||
public static bool HasGradient(AssetImporter assetImporter) { return assetImporter.userData.Contains("#");}
|
||||
|
||||
public static Gradient GetGradientFromTexture(Texture texture, out bool isDirty, bool doReimport = false)
|
||||
public static LwguiGradient GetGradientFromTexture(Texture texture, out bool isDirty, bool doDiscard = false, bool doRegisterUndo = false)
|
||||
{
|
||||
isDirty = false;
|
||||
if (texture == null) return null;
|
||||
|
||||
var assetImporter = AssetImporter.GetAtPath(AssetDatabase.GetAssetPath(texture));
|
||||
if (doRegisterUndo)
|
||||
{
|
||||
LwguiGradientWindow.RegisterRampMapUndo(texture, assetImporter);
|
||||
}
|
||||
if (assetImporter != null && HasGradient(assetImporter))
|
||||
{
|
||||
GradientObject savedGradientObject, editingGradientObject;
|
||||
isDirty = DecodeGradientFromJSON(assetImporter.userData, out savedGradientObject, out editingGradientObject);
|
||||
var outGradient = doReimport ? savedGradientObject.gradient : editingGradientObject.gradient;
|
||||
isDirty = DecodeGradientFromJSON(assetImporter.userData, out var savedGradient, out var editingGradient);
|
||||
var outGradient = doDiscard ? savedGradient : editingGradient;
|
||||
return outGradient;
|
||||
}
|
||||
else
|
||||
@ -156,25 +151,25 @@ namespace LWGUI
|
||||
}
|
||||
}
|
||||
|
||||
public static void SetGradientToTexture(Texture texture, GradientObject gradientObject, bool doSaveToDisk = false)
|
||||
public static void SetGradientToTexture(Texture texture, LwguiGradient gradient, bool doSaveToDisk = false)
|
||||
{
|
||||
if (texture == null || gradientObject.gradient == null) return;
|
||||
if (texture == null || gradient == null) return;
|
||||
|
||||
var texture2D = (Texture2D)texture;
|
||||
var path = AssetDatabase.GetAssetPath(texture);
|
||||
var assetImporter = AssetImporter.GetAtPath(path);
|
||||
VersionControlHelper.Checkout(texture2D);
|
||||
Undo.RecordObject(texture2D, "LWGUI: Set Gradient To Texture");
|
||||
|
||||
LwguiGradientWindow.RegisterRampMapUndo(texture2D, assetImporter);
|
||||
|
||||
// Save to texture
|
||||
var path = AssetDatabase.GetAssetPath(texture);
|
||||
var pixels = GetPixelsFromGradient(gradientObject.gradient, texture.width, texture.height);
|
||||
texture2D.SetPixels32(pixels);
|
||||
var pixels = gradient.GetPixels(texture.width, texture.height);
|
||||
texture2D.SetPixels(pixels);
|
||||
texture2D.Apply();
|
||||
|
||||
// Save gradient JSON to userData
|
||||
var assetImporter = AssetImporter.GetAtPath(path);
|
||||
GradientObject savedGradientObject, editingGradientObject;
|
||||
DecodeGradientFromJSON(assetImporter.userData, out savedGradientObject, out editingGradientObject);
|
||||
assetImporter.userData = EncodeGradientToJSON(doSaveToDisk ? gradientObject : savedGradientObject, gradientObject);
|
||||
DecodeGradientFromJSON(assetImporter.userData, out var savedGradient, out _);
|
||||
assetImporter.userData = EncodeGradientToJSON(doSaveToDisk ? gradient : savedGradient, gradient);
|
||||
|
||||
// Save texture to disk
|
||||
if (doSaveToDisk)
|
||||
@ -186,39 +181,52 @@ namespace LWGUI
|
||||
}
|
||||
}
|
||||
|
||||
private static string EncodeGradientToJSON(GradientObject savedGradientObject, GradientObject editingGradientObject)
|
||||
private static string EncodeGradientToJSON(LwguiGradient savedGradient, LwguiGradient editingGradient)
|
||||
{
|
||||
string savedJSON = " ", editingJSON = " ";
|
||||
if (savedGradientObject != null)
|
||||
savedJSON = EditorJsonUtility.ToJson(savedGradientObject);
|
||||
if (editingGradientObject != null)
|
||||
editingJSON = EditorJsonUtility.ToJson(editingGradientObject);
|
||||
if (savedGradient != null)
|
||||
savedJSON = EditorJsonUtility.ToJson(savedGradient);
|
||||
if (editingGradient != null)
|
||||
editingJSON = EditorJsonUtility.ToJson(editingGradient);
|
||||
|
||||
return savedJSON + "#" + editingJSON;
|
||||
}
|
||||
|
||||
private static bool DecodeGradientFromJSON(string json, out GradientObject savedGradientObject, out GradientObject editingGradientObject)
|
||||
private static bool DecodeGradientFromJSON(string json, out LwguiGradient savedGradient, out LwguiGradient editingGradient)
|
||||
{
|
||||
savedGradient = new LwguiGradient();
|
||||
editingGradient = new LwguiGradient();
|
||||
|
||||
var isLegacyJSON = json.Contains("MonoBehaviour");
|
||||
var subJSONs = json.Split('#');
|
||||
savedGradientObject = ScriptableObject.CreateInstance<GradientObject>();
|
||||
if (subJSONs[0] != " ")
|
||||
EditorJsonUtility.FromJsonOverwrite(subJSONs[0], savedGradientObject);
|
||||
editingGradientObject = ScriptableObject.CreateInstance<GradientObject>();
|
||||
if (subJSONs[1] != " ")
|
||||
EditorJsonUtility.FromJsonOverwrite(subJSONs[1], editingGradientObject);
|
||||
|
||||
// Upgrading from deprecated GradientObject to LwguiGradient
|
||||
if (isLegacyJSON)
|
||||
{
|
||||
var savedGradientLegacy = ScriptableObject.CreateInstance<GradientObject>();
|
||||
var editingGradientLegacy = ScriptableObject.CreateInstance<GradientObject>();
|
||||
|
||||
EditorJsonUtility.FromJsonOverwrite(subJSONs[0], savedGradientLegacy);
|
||||
EditorJsonUtility.FromJsonOverwrite(subJSONs[1], editingGradientLegacy);
|
||||
|
||||
savedGradient = LwguiGradient.FromGradient(savedGradientLegacy.gradient);
|
||||
editingGradient = LwguiGradient.FromGradient(editingGradientLegacy.gradient);
|
||||
}
|
||||
else
|
||||
{
|
||||
EditorJsonUtility.FromJsonOverwrite(subJSONs[0], savedGradient);
|
||||
EditorJsonUtility.FromJsonOverwrite(subJSONs[1], editingGradient);
|
||||
}
|
||||
|
||||
return subJSONs[0] != subJSONs[1];
|
||||
}
|
||||
|
||||
public static bool CreateAndSaveNewGradientTexture(int width, int height, string unityPath, bool isLinear)
|
||||
{
|
||||
var gradientObject = ScriptableObject.CreateInstance<GradientObject>();
|
||||
gradientObject.gradient = new Gradient();
|
||||
gradientObject.gradient.colorKeys = new[] { new GradientColorKey(Color.black, 0.0f), new GradientColorKey(Color.white, 1.0f) };
|
||||
gradientObject.gradient.alphaKeys = new[] { new GradientAlphaKey(1f, 0f), new GradientAlphaKey(1f, 1f) };
|
||||
var gradient = new LwguiGradient();
|
||||
|
||||
var ramp = CreateGradientTexture(gradientObject.gradient, width, height);
|
||||
var ramp = gradient.GetPreviewRampTexture(width, height, ColorSpace.Linear);
|
||||
var png = ramp.EncodeToPNG();
|
||||
Object.DestroyImmediate(ramp);
|
||||
|
||||
var systemPath = projectPath + unityPath;
|
||||
File.WriteAllBytes(systemPath, png);
|
||||
@ -238,44 +246,18 @@ namespace LWGUI
|
||||
textureImporter.SetPlatformTextureSettings(platformTextureSettings);
|
||||
|
||||
//Gradient data embedded in userData
|
||||
textureImporter.userData = EncodeGradientToJSON(gradientObject, gradientObject);
|
||||
textureImporter.userData = EncodeGradientToJSON(gradient, gradient);
|
||||
textureImporter.SaveAndReimport();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private static Texture2D CreateGradientTexture(Gradient gradient, int width, int height)
|
||||
{
|
||||
var ramp = new Texture2D(width, height, TextureFormat.RGBA32, true, true);
|
||||
var colors = GetPixelsFromGradient(gradient, width, height);
|
||||
ramp.SetPixels32(colors);
|
||||
ramp.Apply();
|
||||
return ramp;
|
||||
}
|
||||
|
||||
private static Color32[] GetPixelsFromGradient(Gradient gradient, int width, int height)
|
||||
{
|
||||
var pixels = new Color32[width * height];
|
||||
for (var x = 0; x < width; x++)
|
||||
{
|
||||
var delta = x / (float)width;
|
||||
if (delta < 0) delta = 0;
|
||||
if (delta > 1) delta = 1;
|
||||
var col = gradient.Evaluate(delta);
|
||||
for (int i = 0; i < height; i++)
|
||||
{
|
||||
pixels[x + i * width] = col;
|
||||
}
|
||||
}
|
||||
return pixels;
|
||||
}
|
||||
#endregion
|
||||
|
||||
|
||||
#region RampSelector
|
||||
public delegate void SwitchRampMapEvent(Texture2D selectedRamp);
|
||||
|
||||
public static void RampSelector(Rect rect, string rootPath, SwitchRampMapEvent switchRampMapEvent)
|
||||
public static void RampSelector(Rect rect, string rootPath, Action<Texture2D> switchRampMapEvent)
|
||||
{
|
||||
var e = Event.current;
|
||||
if (e.type == UnityEngine.EventType.MouseDown && rect.Contains(e.mousePosition))
|
||||
@ -301,11 +283,11 @@ namespace LWGUI
|
||||
|
||||
public class RampSelectorWindow : EditorWindow
|
||||
{
|
||||
private Texture2D[] _rampMaps;
|
||||
private Vector2 _scrollPosition;
|
||||
private RampHelper.SwitchRampMapEvent _switchRampMapEvent;
|
||||
private Texture2D[] _rampMaps;
|
||||
private Vector2 _scrollPosition;
|
||||
private Action<Texture2D> _switchRampMapEvent;
|
||||
|
||||
public static void ShowWindow(Rect rect, Texture2D[] rampMaps, RampHelper.SwitchRampMapEvent switchRampMapEvent)
|
||||
public static void ShowWindow(Rect rect, Texture2D[] rampMaps, Action<Texture2D> switchRampMapEvent)
|
||||
{
|
||||
RampSelectorWindow window = ScriptableObject.CreateInstance<RampSelectorWindow>();
|
||||
window.titleContent = new GUIContent("Ramp Selector");
|
||||
|
||||
@ -1,158 +0,0 @@
|
||||
// Copyright (c) Jason Ma
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
|
||||
namespace LWGUI
|
||||
{
|
||||
public class ReflectionHelper
|
||||
{
|
||||
private static Assembly UnityEditor_Assembly = Assembly.GetAssembly(typeof(Editor));
|
||||
|
||||
|
||||
#region MaterialPropertyHandler
|
||||
|
||||
private static Type MaterialPropertyHandler_Type = UnityEditor_Assembly.GetType("UnityEditor.MaterialPropertyHandler");
|
||||
private static MethodInfo MaterialPropertyHandler_GetHandler_Method = MaterialPropertyHandler_Type.GetMethod("GetHandler", BindingFlags.Static | BindingFlags.NonPublic);
|
||||
private static PropertyInfo MaterialPropertyHandler_PropertyDrawer_Property = MaterialPropertyHandler_Type.GetProperty("propertyDrawer");
|
||||
private static FieldInfo MaterialPropertyHandler_DecoratorDrawers_Field = MaterialPropertyHandler_Type.GetField("m_DecoratorDrawers", BindingFlags.NonPublic | BindingFlags.Instance);
|
||||
|
||||
public static MaterialPropertyDrawer GetPropertyDrawer(Shader shader, MaterialProperty prop, out List<MaterialPropertyDrawer> decoratorDrawers)
|
||||
{
|
||||
decoratorDrawers = new List<MaterialPropertyDrawer>();
|
||||
var handler = MaterialPropertyHandler_GetHandler_Method.Invoke(null, new System.Object[] { shader, prop.name });
|
||||
if (handler != null && handler.GetType() == MaterialPropertyHandler_Type)
|
||||
{
|
||||
decoratorDrawers = MaterialPropertyHandler_DecoratorDrawers_Field.GetValue(handler) as List<MaterialPropertyDrawer>;
|
||||
return MaterialPropertyHandler_PropertyDrawer_Property.GetValue(handler, null) as MaterialPropertyDrawer;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static MaterialPropertyDrawer GetPropertyDrawer(Shader shader, MaterialProperty prop)
|
||||
{
|
||||
List<MaterialPropertyDrawer> decoratorDrawers;
|
||||
return GetPropertyDrawer(shader, prop, out decoratorDrawers);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
#region MaterialEditor
|
||||
|
||||
private static Type MaterialEditor_Type = typeof(MaterialEditor);
|
||||
private static MethodInfo MaterialEditor_DoPowerRangeProperty_Method = MaterialEditor_Type.GetMethod("DoPowerRangeProperty", BindingFlags.Static | BindingFlags.NonPublic);
|
||||
private static MethodInfo MaterialEditor_DefaultShaderPropertyInternal_Method = MaterialEditor_Type.GetMethod("DefaultShaderPropertyInternal", BindingFlags.NonPublic | BindingFlags.Instance, null,
|
||||
new[] { typeof(Rect), typeof(MaterialProperty), typeof(GUIContent) }, null);
|
||||
|
||||
public static float DoPowerRangeProperty(Rect position, MaterialProperty prop, GUIContent label, float power)
|
||||
{
|
||||
return (float)MaterialEditor_DoPowerRangeProperty_Method.Invoke(null, new System.Object[] { position, prop, label, power });
|
||||
}
|
||||
|
||||
public static void DefaultShaderPropertyInternal(MaterialEditor editor, Rect position, MaterialProperty prop, GUIContent label)
|
||||
{
|
||||
MaterialEditor_DefaultShaderPropertyInternal_Method.Invoke(editor, new System.Object[] { position, prop, label });
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
#region EditorUtility
|
||||
private static Type EditorUtility_Type = typeof(EditorUtility);
|
||||
private static MethodInfo EditorUtility_DisplayCustomMenuWithSeparators_Method = EditorUtility_Type.GetMethod("DisplayCustomMenuWithSeparators", BindingFlags.NonPublic | BindingFlags.Static, null,
|
||||
new []{typeof(Rect), typeof(string[]), typeof(bool[]), typeof(bool[]), typeof(int[]), typeof(EditorUtility.SelectMenuItemFunction), typeof(object), typeof(bool)}, null);
|
||||
|
||||
public static void DisplayCustomMenuWithSeparators(Rect position, string[] options, bool[] enabled, bool[] separator, int[] selected, EditorUtility.SelectMenuItemFunction callback, object userData = null, bool showHotkey = false)
|
||||
{
|
||||
EditorUtility_DisplayCustomMenuWithSeparators_Method.Invoke(null, new System.Object[] { position, options, enabled, separator, selected, callback, userData, showHotkey });
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
#region EditorGUI
|
||||
|
||||
private static Type EditorGUI_Type = typeof(EditorGUI);
|
||||
private static PropertyInfo EditorGUI_Indent_Property = EditorGUI_Type.GetProperty("indent", BindingFlags.NonPublic | BindingFlags.Static);
|
||||
|
||||
public static float EditorGUI_Indent { get { return (float)EditorGUI_Indent_Property.GetValue(null, null); } }
|
||||
|
||||
#endregion
|
||||
|
||||
#region EditorGUILayout
|
||||
|
||||
private static Type EditorGUILayout_Type = typeof(EditorGUILayout);
|
||||
private static PropertyInfo EditorGUILayout_kLabelFloatMinW_Property = EditorGUILayout_Type.GetProperty("kLabelFloatMinW", BindingFlags.NonPublic | BindingFlags.Static);
|
||||
|
||||
public static float EditorGUILayout_kLabelFloatMinW { get { return (float)EditorGUILayout_kLabelFloatMinW_Property.GetValue(null, null); } }
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
#region MaterialEnumDrawer
|
||||
|
||||
// UnityEditor.MaterialEnumDrawer(string enumName)
|
||||
private static System.Type[] _types;
|
||||
|
||||
public static System.Type[] GetAllTypes()
|
||||
{
|
||||
if (_types == null)
|
||||
{
|
||||
_types = ((IEnumerable<Assembly>)AppDomain.CurrentDomain.GetAssemblies())
|
||||
.SelectMany<Assembly, System.Type>((Func<Assembly, IEnumerable<System.Type>>)
|
||||
(assembly =>
|
||||
{
|
||||
if (assembly == null)
|
||||
return (IEnumerable<System.Type>)(new System.Type[0]);
|
||||
try
|
||||
{
|
||||
return (IEnumerable<System.Type>)assembly.GetTypes();
|
||||
}
|
||||
catch (ReflectionTypeLoadException ex)
|
||||
{
|
||||
Debug.LogError(ex);
|
||||
return (IEnumerable<System.Type>)(new System.Type[0]);
|
||||
}
|
||||
})).ToArray<System.Type>();
|
||||
}
|
||||
return _types;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
#region MaterialProperty.PropertyData
|
||||
|
||||
#if UNITY_2022_1_OR_NEWER
|
||||
private static Type MaterialProperty_Type = typeof(MaterialProperty);
|
||||
private static Type PropertyData_Type = MaterialProperty_Type.GetNestedType("PropertyData", BindingFlags.NonPublic);
|
||||
// MergeStack(out bool lockedInChildren, out bool lockedByAncestor, out bool overriden)
|
||||
private static MethodInfo PropertyData_MergeStack_Method = PropertyData_Type.GetMethod("MergeStack", BindingFlags.Static | BindingFlags.NonPublic);
|
||||
// HandleApplyRevert(GenericMenu menu, bool singleEditing, UnityEngine.Object[] targets)
|
||||
private static MethodInfo PropertyData_HandleApplyRevert_Method = PropertyData_Type.GetMethod("HandleApplyRevert", BindingFlags.Static | BindingFlags.NonPublic);
|
||||
|
||||
public static void HandleApplyRevert(GenericMenu menu, MaterialProperty prop)
|
||||
{
|
||||
System.Object[] parameters = new System.Object[3];
|
||||
ReflectionHelper.PropertyData_MergeStack_Method.Invoke(null, parameters);
|
||||
bool lockedInChildren = (bool)parameters[0];
|
||||
bool lockedByAncestor = (bool)parameters[1];
|
||||
bool overriden = (bool)parameters[2];
|
||||
bool singleEditing = prop.targets.Length == 1;
|
||||
|
||||
if (overriden)
|
||||
{
|
||||
ReflectionHelper.PropertyData_HandleApplyRevert_Method.Invoke(null, new System.Object[]{menu, singleEditing, prop.targets});
|
||||
menu.AddSeparator("");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@ -160,7 +160,8 @@ namespace LWGUI
|
||||
}
|
||||
}
|
||||
|
||||
private static readonly Texture _icon = AssetDatabase.LoadAssetAtPath<Texture>(AssetDatabase.GUIDToAssetPath("e7bc1130858d984488bca32b8512ca96"));
|
||||
private static Texture _iconCache;
|
||||
private static Texture _icon => _iconCache = _iconCache ?? AssetDatabase.LoadAssetAtPath<Texture>(AssetDatabase.GUIDToAssetPath("e7bc1130858d984488bca32b8512ca96"));
|
||||
|
||||
public static bool DrawRevertButton(Rect rect)
|
||||
{
|
||||
|
||||
@ -11,7 +11,7 @@ namespace LWGUI
|
||||
{
|
||||
public class VersionControlHelper
|
||||
{
|
||||
public static bool isVCEnabled { get { return Provider.enabled && Provider.isActive; } }
|
||||
public static bool isVCEnabled => Provider.enabled && Provider.isActive;
|
||||
|
||||
public static bool Checkout(UnityEngine.Object obj)
|
||||
{
|
||||
|
||||
@ -1,7 +1,10 @@
|
||||
{
|
||||
"name": "LWGUI",
|
||||
"rootNamespace": "",
|
||||
"references": [],
|
||||
"references": [
|
||||
"LWGUI.Runtime",
|
||||
"Unity.InternalAPIEditorBridge.020"
|
||||
],
|
||||
"includePlatforms": [
|
||||
"Editor"
|
||||
],
|
||||
|
||||
@ -132,10 +132,11 @@ namespace LWGUI
|
||||
|
||||
private void DrawAdvancedHeader(PropertyStaticData propStaticData, MaterialProperty prop)
|
||||
{
|
||||
EditorGUILayout.Space(3);
|
||||
var rect = EditorGUILayout.GetControlRect();
|
||||
var revertButtonRect = RevertableHelper.SplitRevertButtonRect(ref rect);
|
||||
var label = string.IsNullOrEmpty(propStaticData.advancedHeaderString) ? "Advanced" : propStaticData.advancedHeaderString;
|
||||
propStaticData.isExpanding = EditorGUI.Foldout(rect, propStaticData.isExpanding, label);
|
||||
propStaticData.isExpanding = EditorGUI.Foldout(rect, propStaticData.isExpanding, label, EditorStyles.foldoutHeader);
|
||||
if (Event.current.type == EventType.MouseDown && Event.current.button == 0 && rect.Contains(Event.current.mousePosition))
|
||||
propStaticData.isExpanding = !propStaticData.isExpanding;
|
||||
RevertableHelper.DrawRevertableProperty(revertButtonRect, prop, metaDatas, true);
|
||||
@ -146,6 +147,9 @@ namespace LWGUI
|
||||
{
|
||||
var (propStaticData, propDynamicData) = metaDatas.GetPropDatas(prop);
|
||||
var materialEditor = metaDatas.GetMaterialEditor();
|
||||
|
||||
if (propStaticData.isAdvancedHeaderProperty)
|
||||
EditorGUILayout.Space(3);
|
||||
|
||||
Helper.DrawHelpbox(propStaticData, propDynamicData);
|
||||
|
||||
@ -181,11 +185,32 @@ namespace LWGUI
|
||||
MetaDataHelper.ReleaseMaterialMetadataCache(material);
|
||||
}
|
||||
|
||||
// Called after editing the material
|
||||
public static void OnValidate(Object[] materials)
|
||||
{
|
||||
UnityEditorExtension.ApplyMaterialPropertyAndDecoratorDrawers(materials);
|
||||
MetaDataHelper.ForceUpdateMaterialsMetadataCache(materials);
|
||||
}
|
||||
|
||||
// Called after edit in code
|
||||
public static void OnValidate(LWGUIMetaDatas metaDatas)
|
||||
{
|
||||
OnValidate(metaDatas?.GetMaterialEditor()?.targets);
|
||||
}
|
||||
|
||||
// Called after edit or undo
|
||||
public override void ValidateMaterial(Material material)
|
||||
{
|
||||
base.ValidateMaterial(material);
|
||||
metaDatas?.OnValidate();
|
||||
// Undo
|
||||
if (metaDatas == null)
|
||||
{
|
||||
OnValidate(new Object[] { material });
|
||||
}
|
||||
// Edit
|
||||
else
|
||||
{
|
||||
OnValidate(metaDatas);
|
||||
}
|
||||
}
|
||||
}
|
||||
} //namespace LWGUI
|
||||
@ -62,10 +62,15 @@ namespace LWGUI
|
||||
// Get active presets
|
||||
foreach (var prop in props)
|
||||
{
|
||||
var activePreset = perShaderData.propStaticDatas[prop.name].presetDrawer
|
||||
?.GetActivePreset(prop, perShaderData.propStaticDatas[prop.name].propertyPresetAsset);
|
||||
if (activePreset != null)
|
||||
var propStaticData = perShaderData.propStaticDatas[prop.name];
|
||||
var activePreset = propStaticData.presetDrawer?.GetActivePreset(prop, propStaticData.propertyPresetAsset);
|
||||
if (activePreset != null
|
||||
// Filter invisible preset properties
|
||||
&& (propStaticData.showIfDatas.Count == 0
|
||||
|| ShowIfDecorator.GetShowIfResultFromMaterial(propStaticData.showIfDatas, this.material)))
|
||||
{
|
||||
activePresetDatas.Add(new PersetDynamicData(activePreset, prop));
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
@ -85,16 +90,6 @@ namespace LWGUI
|
||||
var defaultProperties = MaterialEditor.GetMaterialProperties(new[] { defaultMaterial });
|
||||
Debug.Assert(defaultProperties.Length == props.Length);
|
||||
|
||||
// Override default value
|
||||
for (int i = 0; i < props.Length; i++)
|
||||
{
|
||||
Debug.Assert(props[i].name == defaultProperties[i].name);
|
||||
Debug.Assert(!propDynamicDatas.ContainsKey(props[i].name));
|
||||
|
||||
perShaderData.propStaticDatas[props[i].name].baseDrawers
|
||||
?.ForEach(baseDrawer => baseDrawer.OverrideDefaultValue(shader, props[i], defaultProperties[i], perShaderData));
|
||||
}
|
||||
|
||||
// Init propDynamicDatas
|
||||
for (int i = 0; i < props.Length; i++)
|
||||
{
|
||||
@ -132,7 +127,7 @@ namespace LWGUI
|
||||
}
|
||||
}
|
||||
|
||||
// Store Show Modified Props Only Cache
|
||||
// Store "Show Modified Props Only" Caches
|
||||
{
|
||||
if (perShaderData.displayModeData.showOnlyModifiedGroups || perShaderData.displayModeData.showOnlyModifiedProperties)
|
||||
{
|
||||
|
||||
@ -31,7 +31,7 @@ namespace LWGUI
|
||||
public bool IsDefaultDisplayMode() { return !(showAllAdvancedProperties || showAllHiddenProperties || showOnlyModifiedProperties || showOnlyModifiedGroups); }
|
||||
}
|
||||
|
||||
public class PropertyStaticData
|
||||
public partial class PropertyStaticData
|
||||
{
|
||||
public string name = string.Empty;
|
||||
public string displayName = string.Empty; // Decoded displayName (Helpbox and Tooltip are encoded in displayName)
|
||||
@ -105,6 +105,7 @@ namespace LWGUI
|
||||
propStaticDatas[prop.name] = propStaticData;
|
||||
|
||||
// Get Drawers and Build Drawer StaticMetaData
|
||||
bool hasDecodedStaticMetaData = false;
|
||||
{
|
||||
var drawer = ReflectionHelper.GetPropertyDrawer(shader, prop, out var decoratorDrawers);
|
||||
|
||||
@ -116,6 +117,7 @@ namespace LWGUI
|
||||
{
|
||||
propStaticData.baseDrawers = new List<IBaseDrawer>() { baseDrawer };
|
||||
baseDrawer.BuildStaticMetaData(shader, prop, props, propStaticData);
|
||||
hasDecodedStaticMetaData = true;
|
||||
}
|
||||
|
||||
decoratorDrawers?.ForEach(decoratorDrawer =>
|
||||
@ -133,7 +135,8 @@ namespace LWGUI
|
||||
});
|
||||
}
|
||||
|
||||
DecodeMetaDataFromDisplayName(prop, propStaticData);
|
||||
if (!hasDecodedStaticMetaData)
|
||||
DecodeMetaDataFromDisplayName(prop, propStaticData);
|
||||
}
|
||||
|
||||
// Check Data
|
||||
@ -245,7 +248,7 @@ namespace LWGUI
|
||||
|
||||
private static readonly string _helpboxSplitter = "%";
|
||||
|
||||
public void DecodeMetaDataFromDisplayName(MaterialProperty prop, PropertyStaticData propStaticData)
|
||||
public static void DecodeMetaDataFromDisplayName(MaterialProperty prop, PropertyStaticData propStaticData)
|
||||
{
|
||||
var tooltips = prop.displayName.Split(new String[] { _tooltipSplitter }, StringSplitOptions.None);
|
||||
if (tooltips.Length > 1)
|
||||
|
||||
@ -1,13 +1,14 @@
|
||||
// Copyright (c) Jason Ma
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using UnityEngine;
|
||||
using UnityEditor;
|
||||
using Object = UnityEngine.Object;
|
||||
|
||||
namespace LWGUI
|
||||
{
|
||||
[CreateAssetMenu(fileName = "LWGUI_ShaderPropertyPreset.asset", menuName = "LWGUI/Shader Property Preset")]
|
||||
[CreateAssetMenu(fileName = "LWGUI_ShaderPropertyPreset.asset", menuName = "LWGUI/Shader Property Preset", order = 84)]
|
||||
public class ShaderPropertyPreset : ScriptableObject
|
||||
{
|
||||
public enum PropertyType
|
||||
@ -75,7 +76,7 @@ namespace LWGUI
|
||||
break;
|
||||
}
|
||||
|
||||
MaterialEditor.ApplyMaterialPropertyDrawers(material);
|
||||
UnityEditorExtension.ApplyMaterialPropertyAndDecoratorDrawers(material);
|
||||
}
|
||||
// is Property Primary Material
|
||||
else if (perMaterialData != null)
|
||||
@ -145,6 +146,8 @@ namespace LWGUI
|
||||
public List<PropertyValue> propertyValues = new List<PropertyValue>();
|
||||
public List<string> enabledKeywords = new List<string>();
|
||||
public List<string> disabledKeywords = new List<string>();
|
||||
public List<string> enabledPasses = new List<string>();
|
||||
public List<string> disabledPasses = new List<string>();
|
||||
public int renderQueue = -1;
|
||||
|
||||
|
||||
@ -156,11 +159,15 @@ namespace LWGUI
|
||||
material.EnableKeyword(enabledKeyword);
|
||||
foreach (var disabledKeyword in disabledKeywords)
|
||||
material.DisableKeyword(disabledKeyword);
|
||||
|
||||
Helper.SetShaderPassEnabled(new Object[] { material }, enabledPasses.Select(s => s.ToUpper()).ToArray(), true);
|
||||
Helper.SetShaderPassEnabled(new Object[] { material }, disabledPasses.Select(s => s.ToUpper()).ToArray(), false);
|
||||
|
||||
if (renderQueue >= 0)
|
||||
material.renderQueue = renderQueue;
|
||||
}
|
||||
|
||||
public void ApplyToEditingMaterial(UnityEngine.Object[] materials, PerMaterialData perMaterialData)
|
||||
public void ApplyToEditingMaterial(Object[] materials, PerMaterialData perMaterialData)
|
||||
{
|
||||
for (int i = 0; i < materials.Length; i++)
|
||||
{
|
||||
@ -171,12 +178,16 @@ namespace LWGUI
|
||||
material.EnableKeyword(enabledKeyword);
|
||||
foreach (var disabledKeyword in disabledKeywords)
|
||||
material.DisableKeyword(disabledKeyword);
|
||||
|
||||
if (renderQueue >= 0)
|
||||
material.renderQueue = renderQueue;
|
||||
}
|
||||
|
||||
Helper.SetShaderPassEnabled(materials, enabledPasses.Select(s => s.ToUpper()).ToArray(), true);
|
||||
Helper.SetShaderPassEnabled(materials, disabledPasses.Select(s => s.ToUpper()).ToArray(), false);
|
||||
}
|
||||
|
||||
public void ApplyKeywordsToMaterials(UnityEngine.Object[] materials)
|
||||
public void ApplyKeywordsAndPassesToMaterials(Object[] materials)
|
||||
{
|
||||
for (int i = 0; i < materials.Length; i++)
|
||||
{
|
||||
@ -186,6 +197,9 @@ namespace LWGUI
|
||||
foreach (var disabledKeyword in disabledKeywords)
|
||||
material.DisableKeyword(disabledKeyword);
|
||||
}
|
||||
|
||||
Helper.SetShaderPassEnabled(materials, enabledPasses.Select(s => s.ToUpper()).ToArray(), true);
|
||||
Helper.SetShaderPassEnabled(materials, disabledPasses.Select(s => s.ToUpper()).ToArray(), false);
|
||||
}
|
||||
|
||||
public PropertyValue GetPropertyValue(string propName)
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
BIN
Assets/External/NiloToonURP/Editor/ShaderGUI/LWGUI-main/README.md
(Stored with Git LFS)
vendored
BIN
Assets/External/NiloToonURP/Editor/ShaderGUI/LWGUI-main/README.md
(Stored with Git LFS)
vendored
Binary file not shown.
@ -1,9 +1,9 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b3a047b5aeeebeb409a7ed0856959109
|
||||
guid: 5876caab7dc67af4d8e92317782da76f
|
||||
TextureImporter:
|
||||
internalIDToNameTable: []
|
||||
externalObjects: {}
|
||||
serializedVersion: 11
|
||||
serializedVersion: 12
|
||||
mipmaps:
|
||||
mipMapMode: 0
|
||||
enableMipMap: 1
|
||||
@ -20,11 +20,12 @@ TextureImporter:
|
||||
externalNormalMap: 0
|
||||
heightScale: 0.25
|
||||
normalMapFilter: 0
|
||||
flipGreenChannel: 0
|
||||
isReadable: 0
|
||||
streamingMipmaps: 0
|
||||
streamingMipmapsPriority: 0
|
||||
vTOnly: 0
|
||||
ignoreMasterTextureLimit: 0
|
||||
ignoreMipmapLimit: 0
|
||||
grayScaleToAlpha: 0
|
||||
generateCubemap: 6
|
||||
cubemapConvolution: 0
|
||||
@ -34,7 +35,7 @@ TextureImporter:
|
||||
textureSettings:
|
||||
serializedVersion: 2
|
||||
filterMode: 1
|
||||
aniso: 2
|
||||
aniso: 1
|
||||
mipBias: 0
|
||||
wrapU: 0
|
||||
wrapV: 0
|
||||
@ -63,10 +64,12 @@ TextureImporter:
|
||||
textureFormatSet: 0
|
||||
ignorePngGamma: 0
|
||||
applyGammaDecoding: 0
|
||||
swizzle: 50462976
|
||||
cookieLightType: 0
|
||||
platformSettings:
|
||||
- serializedVersion: 3
|
||||
buildTarget: DefaultTexturePlatform
|
||||
maxTextureSize: 8192
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
@ -74,11 +77,12 @@ TextureImporter:
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
ignorePlatformSupport: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
- serializedVersion: 3
|
||||
buildTarget: Standalone
|
||||
maxTextureSize: 8192
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
@ -86,35 +90,12 @@ TextureImporter:
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
ignorePlatformSupport: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
- serializedVersion: 3
|
||||
buildTarget: iPhone
|
||||
maxTextureSize: 8192
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
- serializedVersion: 3
|
||||
buildTarget: Android
|
||||
maxTextureSize: 8192
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
- serializedVersion: 3
|
||||
buildTarget: Windows Store Apps
|
||||
maxTextureSize: 8192
|
||||
buildTarget: Server
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
@ -122,6 +103,7 @@ TextureImporter:
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
ignorePlatformSupport: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
spriteSheet:
|
||||
@ -138,9 +120,8 @@ TextureImporter:
|
||||
weights: []
|
||||
secondaryTextures: []
|
||||
nameFileIdTable: {}
|
||||
spritePackingTag:
|
||||
mipmapLimitGroupName:
|
||||
pSDRemoveMatte: 0
|
||||
pSDShowRemoveMatteOption: 0
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
||||
BIN
Assets/External/NiloToonURP/Editor/ShaderGUI/LWGUI-main/README_CN.assets/image-20240416142736663.png
(Stored with Git LFS)
vendored
BIN
Assets/External/NiloToonURP/Editor/ShaderGUI/LWGUI-main/README_CN.assets/image-20240416142736663.png
(Stored with Git LFS)
vendored
Binary file not shown.
BIN
Assets/External/NiloToonURP/Editor/ShaderGUI/LWGUI-main/README_CN.assets/image-20240716183800118.png
(Stored with Git LFS)
vendored
Normal file
BIN
Assets/External/NiloToonURP/Editor/ShaderGUI/LWGUI-main/README_CN.assets/image-20240716183800118.png
(Stored with Git LFS)
vendored
Normal file
Binary file not shown.
@ -0,0 +1,127 @@
|
||||
fileFormatVersion: 2
|
||||
guid: d728a6f19010f8747b8ac956860a5089
|
||||
TextureImporter:
|
||||
internalIDToNameTable: []
|
||||
externalObjects: {}
|
||||
serializedVersion: 12
|
||||
mipmaps:
|
||||
mipMapMode: 0
|
||||
enableMipMap: 1
|
||||
sRGBTexture: 1
|
||||
linearTexture: 0
|
||||
fadeOut: 0
|
||||
borderMipMap: 0
|
||||
mipMapsPreserveCoverage: 0
|
||||
alphaTestReferenceValue: 0.5
|
||||
mipMapFadeDistanceStart: 1
|
||||
mipMapFadeDistanceEnd: 3
|
||||
bumpmap:
|
||||
convertToNormalMap: 0
|
||||
externalNormalMap: 0
|
||||
heightScale: 0.25
|
||||
normalMapFilter: 0
|
||||
flipGreenChannel: 0
|
||||
isReadable: 0
|
||||
streamingMipmaps: 0
|
||||
streamingMipmapsPriority: 0
|
||||
vTOnly: 0
|
||||
ignoreMipmapLimit: 0
|
||||
grayScaleToAlpha: 0
|
||||
generateCubemap: 6
|
||||
cubemapConvolution: 0
|
||||
seamlessCubemap: 0
|
||||
textureFormat: 1
|
||||
maxTextureSize: 2048
|
||||
textureSettings:
|
||||
serializedVersion: 2
|
||||
filterMode: 1
|
||||
aniso: 1
|
||||
mipBias: 0
|
||||
wrapU: 0
|
||||
wrapV: 0
|
||||
wrapW: 0
|
||||
nPOTScale: 1
|
||||
lightmap: 0
|
||||
compressionQuality: 50
|
||||
spriteMode: 0
|
||||
spriteExtrude: 1
|
||||
spriteMeshType: 1
|
||||
alignment: 0
|
||||
spritePivot: {x: 0.5, y: 0.5}
|
||||
spritePixelsToUnits: 100
|
||||
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
|
||||
spriteGenerateFallbackPhysicsShape: 1
|
||||
alphaUsage: 1
|
||||
alphaIsTransparency: 0
|
||||
spriteTessellationDetail: -1
|
||||
textureType: 0
|
||||
textureShape: 1
|
||||
singleChannelComponent: 0
|
||||
flipbookRows: 1
|
||||
flipbookColumns: 1
|
||||
maxTextureSizeSet: 0
|
||||
compressionQualitySet: 0
|
||||
textureFormatSet: 0
|
||||
ignorePngGamma: 0
|
||||
applyGammaDecoding: 0
|
||||
swizzle: 50462976
|
||||
cookieLightType: 0
|
||||
platformSettings:
|
||||
- serializedVersion: 3
|
||||
buildTarget: DefaultTexturePlatform
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
ignorePlatformSupport: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
- serializedVersion: 3
|
||||
buildTarget: Standalone
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
ignorePlatformSupport: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
- serializedVersion: 3
|
||||
buildTarget: Server
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
ignorePlatformSupport: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
spriteSheet:
|
||||
serializedVersion: 2
|
||||
sprites: []
|
||||
outline: []
|
||||
physicsShape: []
|
||||
bones: []
|
||||
spriteID:
|
||||
internalID: 0
|
||||
vertices: []
|
||||
indices:
|
||||
edges: []
|
||||
weights: []
|
||||
secondaryTextures: []
|
||||
nameFileIdTable: {}
|
||||
mipmapLimitGroupName:
|
||||
pSDRemoveMatte: 0
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
BIN
Assets/External/NiloToonURP/Editor/ShaderGUI/LWGUI-main/README_CN.assets/image-20240716184045776.png
(Stored with Git LFS)
vendored
Normal file
BIN
Assets/External/NiloToonURP/Editor/ShaderGUI/LWGUI-main/README_CN.assets/image-20240716184045776.png
(Stored with Git LFS)
vendored
Normal file
Binary file not shown.
@ -0,0 +1,127 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 56332e65f9dc7b44f83296f4b88f0f23
|
||||
TextureImporter:
|
||||
internalIDToNameTable: []
|
||||
externalObjects: {}
|
||||
serializedVersion: 12
|
||||
mipmaps:
|
||||
mipMapMode: 0
|
||||
enableMipMap: 1
|
||||
sRGBTexture: 1
|
||||
linearTexture: 0
|
||||
fadeOut: 0
|
||||
borderMipMap: 0
|
||||
mipMapsPreserveCoverage: 0
|
||||
alphaTestReferenceValue: 0.5
|
||||
mipMapFadeDistanceStart: 1
|
||||
mipMapFadeDistanceEnd: 3
|
||||
bumpmap:
|
||||
convertToNormalMap: 0
|
||||
externalNormalMap: 0
|
||||
heightScale: 0.25
|
||||
normalMapFilter: 0
|
||||
flipGreenChannel: 0
|
||||
isReadable: 0
|
||||
streamingMipmaps: 0
|
||||
streamingMipmapsPriority: 0
|
||||
vTOnly: 0
|
||||
ignoreMipmapLimit: 0
|
||||
grayScaleToAlpha: 0
|
||||
generateCubemap: 6
|
||||
cubemapConvolution: 0
|
||||
seamlessCubemap: 0
|
||||
textureFormat: 1
|
||||
maxTextureSize: 2048
|
||||
textureSettings:
|
||||
serializedVersion: 2
|
||||
filterMode: 1
|
||||
aniso: 1
|
||||
mipBias: 0
|
||||
wrapU: 0
|
||||
wrapV: 0
|
||||
wrapW: 0
|
||||
nPOTScale: 1
|
||||
lightmap: 0
|
||||
compressionQuality: 50
|
||||
spriteMode: 0
|
||||
spriteExtrude: 1
|
||||
spriteMeshType: 1
|
||||
alignment: 0
|
||||
spritePivot: {x: 0.5, y: 0.5}
|
||||
spritePixelsToUnits: 100
|
||||
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
|
||||
spriteGenerateFallbackPhysicsShape: 1
|
||||
alphaUsage: 1
|
||||
alphaIsTransparency: 0
|
||||
spriteTessellationDetail: -1
|
||||
textureType: 0
|
||||
textureShape: 1
|
||||
singleChannelComponent: 0
|
||||
flipbookRows: 1
|
||||
flipbookColumns: 1
|
||||
maxTextureSizeSet: 0
|
||||
compressionQualitySet: 0
|
||||
textureFormatSet: 0
|
||||
ignorePngGamma: 0
|
||||
applyGammaDecoding: 0
|
||||
swizzle: 50462976
|
||||
cookieLightType: 0
|
||||
platformSettings:
|
||||
- serializedVersion: 3
|
||||
buildTarget: DefaultTexturePlatform
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
ignorePlatformSupport: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
- serializedVersion: 3
|
||||
buildTarget: Standalone
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
ignorePlatformSupport: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
- serializedVersion: 3
|
||||
buildTarget: Server
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
ignorePlatformSupport: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
spriteSheet:
|
||||
serializedVersion: 2
|
||||
sprites: []
|
||||
outline: []
|
||||
physicsShape: []
|
||||
bones: []
|
||||
spriteID:
|
||||
internalID: 0
|
||||
vertices: []
|
||||
indices:
|
||||
edges: []
|
||||
weights: []
|
||||
secondaryTextures: []
|
||||
nameFileIdTable: {}
|
||||
mipmapLimitGroupName:
|
||||
pSDRemoveMatte: 0
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
BIN
Assets/External/NiloToonURP/Editor/ShaderGUI/LWGUI-main/README_CN.assets/image-20240717104144821.png
(Stored with Git LFS)
vendored
Normal file
BIN
Assets/External/NiloToonURP/Editor/ShaderGUI/LWGUI-main/README_CN.assets/image-20240717104144821.png
(Stored with Git LFS)
vendored
Normal file
Binary file not shown.
@ -0,0 +1,123 @@
|
||||
fileFormatVersion: 2
|
||||
guid: d09eaf1bb9d214040a6cb0d350439f7f
|
||||
TextureImporter:
|
||||
internalIDToNameTable: []
|
||||
externalObjects: {}
|
||||
serializedVersion: 12
|
||||
mipmaps:
|
||||
mipMapMode: 0
|
||||
enableMipMap: 1
|
||||
sRGBTexture: 1
|
||||
linearTexture: 0
|
||||
fadeOut: 0
|
||||
borderMipMap: 0
|
||||
mipMapsPreserveCoverage: 0
|
||||
alphaTestReferenceValue: 0.5
|
||||
mipMapFadeDistanceStart: 1
|
||||
mipMapFadeDistanceEnd: 3
|
||||
bumpmap:
|
||||
convertToNormalMap: 0
|
||||
externalNormalMap: 0
|
||||
heightScale: 0.25
|
||||
normalMapFilter: 0
|
||||
isReadable: 0
|
||||
streamingMipmaps: 0
|
||||
streamingMipmapsPriority: 0
|
||||
vTOnly: 0
|
||||
ignoreMasterTextureLimit: 0
|
||||
grayScaleToAlpha: 0
|
||||
generateCubemap: 6
|
||||
cubemapConvolution: 0
|
||||
seamlessCubemap: 0
|
||||
textureFormat: 1
|
||||
maxTextureSize: 2048
|
||||
textureSettings:
|
||||
serializedVersion: 2
|
||||
filterMode: 1
|
||||
aniso: 1
|
||||
mipBias: 0
|
||||
wrapU: 0
|
||||
wrapV: 0
|
||||
wrapW: 0
|
||||
nPOTScale: 1
|
||||
lightmap: 0
|
||||
compressionQuality: 50
|
||||
spriteMode: 0
|
||||
spriteExtrude: 1
|
||||
spriteMeshType: 1
|
||||
alignment: 0
|
||||
spritePivot: {x: 0.5, y: 0.5}
|
||||
spritePixelsToUnits: 100
|
||||
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
|
||||
spriteGenerateFallbackPhysicsShape: 1
|
||||
alphaUsage: 1
|
||||
alphaIsTransparency: 0
|
||||
spriteTessellationDetail: -1
|
||||
textureType: 0
|
||||
textureShape: 1
|
||||
singleChannelComponent: 0
|
||||
flipbookRows: 1
|
||||
flipbookColumns: 1
|
||||
maxTextureSizeSet: 0
|
||||
compressionQualitySet: 0
|
||||
textureFormatSet: 0
|
||||
ignorePngGamma: 0
|
||||
applyGammaDecoding: 0
|
||||
cookieLightType: 0
|
||||
platformSettings:
|
||||
- serializedVersion: 3
|
||||
buildTarget: DefaultTexturePlatform
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
- serializedVersion: 3
|
||||
buildTarget: Standalone
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
- serializedVersion: 3
|
||||
buildTarget: Server
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
spriteSheet:
|
||||
serializedVersion: 2
|
||||
sprites: []
|
||||
outline: []
|
||||
physicsShape: []
|
||||
bones: []
|
||||
spriteID:
|
||||
internalID: 0
|
||||
vertices: []
|
||||
indices:
|
||||
edges: []
|
||||
weights: []
|
||||
secondaryTextures: []
|
||||
nameFileIdTable: {}
|
||||
spritePackingTag:
|
||||
pSDRemoveMatte: 0
|
||||
pSDShowRemoveMatteOption: 0
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
BIN
Assets/External/NiloToonURP/Editor/ShaderGUI/LWGUI-main/README_CN.assets/image-20240717104206365.png
(Stored with Git LFS)
vendored
Normal file
BIN
Assets/External/NiloToonURP/Editor/ShaderGUI/LWGUI-main/README_CN.assets/image-20240717104206365.png
(Stored with Git LFS)
vendored
Normal file
Binary file not shown.
@ -0,0 +1,123 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 43264f7caf023f740b5cc4dd66fa768b
|
||||
TextureImporter:
|
||||
internalIDToNameTable: []
|
||||
externalObjects: {}
|
||||
serializedVersion: 12
|
||||
mipmaps:
|
||||
mipMapMode: 0
|
||||
enableMipMap: 1
|
||||
sRGBTexture: 1
|
||||
linearTexture: 0
|
||||
fadeOut: 0
|
||||
borderMipMap: 0
|
||||
mipMapsPreserveCoverage: 0
|
||||
alphaTestReferenceValue: 0.5
|
||||
mipMapFadeDistanceStart: 1
|
||||
mipMapFadeDistanceEnd: 3
|
||||
bumpmap:
|
||||
convertToNormalMap: 0
|
||||
externalNormalMap: 0
|
||||
heightScale: 0.25
|
||||
normalMapFilter: 0
|
||||
isReadable: 0
|
||||
streamingMipmaps: 0
|
||||
streamingMipmapsPriority: 0
|
||||
vTOnly: 0
|
||||
ignoreMasterTextureLimit: 0
|
||||
grayScaleToAlpha: 0
|
||||
generateCubemap: 6
|
||||
cubemapConvolution: 0
|
||||
seamlessCubemap: 0
|
||||
textureFormat: 1
|
||||
maxTextureSize: 2048
|
||||
textureSettings:
|
||||
serializedVersion: 2
|
||||
filterMode: 1
|
||||
aniso: 1
|
||||
mipBias: 0
|
||||
wrapU: 0
|
||||
wrapV: 0
|
||||
wrapW: 0
|
||||
nPOTScale: 1
|
||||
lightmap: 0
|
||||
compressionQuality: 50
|
||||
spriteMode: 0
|
||||
spriteExtrude: 1
|
||||
spriteMeshType: 1
|
||||
alignment: 0
|
||||
spritePivot: {x: 0.5, y: 0.5}
|
||||
spritePixelsToUnits: 100
|
||||
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
|
||||
spriteGenerateFallbackPhysicsShape: 1
|
||||
alphaUsage: 1
|
||||
alphaIsTransparency: 0
|
||||
spriteTessellationDetail: -1
|
||||
textureType: 0
|
||||
textureShape: 1
|
||||
singleChannelComponent: 0
|
||||
flipbookRows: 1
|
||||
flipbookColumns: 1
|
||||
maxTextureSizeSet: 0
|
||||
compressionQualitySet: 0
|
||||
textureFormatSet: 0
|
||||
ignorePngGamma: 0
|
||||
applyGammaDecoding: 0
|
||||
cookieLightType: 0
|
||||
platformSettings:
|
||||
- serializedVersion: 3
|
||||
buildTarget: DefaultTexturePlatform
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
- serializedVersion: 3
|
||||
buildTarget: Standalone
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
- serializedVersion: 3
|
||||
buildTarget: Server
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
spriteSheet:
|
||||
serializedVersion: 2
|
||||
sprites: []
|
||||
outline: []
|
||||
physicsShape: []
|
||||
bones: []
|
||||
spriteID:
|
||||
internalID: 0
|
||||
vertices: []
|
||||
indices:
|
||||
edges: []
|
||||
weights: []
|
||||
secondaryTextures: []
|
||||
nameFileIdTable: {}
|
||||
spritePackingTag:
|
||||
pSDRemoveMatte: 0
|
||||
pSDShowRemoveMatteOption: 0
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
BIN
Assets/External/NiloToonURP/Editor/ShaderGUI/LWGUI-main/README_CN.assets/image-20241126105823397.png
(Stored with Git LFS)
vendored
Normal file
BIN
Assets/External/NiloToonURP/Editor/ShaderGUI/LWGUI-main/README_CN.assets/image-20241126105823397.png
(Stored with Git LFS)
vendored
Normal file
Binary file not shown.
@ -0,0 +1,153 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 0b6df23f9d012a74abed6b4f422d9442
|
||||
TextureImporter:
|
||||
internalIDToNameTable: []
|
||||
externalObjects: {}
|
||||
serializedVersion: 13
|
||||
mipmaps:
|
||||
mipMapMode: 0
|
||||
enableMipMap: 1
|
||||
sRGBTexture: 1
|
||||
linearTexture: 0
|
||||
fadeOut: 0
|
||||
borderMipMap: 0
|
||||
mipMapsPreserveCoverage: 0
|
||||
alphaTestReferenceValue: 0.5
|
||||
mipMapFadeDistanceStart: 1
|
||||
mipMapFadeDistanceEnd: 3
|
||||
bumpmap:
|
||||
convertToNormalMap: 0
|
||||
externalNormalMap: 0
|
||||
heightScale: 0.25
|
||||
normalMapFilter: 0
|
||||
flipGreenChannel: 0
|
||||
isReadable: 0
|
||||
streamingMipmaps: 0
|
||||
streamingMipmapsPriority: 0
|
||||
vTOnly: 0
|
||||
ignoreMipmapLimit: 0
|
||||
grayScaleToAlpha: 0
|
||||
generateCubemap: 6
|
||||
cubemapConvolution: 0
|
||||
seamlessCubemap: 0
|
||||
textureFormat: 1
|
||||
maxTextureSize: 2048
|
||||
textureSettings:
|
||||
serializedVersion: 2
|
||||
filterMode: 1
|
||||
aniso: 1
|
||||
mipBias: 0
|
||||
wrapU: 0
|
||||
wrapV: 0
|
||||
wrapW: 0
|
||||
nPOTScale: 1
|
||||
lightmap: 0
|
||||
compressionQuality: 50
|
||||
spriteMode: 0
|
||||
spriteExtrude: 1
|
||||
spriteMeshType: 1
|
||||
alignment: 0
|
||||
spritePivot: {x: 0.5, y: 0.5}
|
||||
spritePixelsToUnits: 100
|
||||
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
|
||||
spriteGenerateFallbackPhysicsShape: 1
|
||||
alphaUsage: 1
|
||||
alphaIsTransparency: 0
|
||||
spriteTessellationDetail: -1
|
||||
textureType: 0
|
||||
textureShape: 1
|
||||
singleChannelComponent: 0
|
||||
flipbookRows: 1
|
||||
flipbookColumns: 1
|
||||
maxTextureSizeSet: 0
|
||||
compressionQualitySet: 0
|
||||
textureFormatSet: 0
|
||||
ignorePngGamma: 0
|
||||
applyGammaDecoding: 0
|
||||
swizzle: 50462976
|
||||
cookieLightType: 0
|
||||
platformSettings:
|
||||
- serializedVersion: 3
|
||||
buildTarget: DefaultTexturePlatform
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
ignorePlatformSupport: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
- serializedVersion: 3
|
||||
buildTarget: Standalone
|
||||
maxTextureSize: 1024
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: 25
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 1
|
||||
ignorePlatformSupport: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
- serializedVersion: 3
|
||||
buildTarget: iPhone
|
||||
maxTextureSize: 1024
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: 50
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 1
|
||||
ignorePlatformSupport: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
- serializedVersion: 3
|
||||
buildTarget: Android
|
||||
maxTextureSize: 1024
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: 50
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 1
|
||||
ignorePlatformSupport: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
- serializedVersion: 3
|
||||
buildTarget: VisionOS
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
ignorePlatformSupport: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
spriteSheet:
|
||||
serializedVersion: 2
|
||||
sprites: []
|
||||
outline: []
|
||||
physicsShape: []
|
||||
bones: []
|
||||
spriteID:
|
||||
internalID: 0
|
||||
vertices: []
|
||||
indices:
|
||||
edges: []
|
||||
weights: []
|
||||
secondaryTextures: []
|
||||
nameFileIdTable: {}
|
||||
mipmapLimitGroupName:
|
||||
pSDRemoveMatte: 0
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
BIN
Assets/External/NiloToonURP/Editor/ShaderGUI/LWGUI-main/README_CN.assets/image-20241126110012922.png
(Stored with Git LFS)
vendored
Normal file
BIN
Assets/External/NiloToonURP/Editor/ShaderGUI/LWGUI-main/README_CN.assets/image-20241126110012922.png
(Stored with Git LFS)
vendored
Normal file
Binary file not shown.
@ -0,0 +1,153 @@
|
||||
fileFormatVersion: 2
|
||||
guid: cc772ea50f72a6e44b0f6190010a6424
|
||||
TextureImporter:
|
||||
internalIDToNameTable: []
|
||||
externalObjects: {}
|
||||
serializedVersion: 13
|
||||
mipmaps:
|
||||
mipMapMode: 0
|
||||
enableMipMap: 1
|
||||
sRGBTexture: 1
|
||||
linearTexture: 0
|
||||
fadeOut: 0
|
||||
borderMipMap: 0
|
||||
mipMapsPreserveCoverage: 0
|
||||
alphaTestReferenceValue: 0.5
|
||||
mipMapFadeDistanceStart: 1
|
||||
mipMapFadeDistanceEnd: 3
|
||||
bumpmap:
|
||||
convertToNormalMap: 0
|
||||
externalNormalMap: 0
|
||||
heightScale: 0.25
|
||||
normalMapFilter: 0
|
||||
flipGreenChannel: 0
|
||||
isReadable: 0
|
||||
streamingMipmaps: 0
|
||||
streamingMipmapsPriority: 0
|
||||
vTOnly: 0
|
||||
ignoreMipmapLimit: 0
|
||||
grayScaleToAlpha: 0
|
||||
generateCubemap: 6
|
||||
cubemapConvolution: 0
|
||||
seamlessCubemap: 0
|
||||
textureFormat: 1
|
||||
maxTextureSize: 2048
|
||||
textureSettings:
|
||||
serializedVersion: 2
|
||||
filterMode: 1
|
||||
aniso: 1
|
||||
mipBias: 0
|
||||
wrapU: 0
|
||||
wrapV: 0
|
||||
wrapW: 0
|
||||
nPOTScale: 1
|
||||
lightmap: 0
|
||||
compressionQuality: 50
|
||||
spriteMode: 0
|
||||
spriteExtrude: 1
|
||||
spriteMeshType: 1
|
||||
alignment: 0
|
||||
spritePivot: {x: 0.5, y: 0.5}
|
||||
spritePixelsToUnits: 100
|
||||
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
|
||||
spriteGenerateFallbackPhysicsShape: 1
|
||||
alphaUsage: 1
|
||||
alphaIsTransparency: 0
|
||||
spriteTessellationDetail: -1
|
||||
textureType: 0
|
||||
textureShape: 1
|
||||
singleChannelComponent: 0
|
||||
flipbookRows: 1
|
||||
flipbookColumns: 1
|
||||
maxTextureSizeSet: 0
|
||||
compressionQualitySet: 0
|
||||
textureFormatSet: 0
|
||||
ignorePngGamma: 0
|
||||
applyGammaDecoding: 0
|
||||
swizzle: 50462976
|
||||
cookieLightType: 0
|
||||
platformSettings:
|
||||
- serializedVersion: 3
|
||||
buildTarget: DefaultTexturePlatform
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
ignorePlatformSupport: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
- serializedVersion: 3
|
||||
buildTarget: Standalone
|
||||
maxTextureSize: 1024
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: 25
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 1
|
||||
ignorePlatformSupport: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
- serializedVersion: 3
|
||||
buildTarget: iPhone
|
||||
maxTextureSize: 1024
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: 50
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 1
|
||||
ignorePlatformSupport: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
- serializedVersion: 3
|
||||
buildTarget: Android
|
||||
maxTextureSize: 1024
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: 50
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 1
|
||||
ignorePlatformSupport: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
- serializedVersion: 3
|
||||
buildTarget: VisionOS
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
ignorePlatformSupport: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
spriteSheet:
|
||||
serializedVersion: 2
|
||||
sprites: []
|
||||
outline: []
|
||||
physicsShape: []
|
||||
bones: []
|
||||
spriteID:
|
||||
internalID: 0
|
||||
vertices: []
|
||||
indices:
|
||||
edges: []
|
||||
weights: []
|
||||
secondaryTextures: []
|
||||
nameFileIdTable: {}
|
||||
mipmapLimitGroupName:
|
||||
pSDRemoveMatte: 0
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
BIN
Assets/External/NiloToonURP/Editor/ShaderGUI/LWGUI-main/README_CN.assets/image-20241126112320151.png
(Stored with Git LFS)
vendored
Normal file
BIN
Assets/External/NiloToonURP/Editor/ShaderGUI/LWGUI-main/README_CN.assets/image-20241126112320151.png
(Stored with Git LFS)
vendored
Normal file
Binary file not shown.
@ -0,0 +1,153 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c387c6327985b4f419caee4e22ffbb9b
|
||||
TextureImporter:
|
||||
internalIDToNameTable: []
|
||||
externalObjects: {}
|
||||
serializedVersion: 13
|
||||
mipmaps:
|
||||
mipMapMode: 0
|
||||
enableMipMap: 1
|
||||
sRGBTexture: 1
|
||||
linearTexture: 0
|
||||
fadeOut: 0
|
||||
borderMipMap: 0
|
||||
mipMapsPreserveCoverage: 0
|
||||
alphaTestReferenceValue: 0.5
|
||||
mipMapFadeDistanceStart: 1
|
||||
mipMapFadeDistanceEnd: 3
|
||||
bumpmap:
|
||||
convertToNormalMap: 0
|
||||
externalNormalMap: 0
|
||||
heightScale: 0.25
|
||||
normalMapFilter: 0
|
||||
flipGreenChannel: 0
|
||||
isReadable: 0
|
||||
streamingMipmaps: 0
|
||||
streamingMipmapsPriority: 0
|
||||
vTOnly: 0
|
||||
ignoreMipmapLimit: 0
|
||||
grayScaleToAlpha: 0
|
||||
generateCubemap: 6
|
||||
cubemapConvolution: 0
|
||||
seamlessCubemap: 0
|
||||
textureFormat: 1
|
||||
maxTextureSize: 2048
|
||||
textureSettings:
|
||||
serializedVersion: 2
|
||||
filterMode: 1
|
||||
aniso: 1
|
||||
mipBias: 0
|
||||
wrapU: 0
|
||||
wrapV: 0
|
||||
wrapW: 0
|
||||
nPOTScale: 1
|
||||
lightmap: 0
|
||||
compressionQuality: 50
|
||||
spriteMode: 0
|
||||
spriteExtrude: 1
|
||||
spriteMeshType: 1
|
||||
alignment: 0
|
||||
spritePivot: {x: 0.5, y: 0.5}
|
||||
spritePixelsToUnits: 100
|
||||
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
|
||||
spriteGenerateFallbackPhysicsShape: 1
|
||||
alphaUsage: 1
|
||||
alphaIsTransparency: 0
|
||||
spriteTessellationDetail: -1
|
||||
textureType: 0
|
||||
textureShape: 1
|
||||
singleChannelComponent: 0
|
||||
flipbookRows: 1
|
||||
flipbookColumns: 1
|
||||
maxTextureSizeSet: 0
|
||||
compressionQualitySet: 0
|
||||
textureFormatSet: 0
|
||||
ignorePngGamma: 0
|
||||
applyGammaDecoding: 0
|
||||
swizzle: 50462976
|
||||
cookieLightType: 0
|
||||
platformSettings:
|
||||
- serializedVersion: 3
|
||||
buildTarget: DefaultTexturePlatform
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
ignorePlatformSupport: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
- serializedVersion: 3
|
||||
buildTarget: Standalone
|
||||
maxTextureSize: 1024
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: 25
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 1
|
||||
ignorePlatformSupport: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
- serializedVersion: 3
|
||||
buildTarget: iPhone
|
||||
maxTextureSize: 1024
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: 50
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 1
|
||||
ignorePlatformSupport: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
- serializedVersion: 3
|
||||
buildTarget: Android
|
||||
maxTextureSize: 1024
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: 50
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 1
|
||||
ignorePlatformSupport: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
- serializedVersion: 3
|
||||
buildTarget: VisionOS
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
ignorePlatformSupport: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
spriteSheet:
|
||||
serializedVersion: 2
|
||||
sprites: []
|
||||
outline: []
|
||||
physicsShape: []
|
||||
bones: []
|
||||
spriteID:
|
||||
internalID: 0
|
||||
vertices: []
|
||||
indices:
|
||||
edges: []
|
||||
weights: []
|
||||
secondaryTextures: []
|
||||
nameFileIdTable: {}
|
||||
mipmapLimitGroupName:
|
||||
pSDRemoveMatte: 0
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
BIN
Assets/External/NiloToonURP/Editor/ShaderGUI/LWGUI-main/README_CN.assets/image-20241127180711449.png
(Stored with Git LFS)
vendored
Normal file
BIN
Assets/External/NiloToonURP/Editor/ShaderGUI/LWGUI-main/README_CN.assets/image-20241127180711449.png
(Stored with Git LFS)
vendored
Normal file
Binary file not shown.
@ -0,0 +1,127 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b307e0433bc4e724180c49d205d9060e
|
||||
TextureImporter:
|
||||
internalIDToNameTable: []
|
||||
externalObjects: {}
|
||||
serializedVersion: 12
|
||||
mipmaps:
|
||||
mipMapMode: 0
|
||||
enableMipMap: 1
|
||||
sRGBTexture: 1
|
||||
linearTexture: 0
|
||||
fadeOut: 0
|
||||
borderMipMap: 0
|
||||
mipMapsPreserveCoverage: 0
|
||||
alphaTestReferenceValue: 0.5
|
||||
mipMapFadeDistanceStart: 1
|
||||
mipMapFadeDistanceEnd: 3
|
||||
bumpmap:
|
||||
convertToNormalMap: 0
|
||||
externalNormalMap: 0
|
||||
heightScale: 0.25
|
||||
normalMapFilter: 0
|
||||
flipGreenChannel: 0
|
||||
isReadable: 0
|
||||
streamingMipmaps: 0
|
||||
streamingMipmapsPriority: 0
|
||||
vTOnly: 0
|
||||
ignoreMipmapLimit: 0
|
||||
grayScaleToAlpha: 0
|
||||
generateCubemap: 6
|
||||
cubemapConvolution: 0
|
||||
seamlessCubemap: 0
|
||||
textureFormat: 1
|
||||
maxTextureSize: 2048
|
||||
textureSettings:
|
||||
serializedVersion: 2
|
||||
filterMode: 1
|
||||
aniso: 1
|
||||
mipBias: 0
|
||||
wrapU: 0
|
||||
wrapV: 0
|
||||
wrapW: 0
|
||||
nPOTScale: 1
|
||||
lightmap: 0
|
||||
compressionQuality: 50
|
||||
spriteMode: 0
|
||||
spriteExtrude: 1
|
||||
spriteMeshType: 1
|
||||
alignment: 0
|
||||
spritePivot: {x: 0.5, y: 0.5}
|
||||
spritePixelsToUnits: 100
|
||||
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
|
||||
spriteGenerateFallbackPhysicsShape: 1
|
||||
alphaUsage: 1
|
||||
alphaIsTransparency: 0
|
||||
spriteTessellationDetail: -1
|
||||
textureType: 0
|
||||
textureShape: 1
|
||||
singleChannelComponent: 0
|
||||
flipbookRows: 1
|
||||
flipbookColumns: 1
|
||||
maxTextureSizeSet: 0
|
||||
compressionQualitySet: 0
|
||||
textureFormatSet: 0
|
||||
ignorePngGamma: 0
|
||||
applyGammaDecoding: 0
|
||||
swizzle: 50462976
|
||||
cookieLightType: 0
|
||||
platformSettings:
|
||||
- serializedVersion: 3
|
||||
buildTarget: DefaultTexturePlatform
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
ignorePlatformSupport: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
- serializedVersion: 3
|
||||
buildTarget: Standalone
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
ignorePlatformSupport: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
- serializedVersion: 3
|
||||
buildTarget: Server
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
ignorePlatformSupport: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
spriteSheet:
|
||||
serializedVersion: 2
|
||||
sprites: []
|
||||
outline: []
|
||||
physicsShape: []
|
||||
bones: []
|
||||
spriteID:
|
||||
internalID: 0
|
||||
vertices: []
|
||||
indices:
|
||||
edges: []
|
||||
weights: []
|
||||
secondaryTextures: []
|
||||
nameFileIdTable: {}
|
||||
mipmapLimitGroupName:
|
||||
pSDRemoveMatte: 0
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
BIN
Assets/External/NiloToonURP/Editor/ShaderGUI/LWGUI-main/README_CN.md
(Stored with Git LFS)
vendored
BIN
Assets/External/NiloToonURP/Editor/ShaderGUI/LWGUI-main/README_CN.md
(Stored with Git LFS)
vendored
Binary file not shown.
@ -1,5 +1,6 @@
|
||||
fileFormatVersion: 2
|
||||
guid: d0ddbd505f5f46444b98a9285b7cdb8a
|
||||
guid: 9c80aad1bb2dd5348bc922988445a5fb
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
3
Assets/External/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Runtime/LWGUI.Runtime.asmdef
vendored
Normal file
3
Assets/External/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Runtime/LWGUI.Runtime.asmdef
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
{
|
||||
"name": "LWGUI.Runtime"
|
||||
}
|
||||
7
Assets/External/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Runtime/LWGUI.Runtime.asmdef.meta
vendored
Normal file
7
Assets/External/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Runtime/LWGUI.Runtime.asmdef.meta
vendored
Normal file
@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 959b4969da7632b4e9d4dc209cce9cd6
|
||||
AssemblyDefinitionImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
3
Assets/External/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Runtime/LwguiGradient.meta
vendored
Normal file
3
Assets/External/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Runtime/LwguiGradient.meta
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 756c9f5a40564b56bc263009a656acba
|
||||
timeCreated: 1720764695
|
||||
500
Assets/External/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Runtime/LwguiGradient/LwguiGradient.cs
vendored
Normal file
500
Assets/External/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Runtime/LwguiGradient/LwguiGradient.cs
vendored
Normal file
@ -0,0 +1,500 @@
|
||||
// Copyright (c) Jason Ma
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using UnityEngine;
|
||||
|
||||
namespace LWGUI.Runtime.LwguiGradient
|
||||
{
|
||||
[Serializable]
|
||||
public class LwguiGradient : IDisposable
|
||||
{
|
||||
#region Channel Enum
|
||||
|
||||
public enum Channel
|
||||
{
|
||||
Red = 0,
|
||||
Green = 1,
|
||||
Blue = 2,
|
||||
Alpha = 3,
|
||||
Num = 4
|
||||
}
|
||||
|
||||
[Flags]
|
||||
public enum ChannelMask
|
||||
{
|
||||
None = 0,
|
||||
Red = 1 << 0,
|
||||
Green = 1 << 1,
|
||||
Blue = 1 << 2,
|
||||
Alpha = 1 << 3,
|
||||
RGB = Red | Green | Blue,
|
||||
All = RGB | Alpha
|
||||
}
|
||||
|
||||
public enum GradientTimeRange
|
||||
{
|
||||
One = 1,
|
||||
TwentyFour = 24,
|
||||
TwentyFourHundred = 2400
|
||||
}
|
||||
|
||||
public static bool HasChannelMask(ChannelMask channelMaskA, ChannelMask channelMaskB) => ((uint)channelMaskA & (uint)channelMaskB) > 0;
|
||||
|
||||
public static bool IsChannelIndexInMask(int channelIndex, ChannelMask channelMask) => ((uint)channelMask & (uint)(1 << channelIndex)) > 0;
|
||||
|
||||
public static ChannelMask ChannelIndexToMask(int channelIndex) => (ChannelMask)(1 << channelIndex);
|
||||
|
||||
#endregion
|
||||
|
||||
#region Const
|
||||
|
||||
public static readonly Color[] channelColors = new[] { Color.red, Color.green, Color.blue, Color.white };
|
||||
public static readonly char[] channelNames = new[] { 'r', 'g', 'b', 'a' };
|
||||
|
||||
public static AnimationCurve defaultCurve => new (new Keyframe(0, 1).SetLinearTangentMode(), new Keyframe(1, 1).SetLinearTangentMode());
|
||||
|
||||
#endregion
|
||||
|
||||
#region Data
|
||||
|
||||
// The complete data is stored by RGBA Curves and can be converted into Texture
|
||||
[SerializeField] private List<AnimationCurve> _curves;
|
||||
|
||||
#endregion
|
||||
|
||||
#region Constructor
|
||||
|
||||
public LwguiGradient()
|
||||
{
|
||||
_curves = new List<AnimationCurve>();
|
||||
for (int c = 0; c < (int)Channel.Num; c++)
|
||||
_curves.Add(defaultCurve);
|
||||
}
|
||||
|
||||
public LwguiGradient(LwguiGradient src)
|
||||
{
|
||||
DeepCopyFrom(src);
|
||||
}
|
||||
|
||||
public LwguiGradient(params Keyframe[] keys)
|
||||
{
|
||||
_curves = new List<AnimationCurve>();
|
||||
for (int c = 0; c < (int)Channel.Num; c++)
|
||||
_curves.Add(new AnimationCurve());
|
||||
|
||||
if (keys?.Length > 0)
|
||||
{
|
||||
AddKeys(keys, ChannelMask.All);
|
||||
}
|
||||
}
|
||||
|
||||
public LwguiGradient(Color[] colors, float[] times)
|
||||
{
|
||||
_curves = new List<AnimationCurve>();
|
||||
for (int c = 0; c < (int)Channel.Num; c++)
|
||||
_curves.Add(new AnimationCurve());
|
||||
|
||||
if (colors == null || times == null)
|
||||
return;
|
||||
|
||||
for (int i = 0; i < Mathf.Min(colors.Length, times.Length); i++)
|
||||
{
|
||||
for (int c = 0; c < (int)Channel.Num; c++)
|
||||
{
|
||||
_curves[c].AddKey(new Keyframe(times[i], colors[i][c]).SetLinearTangentMode());
|
||||
}
|
||||
}
|
||||
SetLinearTangentMode();
|
||||
}
|
||||
|
||||
public LwguiGradient(List<AnimationCurve> inRgbaCurves) => SetRgbaCurves(inRgbaCurves);
|
||||
|
||||
public static LwguiGradient white
|
||||
{
|
||||
get => new ();
|
||||
}
|
||||
|
||||
public static LwguiGradient gray
|
||||
{
|
||||
get => new (new []{Color.gray, Color.gray}, new []{0.0f, 1.0f});
|
||||
}
|
||||
|
||||
public static LwguiGradient black
|
||||
{
|
||||
get => new (new []{Color.black, Color.black}, new []{0.0f, 1.0f});
|
||||
}
|
||||
|
||||
public static LwguiGradient red
|
||||
{
|
||||
get => new (new []{Color.red, Color.red}, new []{0.0f, 1.0f});
|
||||
}
|
||||
|
||||
public static LwguiGradient green
|
||||
{
|
||||
get => new (new []{Color.green, Color.green}, new []{0.0f, 1.0f});
|
||||
}
|
||||
|
||||
public static LwguiGradient blue
|
||||
{
|
||||
get => new (new []{Color.blue, Color.blue}, new []{0.0f, 1.0f});
|
||||
}
|
||||
|
||||
public static LwguiGradient cyan
|
||||
{
|
||||
get => new (new []{Color.cyan, Color.cyan}, new []{0.0f, 1.0f});
|
||||
}
|
||||
|
||||
public static LwguiGradient magenta
|
||||
{
|
||||
get => new (new []{Color.magenta, Color.magenta}, new []{0.0f, 1.0f});
|
||||
}
|
||||
|
||||
public static LwguiGradient yellow
|
||||
{
|
||||
get => new (new []{Color.yellow, Color.yellow}, new []{0.0f, 1.0f});
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
public int GetValueBasedHashCode()
|
||||
{
|
||||
var hash = 17;
|
||||
|
||||
if (_curves != null)
|
||||
{
|
||||
foreach (var curve in _curves)
|
||||
{
|
||||
if (curve != null)
|
||||
{
|
||||
hash = hash * 23 + curve.GetHashCode();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return hash;
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
_curves?.Clear();
|
||||
}
|
||||
|
||||
public void Clear(ChannelMask channelMask = ChannelMask.All)
|
||||
{
|
||||
_curves ??= new List<AnimationCurve>();
|
||||
for (int c = 0; c < (int)Channel.Num; c++)
|
||||
{
|
||||
if (!IsChannelIndexInMask(c, channelMask)) continue;
|
||||
|
||||
if (_curves.Count > c) _curves[c].keys = Array.Empty<Keyframe>();
|
||||
else _curves.Add(new AnimationCurve());
|
||||
}
|
||||
}
|
||||
|
||||
public void DeepCopyFrom(LwguiGradient src)
|
||||
{
|
||||
_curves ??= new List<AnimationCurve>();
|
||||
for (int c = 0; c < (int)Channel.Num; c++)
|
||||
{
|
||||
if (_curves.Count == c)
|
||||
_curves.Add(new AnimationCurve());
|
||||
|
||||
_curves[c].keys = Array.Empty<Keyframe>();
|
||||
}
|
||||
|
||||
for (int c = 0; c < src._curves.Count; c++)
|
||||
{
|
||||
foreach (var key in src._curves[c].keys)
|
||||
{
|
||||
_curves[c].AddKey(key);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void SetCurve(AnimationCurve curve, ChannelMask channelMask)
|
||||
{
|
||||
curve ??= defaultCurve;
|
||||
for (int c = 0; c < (int)Channel.Num; c++)
|
||||
{
|
||||
if (!IsChannelIndexInMask(c, channelMask)) continue;
|
||||
|
||||
_curves[c] = curve;
|
||||
}
|
||||
}
|
||||
|
||||
public void SetRgbaCurves(List<AnimationCurve> inRgbaCurves)
|
||||
{
|
||||
_curves = new List<AnimationCurve>();
|
||||
|
||||
for (int c = 0; c < (int)Channel.Num; c++)
|
||||
{
|
||||
if (inRgbaCurves?.Count > c && inRgbaCurves[c]?.keys.Length > 0)
|
||||
{
|
||||
_curves.Add(inRgbaCurves[c]);
|
||||
}
|
||||
else
|
||||
{
|
||||
_curves.Add(defaultCurve);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void AddKey(Keyframe key, ChannelMask channelMask)
|
||||
{
|
||||
for (int c = 0; c < (int)Channel.Num; c++)
|
||||
{
|
||||
if (!IsChannelIndexInMask(c, channelMask))
|
||||
continue;
|
||||
|
||||
_curves[c].AddKey(key);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public void AddKeys(Keyframe[] keys, ChannelMask channelMask)
|
||||
{
|
||||
for (int i = 0; i < keys?.Length; i++)
|
||||
{
|
||||
AddKey(keys[i], channelMask);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public List<AnimationCurve> rawCurves
|
||||
{
|
||||
get => _curves;
|
||||
set => SetRgbaCurves(value);
|
||||
}
|
||||
|
||||
public AnimationCurve redCurve
|
||||
{
|
||||
get => _curves[(int)Channel.Red] ?? defaultCurve;
|
||||
set => SetCurve(value, ChannelMask.Red);
|
||||
}
|
||||
|
||||
public AnimationCurve greenCurve
|
||||
{
|
||||
get => _curves[(int)Channel.Green] ?? defaultCurve;
|
||||
set => SetCurve(value, ChannelMask.Green);
|
||||
}
|
||||
|
||||
public AnimationCurve blueCurve
|
||||
{
|
||||
get => _curves[(int)Channel.Blue] ?? defaultCurve;
|
||||
set => SetCurve(value, ChannelMask.Blue);
|
||||
}
|
||||
|
||||
public AnimationCurve alphaCurve
|
||||
{
|
||||
get => _curves[(int)Channel.Alpha] ?? defaultCurve;
|
||||
set => SetCurve(value, ChannelMask.Alpha);
|
||||
}
|
||||
|
||||
|
||||
public Color Evaluate(float time, ChannelMask channelMask = ChannelMask.All, GradientTimeRange timeRange = GradientTimeRange.One)
|
||||
{
|
||||
time /= (int)timeRange;
|
||||
|
||||
if (channelMask == ChannelMask.Alpha)
|
||||
{
|
||||
var alpha = _curves[(int)Channel.Alpha].Evaluate(time);
|
||||
return new Color(alpha, alpha, alpha, 1);
|
||||
}
|
||||
|
||||
return new Color(
|
||||
IsChannelIndexInMask((int)Channel.Red, channelMask) ? _curves[(int)Channel.Red].Evaluate(time) : 0,
|
||||
IsChannelIndexInMask((int)Channel.Green, channelMask) ? _curves[(int)Channel.Green].Evaluate(time) : 0,
|
||||
IsChannelIndexInMask((int)Channel.Blue, channelMask) ? _curves[(int)Channel.Blue].Evaluate(time) : 0,
|
||||
IsChannelIndexInMask((int)Channel.Alpha, channelMask) ? _curves[(int)Channel.Alpha].Evaluate(time) : 1);
|
||||
}
|
||||
|
||||
public void SetLinearTangentMode()
|
||||
{
|
||||
for (int c = 0; c < (int)Channel.Num; c++)
|
||||
{
|
||||
_curves[c].SetLinearTangents();
|
||||
}
|
||||
}
|
||||
|
||||
#region LwguiGradient <=> Ramp Texture
|
||||
|
||||
public Color[] GetPixels(int width, int height, ChannelMask channelMask = ChannelMask.All)
|
||||
{
|
||||
var pixels = new Color[width * height];
|
||||
for (var x = 0; x < width; x++)
|
||||
{
|
||||
var u = x / (float)width;
|
||||
var col = Evaluate(u, channelMask);
|
||||
for (int i = 0; i < height; i++)
|
||||
{
|
||||
pixels[x + i * width] = col;
|
||||
}
|
||||
}
|
||||
|
||||
return pixels;
|
||||
}
|
||||
|
||||
public Texture2D GetPreviewRampTexture(int width = 256, int height = 1, ColorSpace colorSpace = ColorSpace.Gamma, ChannelMask channelMask = ChannelMask.All)
|
||||
{
|
||||
if (LwguiGradientHelper.TryGetRampPreview(this, width, height, colorSpace, channelMask, out var cachedPreview))
|
||||
return cachedPreview;
|
||||
|
||||
var rampPreview = new Texture2D(width, height, TextureFormat.RGBA32, false, colorSpace == ColorSpace.Linear);
|
||||
var pixels = GetPixels(width, height, channelMask);
|
||||
rampPreview.SetPixels(pixels);
|
||||
rampPreview.wrapMode = TextureWrapMode.Clamp;
|
||||
rampPreview.name = "LWGUI Gradient Preview";
|
||||
rampPreview.Apply();
|
||||
|
||||
LwguiGradientHelper.SetRampPreview(this, width, height, colorSpace, channelMask, rampPreview);
|
||||
return rampPreview;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region LwguiGradient <=> Gradient
|
||||
|
||||
public struct LwguiKeyframe
|
||||
{
|
||||
public float time;
|
||||
public float value;
|
||||
public int index;
|
||||
|
||||
public LwguiKeyframe(float time, float value, int index)
|
||||
{
|
||||
this.time = time;
|
||||
this.value = value;
|
||||
this.index = index;
|
||||
}
|
||||
}
|
||||
|
||||
public class LwguiMergedColorCurves : IDisposable
|
||||
{
|
||||
public List<List<LwguiKeyframe>> curves = new ();
|
||||
|
||||
public LwguiMergedColorCurves()
|
||||
{
|
||||
for (int c = 0; c < (int)Channel.Num; c++)
|
||||
curves.Add(new List<LwguiKeyframe>());
|
||||
}
|
||||
|
||||
public LwguiMergedColorCurves(List<AnimationCurve> rgbaCurves)
|
||||
{
|
||||
for (int c = 0; c < (int)Channel.Num; c++)
|
||||
curves.Add(new List<LwguiKeyframe>());
|
||||
|
||||
// Get color keys
|
||||
{
|
||||
var timeColorDic = new Dictionary<float, List<(float value, int index)>>();
|
||||
for (int c = 0; c < (int)Channel.Num - 1; c++)
|
||||
{
|
||||
var keys = rgbaCurves[c].keys;
|
||||
for (int j = 0; j < keys.Length; j++)
|
||||
{
|
||||
var keyframe = keys[j];
|
||||
if (timeColorDic.ContainsKey(keyframe.time))
|
||||
{
|
||||
timeColorDic[keyframe.time].Add((keyframe.value, j));
|
||||
}
|
||||
else
|
||||
{
|
||||
timeColorDic.Add(keyframe.time, new List<(float value, int index)> { (keyframe.value, j) });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
foreach (var kwPair in timeColorDic)
|
||||
{
|
||||
if (kwPair.Value.Count == (int)Channel.Num - 1)
|
||||
{
|
||||
for (int c = 0; c < (int)Channel.Num - 1; c++)
|
||||
{
|
||||
curves[c].Add(new LwguiKeyframe(kwPair.Key, kwPair.Value[c].value, kwPair.Value[c].index));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Get alpha keys
|
||||
for (int i = 0; i < rgbaCurves[(int)Channel.Alpha].keys.Length; i++)
|
||||
{
|
||||
var alphaKey = rgbaCurves[(int)Channel.Alpha].keys[i];
|
||||
curves[(int)Channel.Alpha].Add(new LwguiKeyframe(alphaKey.time, alphaKey.value, i));
|
||||
}
|
||||
}
|
||||
|
||||
public LwguiMergedColorCurves(Gradient gradient)
|
||||
{
|
||||
for (int c = 0; c < (int)Channel.Num; c++)
|
||||
curves.Add(new List<LwguiKeyframe>());
|
||||
|
||||
foreach (var colorKey in gradient.colorKeys)
|
||||
{
|
||||
for (int c = 0; c < (int)Channel.Num - 1; c++)
|
||||
{
|
||||
curves[c].Add(new LwguiKeyframe(colorKey.time, colorKey.color[c], 0));
|
||||
}
|
||||
}
|
||||
foreach (var alphaKey in gradient.alphaKeys)
|
||||
{
|
||||
curves[(int)Channel.Alpha].Add(new LwguiKeyframe(alphaKey.time, alphaKey.alpha, 0));
|
||||
}
|
||||
}
|
||||
|
||||
public Gradient ToGradient(int maxGradientKeyCount = 8) => new Gradient
|
||||
{
|
||||
colorKeys = curves[(int)Channel.Red].Select((keyframe, i) => new GradientColorKey(
|
||||
new Color(
|
||||
curves[(int)Channel.Red][i].value,
|
||||
curves[(int)Channel.Green][i].value,
|
||||
curves[(int)Channel.Blue][i].value),
|
||||
curves[(int)Channel.Red][i].time))
|
||||
.Where((key, i) => i < maxGradientKeyCount).ToArray(),
|
||||
|
||||
alphaKeys = curves[(int)Channel.Alpha].Select(alphaKey => new GradientAlphaKey(alphaKey.value, alphaKey.time))
|
||||
.Where((key, i) => i < maxGradientKeyCount).ToArray()
|
||||
};
|
||||
|
||||
public List<AnimationCurve> ToAnimationCurves()
|
||||
{
|
||||
var outCurves = new List<AnimationCurve>();
|
||||
for (int c = 0; c < (int)Channel.Num; c++)
|
||||
{
|
||||
var curve = new AnimationCurve();
|
||||
foreach (var key in curves[c])
|
||||
{
|
||||
curve.AddKey(new Keyframe(key.time, key.value).SetLinearTangentMode());
|
||||
}
|
||||
curve.SetLinearTangents();
|
||||
outCurves.Add(curve);
|
||||
}
|
||||
|
||||
return outCurves;
|
||||
}
|
||||
|
||||
public LwguiGradient ToLwguiGradient()
|
||||
{
|
||||
return new LwguiGradient(ToAnimationCurves());
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
curves?.Clear();
|
||||
}
|
||||
}
|
||||
|
||||
public static LwguiGradient FromGradient(Gradient gradient)
|
||||
{
|
||||
return new LwguiMergedColorCurves(gradient).ToLwguiGradient();
|
||||
}
|
||||
|
||||
public Gradient ToGradient(int maxGradientKeyCount = 8)
|
||||
{
|
||||
return new LwguiMergedColorCurves(_curves).ToGradient(maxGradientKeyCount);
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: a1c1406f2f784af489fb3758fb334d07
|
||||
timeCreated: 1716793021
|
||||
@ -0,0 +1,91 @@
|
||||
// Copyright (c) Jason Ma
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using UnityEngine;
|
||||
|
||||
// Disable Keyframe.tangentMode obsolete warning
|
||||
#pragma warning disable 0618
|
||||
|
||||
|
||||
namespace LWGUI.Runtime.LwguiGradient
|
||||
{
|
||||
public static class LwguiGradientHelper
|
||||
{
|
||||
#region Extended Methods
|
||||
|
||||
public static Keyframe SetLinearTangentMode(this Keyframe key)
|
||||
{
|
||||
key.tangentMode = 69;
|
||||
return key;
|
||||
}
|
||||
|
||||
public static void SetLinearTangents(this AnimationCurve curve)
|
||||
{
|
||||
for (int i = 1; i < curve.keys.Length; i++)
|
||||
{
|
||||
var keyStart = curve.keys[i - 1];
|
||||
var keyEnd = curve.keys[i];
|
||||
float tangent = (keyEnd.value - keyStart.value) / (keyEnd.time - keyStart.time);
|
||||
keyStart.outTangent = tangent;
|
||||
keyEnd.inTangent = tangent;
|
||||
curve.MoveKey(i - 1, keyStart);
|
||||
curve.MoveKey(i, keyEnd);
|
||||
}
|
||||
}
|
||||
|
||||
public static void DestroyInEditorOrRuntime(this UnityEngine.Object obj)
|
||||
{
|
||||
#if UNITY_EDITOR
|
||||
Object.DestroyImmediate(obj);
|
||||
#else
|
||||
Object.Destroy(obj);
|
||||
#endif
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Ramp Preview Caches
|
||||
|
||||
private static Dictionary<int/* LwguiGradient Value Based Hash */,
|
||||
Dictionary<(int, int, ColorSpace, LwguiGradient.ChannelMask), Texture2D>> _gradientToPreviewDic;
|
||||
|
||||
public static bool TryGetRampPreview(LwguiGradient gradient, int width, int height, ColorSpace colorSpace, LwguiGradient.ChannelMask channelMask,
|
||||
out Texture2D cachedPreview)
|
||||
{
|
||||
cachedPreview = _gradientToPreviewDic?.GetValueOrDefault(gradient.GetValueBasedHashCode())?.GetValueOrDefault((width, height, colorSpace, channelMask));
|
||||
return cachedPreview;
|
||||
}
|
||||
|
||||
public static void SetRampPreview(LwguiGradient gradient, int width, int height, ColorSpace colorSpace, LwguiGradient.ChannelMask channelMask, Texture2D newPreviewTex)
|
||||
{
|
||||
_gradientToPreviewDic ??= new Dictionary<int, Dictionary<(int, int, ColorSpace, LwguiGradient.ChannelMask), Texture2D>>();
|
||||
var hash = gradient.GetValueBasedHashCode();
|
||||
|
||||
if (!_gradientToPreviewDic.ContainsKey(hash))
|
||||
{
|
||||
_gradientToPreviewDic[hash] = new Dictionary<(int, int, ColorSpace, LwguiGradient.ChannelMask), Texture2D>();
|
||||
}
|
||||
|
||||
if (_gradientToPreviewDic[hash].ContainsKey((width, height, colorSpace, channelMask)))
|
||||
{
|
||||
_gradientToPreviewDic[hash][(width, height, colorSpace, channelMask)].DestroyInEditorOrRuntime();
|
||||
}
|
||||
|
||||
_gradientToPreviewDic[hash][(width, height, colorSpace, channelMask)] = newPreviewTex;
|
||||
}
|
||||
|
||||
public static void ClearRampPreviewCaches()
|
||||
{
|
||||
if (_gradientToPreviewDic == null) return;
|
||||
|
||||
foreach (var paramsToPreviewTexDic in _gradientToPreviewDic.Values)
|
||||
{
|
||||
paramsToPreviewTexDic.Values.ToList().ForEach(previewTex => previewTex.DestroyInEditorOrRuntime());
|
||||
}
|
||||
_gradientToPreviewDic.Clear();
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: dacb09adca6c4f07b8f5fa5acdc7cbfd
|
||||
timeCreated: 1720172986
|
||||
@ -10,7 +10,7 @@ MonoBehaviour:
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: 28fbcbca3fb14507af6ed5c104c40b84, type: 3}
|
||||
m_Name: LWGUI_BlendModePreset
|
||||
m_Name: LWGUI_Preset_BlendMode
|
||||
m_EditorClassIdentifier:
|
||||
presets:
|
||||
- presetName: Opaque
|
||||
29
Assets/External/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Test/LWGUI_Preset_Toggle.asset
vendored
Normal file
29
Assets/External/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Test/LWGUI_Preset_Toggle.asset
vendored
Normal file
@ -0,0 +1,29 @@
|
||||
%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: 28fbcbca3fb14507af6ed5c104c40b84, type: 3}
|
||||
m_Name: LWGUI_Preset_Toggle
|
||||
m_EditorClassIdentifier:
|
||||
presets:
|
||||
- presetName: Disable
|
||||
propertyValues: []
|
||||
enabledKeywords: []
|
||||
disabledKeywords: []
|
||||
enabledPasses: []
|
||||
disabledPasses: []
|
||||
renderQueue: 2000
|
||||
- presetName: Enable
|
||||
propertyValues: []
|
||||
enabledKeywords: []
|
||||
disabledKeywords: []
|
||||
enabledPasses: []
|
||||
disabledPasses: []
|
||||
renderQueue: 2001
|
||||
8
Assets/External/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Test/LWGUI_Preset_Toggle.asset.meta
vendored
Normal file
8
Assets/External/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Test/LWGUI_Preset_Toggle.asset.meta
vendored
Normal file
@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c3b3b9433213824419f41452830ee4ea
|
||||
NativeFormatImporter:
|
||||
externalObjects: {}
|
||||
mainObjectFileID: 11400000
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@ -9,16 +9,20 @@ Material:
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_Name: LWGUI_SampleDrawer 1
|
||||
m_Shader: {fileID: 4800000, guid: 7ee048c9536c0344bb8b4860595a4d9b, type: 3}
|
||||
m_Parent: {fileID: 0}
|
||||
m_ModifiedSerializedProperties: 0
|
||||
m_ValidKeywords: []
|
||||
m_InvalidKeywords:
|
||||
- _GROUP_ON
|
||||
- _KEY2
|
||||
- _KEY3
|
||||
m_LightmapFlags: 4
|
||||
m_EnableInstancingVariants: 0
|
||||
m_DoubleSidedGI: 0
|
||||
m_CustomRenderQueue: 3000
|
||||
stringTagMap: {}
|
||||
disabledShaderPasses: []
|
||||
m_LockedProperties:
|
||||
m_SavedProperties:
|
||||
serializedVersion: 3
|
||||
m_TexEnvs:
|
||||
|
||||
@ -20,12 +20,11 @@ TextureImporter:
|
||||
externalNormalMap: 0
|
||||
heightScale: 0.25
|
||||
normalMapFilter: 0
|
||||
flipGreenChannel: 0
|
||||
isReadable: 1
|
||||
streamingMipmaps: 0
|
||||
streamingMipmapsPriority: 0
|
||||
vTOnly: 0
|
||||
ignoreMipmapLimit: 0
|
||||
ignoreMasterTextureLimit: 0
|
||||
grayScaleToAlpha: 0
|
||||
generateCubemap: 6
|
||||
cubemapConvolution: 0
|
||||
@ -64,7 +63,6 @@ TextureImporter:
|
||||
textureFormatSet: 0
|
||||
ignorePngGamma: 0
|
||||
applyGammaDecoding: 0
|
||||
swizzle: 50462976
|
||||
cookieLightType: 0
|
||||
platformSettings:
|
||||
- serializedVersion: 3
|
||||
@ -77,7 +75,6 @@ TextureImporter:
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
ignorePlatformSupport: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
- serializedVersion: 3
|
||||
@ -90,7 +87,6 @@ TextureImporter:
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
ignorePlatformSupport: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
- serializedVersion: 3
|
||||
@ -103,7 +99,6 @@ TextureImporter:
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
ignorePlatformSupport: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
spriteSheet:
|
||||
@ -120,8 +115,9 @@ TextureImporter:
|
||||
weights: []
|
||||
secondaryTextures: []
|
||||
nameFileIdTable: {}
|
||||
mipmapLimitGroupName:
|
||||
spritePackingTag:
|
||||
pSDRemoveMatte: 0
|
||||
userData: '{"MonoBehaviour":{"m_Enabled":true,"m_EditorHideFlags":0,"m_Name":"","m_EditorClassIdentifier":"","gradient":{"serializedVersion":"2","key0":{"r":0.0,"g":0.0,"b":0.0,"a":1.0},"key1":{"r":1.0,"g":1.0,"b":1.0,"a":1.0},"key2":{"r":0.0,"g":0.0,"b":0.0,"a":0.0},"key3":{"r":0.0,"g":0.0,"b":0.0,"a":0.0},"key4":{"r":0.0,"g":0.0,"b":0.0,"a":0.0},"key5":{"r":0.0,"g":0.0,"b":0.0,"a":0.0},"key6":{"r":0.0,"g":0.0,"b":0.0,"a":0.0},"key7":{"r":0.0,"g":0.0,"b":0.0,"a":0.0},"ctime0":0,"ctime1":65535,"ctime2":0,"ctime3":0,"ctime4":0,"ctime5":0,"ctime6":0,"ctime7":0,"atime0":0,"atime1":65535,"atime2":0,"atime3":0,"atime4":0,"atime5":0,"atime6":0,"atime7":0,"m_Mode":0,"m_ColorSpace":1,"m_NumColorKeys":2,"m_NumAlphaKeys":2}}}#{"MonoBehaviour":{"m_Enabled":true,"m_EditorHideFlags":0,"m_Name":"","m_EditorClassIdentifier":"","gradient":{"serializedVersion":"2","key0":{"r":0.0,"g":0.0,"b":0.0,"a":1.0},"key1":{"r":1.0,"g":1.0,"b":1.0,"a":1.0},"key2":{"r":0.0,"g":0.0,"b":0.0,"a":0.0},"key3":{"r":0.0,"g":0.0,"b":0.0,"a":0.0},"key4":{"r":0.0,"g":0.0,"b":0.0,"a":0.0},"key5":{"r":0.0,"g":0.0,"b":0.0,"a":0.0},"key6":{"r":0.0,"g":0.0,"b":0.0,"a":0.0},"key7":{"r":0.0,"g":0.0,"b":0.0,"a":0.0},"ctime0":0,"ctime1":65535,"ctime2":0,"ctime3":0,"ctime4":0,"ctime5":0,"ctime6":0,"ctime7":0,"atime0":0,"atime1":65535,"atime2":0,"atime3":0,"atime4":0,"atime5":0,"atime6":0,"atime7":0,"m_Mode":0,"m_ColorSpace":1,"m_NumColorKeys":2,"m_NumAlphaKeys":2}}}'
|
||||
pSDShowRemoveMatteOption: 0
|
||||
userData: '{"_curves":[{"serializedVersion":"2","m_Curve":[{"serializedVersion":"3","time":0.0,"value":0.0,"inSlope":0.0,"outSlope":1.0,"tangentMode":69,"weightedMode":0,"inWeight":0.0,"outWeight":0.0},{"serializedVersion":"3","time":1.0,"value":1.0,"inSlope":1.0,"outSlope":0.0,"tangentMode":69,"weightedMode":0,"inWeight":0.0,"outWeight":0.0}],"m_PreInfinity":2,"m_PostInfinity":2,"m_RotationOrder":4},{"serializedVersion":"2","m_Curve":[{"serializedVersion":"3","time":0.0,"value":0.0,"inSlope":0.0,"outSlope":1.0,"tangentMode":69,"weightedMode":0,"inWeight":0.0,"outWeight":0.0},{"serializedVersion":"3","time":1.0,"value":1.0,"inSlope":1.0,"outSlope":0.0,"tangentMode":69,"weightedMode":0,"inWeight":0.0,"outWeight":0.0}],"m_PreInfinity":2,"m_PostInfinity":2,"m_RotationOrder":4},{"serializedVersion":"2","m_Curve":[{"serializedVersion":"3","time":0.0,"value":0.0,"inSlope":0.0,"outSlope":1.0,"tangentMode":69,"weightedMode":0,"inWeight":0.0,"outWeight":0.0},{"serializedVersion":"3","time":1.0,"value":1.0,"inSlope":1.0,"outSlope":0.0,"tangentMode":69,"weightedMode":0,"inWeight":0.0,"outWeight":0.0}],"m_PreInfinity":2,"m_PostInfinity":2,"m_RotationOrder":4},{"serializedVersion":"2","m_Curve":[{"serializedVersion":"3","time":0.0,"value":1.0,"inSlope":0.0,"outSlope":0.0,"tangentMode":69,"weightedMode":0,"inWeight":0.0,"outWeight":0.0},{"serializedVersion":"3","time":1.0,"value":1.0,"inSlope":0.0,"outSlope":0.0,"tangentMode":69,"weightedMode":0,"inWeight":0.0,"outWeight":0.0}],"m_PreInfinity":2,"m_PostInfinity":2,"m_RotationOrder":4}]}#{"_curves":[{"serializedVersion":"2","m_Curve":[{"serializedVersion":"3","time":0.0,"value":0.0,"inSlope":0.0,"outSlope":1.0,"tangentMode":69,"weightedMode":0,"inWeight":0.0,"outWeight":0.0},{"serializedVersion":"3","time":1.0,"value":1.0,"inSlope":1.0,"outSlope":0.0,"tangentMode":69,"weightedMode":0,"inWeight":0.0,"outWeight":0.0}],"m_PreInfinity":2,"m_PostInfinity":2,"m_RotationOrder":4},{"serializedVersion":"2","m_Curve":[{"serializedVersion":"3","time":0.0,"value":0.0,"inSlope":0.0,"outSlope":1.0,"tangentMode":69,"weightedMode":0,"inWeight":0.0,"outWeight":0.0},{"serializedVersion":"3","time":1.0,"value":1.0,"inSlope":1.0,"outSlope":0.0,"tangentMode":69,"weightedMode":0,"inWeight":0.0,"outWeight":0.0}],"m_PreInfinity":2,"m_PostInfinity":2,"m_RotationOrder":4},{"serializedVersion":"2","m_Curve":[{"serializedVersion":"3","time":0.0,"value":0.0,"inSlope":0.0,"outSlope":1.0,"tangentMode":69,"weightedMode":0,"inWeight":0.0,"outWeight":0.0},{"serializedVersion":"3","time":1.0,"value":1.0,"inSlope":1.0,"outSlope":0.0,"tangentMode":69,"weightedMode":0,"inWeight":0.0,"outWeight":0.0}],"m_PreInfinity":2,"m_PostInfinity":2,"m_RotationOrder":4},{"serializedVersion":"2","m_Curve":[{"serializedVersion":"3","time":0.0,"value":1.0,"inSlope":0.0,"outSlope":0.0,"tangentMode":69,"weightedMode":0,"inWeight":0.0,"outWeight":0.0},{"serializedVersion":"3","time":1.0,"value":1.0,"inSlope":0.0,"outSlope":0.0,"tangentMode":69,"weightedMode":0,"inWeight":0.0,"outWeight":0.0}],"m_PreInfinity":2,"m_PostInfinity":2,"m_RotationOrder":4}]}'
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
||||
BIN
Assets/External/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Test/RampMap_Test.png
(Stored with Git LFS)
vendored
Normal file
BIN
Assets/External/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Test/RampMap_Test.png
(Stored with Git LFS)
vendored
Normal file
Binary file not shown.
127
Assets/External/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Test/RampMap_Test.png.meta
vendored
Normal file
127
Assets/External/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Test/RampMap_Test.png.meta
vendored
Normal file
@ -0,0 +1,127 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 1522a7c4f7317044ab912724c1594427
|
||||
TextureImporter:
|
||||
internalIDToNameTable: []
|
||||
externalObjects: {}
|
||||
serializedVersion: 12
|
||||
mipmaps:
|
||||
mipMapMode: 0
|
||||
enableMipMap: 0
|
||||
sRGBTexture: 1
|
||||
linearTexture: 0
|
||||
fadeOut: 0
|
||||
borderMipMap: 0
|
||||
mipMapsPreserveCoverage: 0
|
||||
alphaTestReferenceValue: 0.5
|
||||
mipMapFadeDistanceStart: 1
|
||||
mipMapFadeDistanceEnd: 3
|
||||
bumpmap:
|
||||
convertToNormalMap: 0
|
||||
externalNormalMap: 0
|
||||
heightScale: 0.25
|
||||
normalMapFilter: 0
|
||||
flipGreenChannel: 0
|
||||
isReadable: 1
|
||||
streamingMipmaps: 0
|
||||
streamingMipmapsPriority: 0
|
||||
vTOnly: 0
|
||||
ignoreMipmapLimit: 0
|
||||
grayScaleToAlpha: 0
|
||||
generateCubemap: 6
|
||||
cubemapConvolution: 0
|
||||
seamlessCubemap: 0
|
||||
textureFormat: 1
|
||||
maxTextureSize: 2048
|
||||
textureSettings:
|
||||
serializedVersion: 2
|
||||
filterMode: 1
|
||||
aniso: 1
|
||||
mipBias: 0
|
||||
wrapU: 1
|
||||
wrapV: 1
|
||||
wrapW: 1
|
||||
nPOTScale: 1
|
||||
lightmap: 0
|
||||
compressionQuality: 50
|
||||
spriteMode: 0
|
||||
spriteExtrude: 1
|
||||
spriteMeshType: 1
|
||||
alignment: 0
|
||||
spritePivot: {x: 0.5, y: 0.5}
|
||||
spritePixelsToUnits: 100
|
||||
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
|
||||
spriteGenerateFallbackPhysicsShape: 1
|
||||
alphaUsage: 1
|
||||
alphaIsTransparency: 0
|
||||
spriteTessellationDetail: -1
|
||||
textureType: 0
|
||||
textureShape: 1
|
||||
singleChannelComponent: 0
|
||||
flipbookRows: 1
|
||||
flipbookColumns: 1
|
||||
maxTextureSizeSet: 0
|
||||
compressionQualitySet: 0
|
||||
textureFormatSet: 0
|
||||
ignorePngGamma: 0
|
||||
applyGammaDecoding: 0
|
||||
swizzle: 50462976
|
||||
cookieLightType: 0
|
||||
platformSettings:
|
||||
- serializedVersion: 3
|
||||
buildTarget: DefaultTexturePlatform
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: 4
|
||||
textureCompression: 0
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
ignorePlatformSupport: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
- serializedVersion: 3
|
||||
buildTarget: Standalone
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
ignorePlatformSupport: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
- serializedVersion: 3
|
||||
buildTarget: Server
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
ignorePlatformSupport: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
spriteSheet:
|
||||
serializedVersion: 2
|
||||
sprites: []
|
||||
outline: []
|
||||
physicsShape: []
|
||||
bones: []
|
||||
spriteID:
|
||||
internalID: 0
|
||||
vertices: []
|
||||
indices:
|
||||
edges: []
|
||||
weights: []
|
||||
secondaryTextures: []
|
||||
nameFileIdTable: {}
|
||||
mipmapLimitGroupName:
|
||||
pSDRemoveMatte: 0
|
||||
userData: '{"_curves":[{"serializedVersion":"2","m_Curve":[{"serializedVersion":"3","time":0.0,"value":0.0,"inSlope":0.0,"outSlope":1.0,"tangentMode":69,"weightedMode":0,"inWeight":0.0,"outWeight":0.0},{"serializedVersion":"3","time":1.0,"value":1.0,"inSlope":1.0,"outSlope":0.0,"tangentMode":69,"weightedMode":0,"inWeight":0.0,"outWeight":0.0}],"m_PreInfinity":2,"m_PostInfinity":2,"m_RotationOrder":4},{"serializedVersion":"2","m_Curve":[{"serializedVersion":"3","time":0.0,"value":0.0,"inSlope":0.0,"outSlope":1.0,"tangentMode":69,"weightedMode":0,"inWeight":0.0,"outWeight":0.0},{"serializedVersion":"3","time":1.0,"value":1.0,"inSlope":1.0,"outSlope":0.0,"tangentMode":69,"weightedMode":0,"inWeight":0.0,"outWeight":0.0}],"m_PreInfinity":2,"m_PostInfinity":2,"m_RotationOrder":4},{"serializedVersion":"2","m_Curve":[{"serializedVersion":"3","time":0.0,"value":0.0,"inSlope":0.0,"outSlope":1.0,"tangentMode":69,"weightedMode":0,"inWeight":0.0,"outWeight":0.0},{"serializedVersion":"3","time":1.0,"value":1.0,"inSlope":1.0,"outSlope":0.0,"tangentMode":69,"weightedMode":0,"inWeight":0.0,"outWeight":0.0}],"m_PreInfinity":2,"m_PostInfinity":2,"m_RotationOrder":4},{"serializedVersion":"2","m_Curve":[{"serializedVersion":"3","time":0.0,"value":1.0,"inSlope":0.0,"outSlope":0.0,"tangentMode":69,"weightedMode":0,"inWeight":0.0,"outWeight":0.0},{"serializedVersion":"3","time":1.0,"value":1.0,"inSlope":0.0,"outSlope":0.0,"tangentMode":69,"weightedMode":0,"inWeight":0.0,"outWeight":0.0}],"m_PreInfinity":2,"m_PostInfinity":2,"m_RotationOrder":4}]}#{"_curves":[{"serializedVersion":"2","m_Curve":[{"serializedVersion":"3","time":0.0,"value":0.0,"inSlope":0.0,"outSlope":1.0,"tangentMode":69,"weightedMode":0,"inWeight":0.0,"outWeight":0.0},{"serializedVersion":"3","time":1.0,"value":1.0,"inSlope":1.0,"outSlope":0.0,"tangentMode":69,"weightedMode":0,"inWeight":0.0,"outWeight":0.0}],"m_PreInfinity":2,"m_PostInfinity":2,"m_RotationOrder":4},{"serializedVersion":"2","m_Curve":[{"serializedVersion":"3","time":0.0,"value":0.0,"inSlope":0.0,"outSlope":1.0,"tangentMode":69,"weightedMode":0,"inWeight":0.0,"outWeight":0.0},{"serializedVersion":"3","time":1.0,"value":1.0,"inSlope":1.0,"outSlope":0.0,"tangentMode":69,"weightedMode":0,"inWeight":0.0,"outWeight":0.0}],"m_PreInfinity":2,"m_PostInfinity":2,"m_RotationOrder":4},{"serializedVersion":"2","m_Curve":[{"serializedVersion":"3","time":0.0,"value":0.0,"inSlope":0.0,"outSlope":1.0,"tangentMode":69,"weightedMode":0,"inWeight":0.0,"outWeight":0.0},{"serializedVersion":"3","time":1.0,"value":1.0,"inSlope":1.0,"outSlope":0.0,"tangentMode":69,"weightedMode":0,"inWeight":0.0,"outWeight":0.0}],"m_PreInfinity":2,"m_PostInfinity":2,"m_RotationOrder":4},{"serializedVersion":"2","m_Curve":[{"serializedVersion":"3","time":0.0,"value":1.0,"inSlope":0.0,"outSlope":0.0,"tangentMode":69,"weightedMode":0,"inWeight":0.0,"outWeight":0.0},{"serializedVersion":"3","time":1.0,"value":1.0,"inSlope":0.0,"outSlope":0.0,"tangentMode":69,"weightedMode":0,"inWeight":0.0,"outWeight":0.0}],"m_PreInfinity":2,"m_PostInfinity":2,"m_RotationOrder":4}]}'
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
File diff suppressed because one or more lines are too long
@ -12,6 +12,7 @@
|
||||
[Main(Group1, _KEYWORD, on)] _group1 ("Group - Default Open", float) = 1
|
||||
[Preset(Group1, LWGUI_ShaderPropertyPreset)] _preset ("Preset Sample", float) = 0
|
||||
[Preset(Group1, LWGUI_ShaderPropertyPreset1)] _preset1 ("Preset Sample 1", float) = 0
|
||||
[SubToggle(Group1, _, LWGUI_Preset_Toggle)] _preset_toggle ("Preset Toggle Sample", float) = 0
|
||||
[Sub(Group1)] _float1 ("Sub Float", float) = 0
|
||||
[Sub(Group1)] _vector1 ("Sub Vector", vector) = (1, 1, 1, 1)
|
||||
[Sub(Group1)] [HDR] _color1 ("Sub HDR Color", color) = (0.7, 0.7, 1, 1)
|
||||
@ -36,7 +37,7 @@
|
||||
[Advanced][Tex(Group2, _AdvancedColor0)] _AdvancedTex1 ("Advanced Tex 1", 2D) = "white" { }
|
||||
[Advanced][HideInInspector] _AdvancedColor0 ("Advanced Color 0", Color) = (1, 1, 1, 1)
|
||||
[AdvancedHeaderProperty][Sub(Group2)] _AdvancedFloat ("Advanced Image", float) = 0
|
||||
[Advanced][Image(Group2)] _AdvancedImage ("Advanced Image", 2D) = "white" { }
|
||||
[Advanced][Image(Group2)] _AdvancedImage ("../image-20220828003810353.png", float) = 0
|
||||
|
||||
[Title(Channel Samples)]
|
||||
[Channel] _textureChannelMask ("Texture Channel Mask (Default G)", Vector) = (0, 1, 0, 0)
|
||||
@ -76,6 +77,9 @@
|
||||
[MinMaxSlider(_rangeStart, _rangeEnd)] _minMaxSlider ("Min Max Slider (0 - 1)", Range(0.0, 1.0)) = 1.0
|
||||
_rangeStart ("Range Start", Range(0.0, 0.5)) = 0.0
|
||||
[PowerSlider(10)] _rangeEnd ("Range End PowerSlider", Range(0.5, 1.0)) = 1.0
|
||||
|
||||
[Title(Button Samples)]
|
||||
[Button(_)] _button0 ("URL Button@URL:https://github.com/JasonMa0012/LWGUI@C# Button@C#:LWGUI.ButtonDrawer.TestMethod(1234, abcd)", Float) = 0
|
||||
}
|
||||
|
||||
HLSLINCLUDE
|
||||
|
||||
@ -44,7 +44,7 @@
|
||||
|
||||
|
||||
[Main(Preset, _, on, off)] _PresetGroup ("Preset Samples", float) = 0
|
||||
[Preset(Preset, LWGUI_BlendModePreset)] _BlendMode ("Blend Mode Preset", float) = 0
|
||||
[Preset(Preset, LWGUI_Preset_BlendMode)] _BlendMode ("Blend Mode Preset", float) = 0
|
||||
[SubEnum(Preset, UnityEngine.Rendering.CullMode)] _Cull ("Cull", Float) = 2
|
||||
[SubEnum(Preset, UnityEngine.Rendering.BlendMode)] _SrcBlend ("SrcBlend", Float) = 1
|
||||
[SubEnum(Preset, UnityEngine.Rendering.BlendMode)] _DstBlend ("DstBlend", Float) = 0
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 6ea7dfa994ebd3c42aed7934d8377314
|
||||
guid: 56e3a65fe6e61904a94a3cd1ea19a8ee
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 76783890193e4d1aaab781515ec60548
|
||||
timeCreated: 1720764555
|
||||
@ -0,0 +1,58 @@
|
||||
// Copyright (c) Jason Ma
|
||||
|
||||
using System;
|
||||
using UnityEngine;
|
||||
using UnityEditor;
|
||||
using LWGUI.Runtime.LwguiGradient;
|
||||
|
||||
namespace LWGUI.LwguiGradientEditor
|
||||
{
|
||||
[System.AttributeUsage(AttributeTargets.Field, Inherited = true, AllowMultiple = false)]
|
||||
public sealed class LwguiGradientUsageAttribute : PropertyAttribute
|
||||
{
|
||||
public ColorSpace colorSpace;
|
||||
public LwguiGradient.ChannelMask viewChannelMask;
|
||||
public LwguiGradient.GradientTimeRange timeRange;
|
||||
|
||||
public LwguiGradientUsageAttribute(ColorSpace colorSpace = ColorSpace.Gamma, LwguiGradient.ChannelMask viewChannelMask = LwguiGradient.ChannelMask.All, LwguiGradient.GradientTimeRange timeRange = LwguiGradient.GradientTimeRange.One)
|
||||
{
|
||||
this.colorSpace = colorSpace;
|
||||
this.viewChannelMask = viewChannelMask;
|
||||
this.timeRange = timeRange;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
[CustomPropertyDrawer(typeof(LwguiGradientUsageAttribute))]
|
||||
internal sealed class LwguiGradientUsageDrawer : LwguiGradientPropertyDrawer
|
||||
{
|
||||
public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
|
||||
{
|
||||
var colorUsage = (LwguiGradientUsageAttribute)attribute;
|
||||
|
||||
colorSpace = colorUsage.colorSpace;
|
||||
viewChannelMask = colorUsage.viewChannelMask;
|
||||
timeRange = colorUsage.timeRange;
|
||||
base.OnGUI(position, property, label);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
[CustomPropertyDrawer(typeof(LwguiGradient))]
|
||||
public class LwguiGradientPropertyDrawer : PropertyDrawer
|
||||
{
|
||||
public ColorSpace colorSpace = ColorSpace.Gamma;
|
||||
public LwguiGradient.ChannelMask viewChannelMask = LwguiGradient.ChannelMask.All;
|
||||
public LwguiGradient.GradientTimeRange timeRange = LwguiGradient.GradientTimeRange.One;
|
||||
|
||||
public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
|
||||
{
|
||||
EditorGUI.BeginChangeCheck();
|
||||
var gradient = (LwguiGradient)fieldInfo.GetValue(property.serializedObject.targetObject);
|
||||
LwguiGradientEditorHelper.GradientField(position, label, property, gradient, colorSpace, viewChannelMask, timeRange);
|
||||
if (EditorGUI.EndChangeCheck())
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 9672b824fb314326a5fd4078a7068d89
|
||||
timeCreated: 1716793950
|
||||
@ -0,0 +1,851 @@
|
||||
// Copyright (c) Jason Ma
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using UnityEngine;
|
||||
using UnityEditor;
|
||||
using LWGUI.Runtime.LwguiGradient;
|
||||
|
||||
namespace LWGUI.LwguiGradientEditor
|
||||
{
|
||||
public class LwguiGradientEditor
|
||||
{
|
||||
private class CurveSelectionInfo
|
||||
{
|
||||
public List<AnimationCurve> selectedAnimationCurves;
|
||||
public Vector4 selectedVectorValue = Vector4.negativeInfinity;
|
||||
public float selectedFloatValue = float.NegativeInfinity;
|
||||
public float selectedTime = float.NegativeInfinity;
|
||||
public bool isOnlyColorKeySelected;
|
||||
public LwguiGradient.LwguiMergedColorCurves mergedCurves;
|
||||
|
||||
public bool hasMixedTime;
|
||||
public bool hasMixedFloatValue; // Selected multiple keys with different values in a same Curve
|
||||
public bool hasMixedColorValue; // Selected multiple color keys with different values in the RGB Curves
|
||||
public List<bool> hasMixedChannelValue = Enumerable.Repeat(false, (int)LwguiGradient.Channel.Num).ToList();
|
||||
|
||||
public CurveSelectionInfo(CurveEditor curveEditor)
|
||||
{
|
||||
selectedAnimationCurves = new List<AnimationCurve>();
|
||||
for (int c = 0; c < (int)LwguiGradient.Channel.Num; c++)
|
||||
selectedAnimationCurves.Add(new AnimationCurve());
|
||||
|
||||
if (curveEditor?.selectedCurves is { Count: > 0 })
|
||||
{
|
||||
foreach (var curveSelection in curveEditor.selectedCurves.Where(selection => selection != null))
|
||||
{
|
||||
var channelID = curveSelection.curveID;
|
||||
var key = curveEditor.GetKeyframeFromSelection(curveSelection);
|
||||
selectedAnimationCurves[channelID].AddKey(key);
|
||||
|
||||
if (selectedTime != float.NegativeInfinity && selectedTime != key.time)
|
||||
hasMixedTime = true;
|
||||
selectedTime = key.time;
|
||||
|
||||
if (selectedVectorValue[channelID] != Vector4.negativeInfinity[channelID] && selectedVectorValue[channelID] != key.value)
|
||||
hasMixedChannelValue[channelID] = true;
|
||||
selectedVectorValue[channelID] = key.value;
|
||||
|
||||
if (selectedFloatValue != float.NegativeInfinity && selectedFloatValue != key.value)
|
||||
hasMixedFloatValue = true;
|
||||
selectedFloatValue = key.value;
|
||||
}
|
||||
|
||||
for (int i = 0; i < 4; i++)
|
||||
{
|
||||
if (selectedVectorValue[i] == Vector4.negativeInfinity[i])
|
||||
selectedVectorValue[i] = 0;
|
||||
}
|
||||
|
||||
if (selectedFloatValue == float.NegativeInfinity)
|
||||
selectedFloatValue = 0;
|
||||
|
||||
mergedCurves = new LwguiGradient.LwguiMergedColorCurves(selectedAnimationCurves);
|
||||
|
||||
var noAlphaKeySelected = mergedCurves.curves[(int)LwguiGradient.Channel.Alpha].Count == 0;
|
||||
hasMixedColorValue = noAlphaKeySelected && hasMixedChannelValue. Where((_, c) => c < (int)LwguiGradient.Channel.Alpha).Any(b => b);
|
||||
isOnlyColorKeySelected = noAlphaKeySelected && selectedAnimationCurves.Where((_, c) => c < (int)LwguiGradient.Channel.Alpha).All(curve => curve.length == mergedCurves.curves[(int)LwguiGradient.Channel.Red].Count);
|
||||
}
|
||||
else
|
||||
{
|
||||
mergedCurves = new LwguiGradient.LwguiMergedColorCurves();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#region UI Layout
|
||||
|
||||
private bool _useSignalLineEditField => _position.width > 1150;
|
||||
|
||||
private float _gradientEditorHeisht => _useSignalLineEditField ? 160 : 160 + _editFieldHeight;
|
||||
private float _margin => 8;
|
||||
private float _editFieldHeight => EditorGUIUtility.singleLineHeight; // 18
|
||||
private float _editFieldMarginsHeight => _margin * (_useSignalLineEditField ? 2 : 3);
|
||||
private float _gradientAndSwatchHeight => _gradientEditorHeisht - _margin - _editFieldMarginsHeight - _editFieldHeight - _secondEditFieldRect.height;
|
||||
private float _swatchHeisht => _gradientAndSwatchHeight * 0.15f;
|
||||
private float _alphaGradientHeisht => _rgbGradientHeisht * 0.5f;
|
||||
private float _rgbGradientHeisht => (_gradientAndSwatchHeight - _swatchHeisht * 2) * 0.66666f;
|
||||
|
||||
private Rect _gradientEditorRect => new Rect(0, 0, _position.width, _gradientEditorHeisht);
|
||||
private Rect _editFieldRect => new Rect(_curveEditor.leftmargin, _margin, _position.width - _curveEditor.leftmargin - _curveEditor.rightmargin, _editFieldHeight);
|
||||
private Rect _secondEditFieldRect => _useSignalLineEditField ? Rect.zero : new Rect(_curveEditor.leftmargin, _margin * 2 + _editFieldHeight, _position.width - _curveEditor.leftmargin - _curveEditor.rightmargin, _editFieldHeight);
|
||||
private Rect _alphaSwatchesRect => new Rect(_curveEditor.leftmargin, _editFieldMarginsHeight + _editFieldHeight + _secondEditFieldRect.height, _position.width - _curveEditor.leftmargin - _curveEditor.rightmargin, _swatchHeisht);
|
||||
private Rect _rgbSwatchesRect => new Rect(_curveEditor.leftmargin, _editFieldMarginsHeight + _editFieldHeight + _secondEditFieldRect.height + _swatchHeisht + _alphaGradientHeisht + _rgbGradientHeisht, _position.width - _curveEditor.leftmargin - _curveEditor.rightmargin, _swatchHeisht);
|
||||
private Rect _alphaGradientRect => new Rect(_curveEditor.leftmargin, _editFieldMarginsHeight + _editFieldHeight + _secondEditFieldRect.height + _swatchHeisht, _position.width - _curveEditor.leftmargin - _curveEditor.rightmargin, _alphaGradientHeisht);
|
||||
private Rect _rgbGradientRect => new Rect(_curveEditor.leftmargin, _editFieldMarginsHeight + _editFieldHeight + _secondEditFieldRect.height + _swatchHeisht + _alphaGradientHeisht, _position.width - _curveEditor.leftmargin - _curveEditor.rightmargin, _rgbGradientHeisht);
|
||||
|
||||
private Rect _curveEditorRect => new Rect(0, _gradientEditorHeisht, _position.width, _position.height - _gradientEditorHeisht);
|
||||
|
||||
|
||||
private static readonly GUIContent[] s_XYZWLabels = {EditorGUIUtility.TextContent("R"), EditorGUIUtility.TextContent("G"), EditorGUIUtility.TextContent("B"), EditorGUIUtility.TextContent("A")};
|
||||
|
||||
|
||||
private static GUIStyle _style_PopupCurveEditorBackground;
|
||||
public static GUIStyle style_PopupCurveEditorBackground => _style_PopupCurveEditorBackground ??= "PopupCurveEditorBackground";
|
||||
|
||||
#endregion
|
||||
|
||||
#region Math
|
||||
|
||||
private const float TOLERANCE = 0.00001f;
|
||||
|
||||
private static bool Equal(float a, float b) => Math.Abs(a - b) < TOLERANCE;
|
||||
|
||||
private static bool Equal(GradientEditor.Swatch a, GradientEditor.Swatch b) =>
|
||||
a == b
|
||||
|| (a != null && b != null && a.m_Time == b.m_Time && a.m_Value == b.m_Value && a.m_IsAlpha == b.m_IsAlpha);
|
||||
|
||||
#endregion
|
||||
|
||||
#region Fields
|
||||
|
||||
#region Inputs
|
||||
|
||||
private Rect _position;
|
||||
internal LwguiGradient lwguiGradient;
|
||||
internal ColorSpace colorSpace;
|
||||
internal LwguiGradient.ChannelMask viewChannelMask;
|
||||
internal LwguiGradient.GradientTimeRange gradientTimeRange;
|
||||
private Action<LwguiGradient> _onChange;
|
||||
|
||||
#endregion
|
||||
|
||||
private GradientEditor _gradientEditor;
|
||||
private CurveEditor _curveEditor;
|
||||
private bool _viewSettingschanged;
|
||||
private bool _curveEditorContextMenuChanged;
|
||||
private bool _changed;
|
||||
private bool _lastChanged;
|
||||
|
||||
#region Gradient Editor
|
||||
|
||||
private static readonly string[] timeRangeMenuNames = new string[] { "0-1", "0-24", "0-2400" };
|
||||
private static readonly List<LwguiGradient.GradientTimeRange> timeRangeMenuValues = new () { LwguiGradient.GradientTimeRange.One, LwguiGradient.GradientTimeRange.TwentyFour, LwguiGradient.GradientTimeRange.TwentyFourHundred };
|
||||
|
||||
private GradientEditor.Swatch _selectedGradientKey
|
||||
{
|
||||
get => _gradientEditor.GetSelectedSwatch();
|
||||
set => _gradientEditor.SetSelectedSwatch(value);
|
||||
}
|
||||
|
||||
private GradientEditor.Swatch _lastSelectedGradientKey;
|
||||
private GradientEditor.Swatch _deletedGradientKey;
|
||||
|
||||
private List<GradientEditor.Swatch> _gradientRGBSwatches => _gradientEditor.GetRGBdSwatches();
|
||||
private List<GradientEditor.Swatch> _gradientAlphaSwatches => _gradientEditor.GetAlphaSwatches();
|
||||
private int _lastGradientRGBSwatchesCount;
|
||||
private int _lastGradientAlphaSwatchesCount;
|
||||
|
||||
private float _lastEditingTime = float.NegativeInfinity;
|
||||
|
||||
private static bool _isAddGradientKeyFailure;
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
#region Curve Editor
|
||||
|
||||
private List<CurveSelection> _selectedCurves
|
||||
{
|
||||
get => _curveEditor.selectedCurves;
|
||||
set => _curveEditor.selectedCurves = value;
|
||||
}
|
||||
|
||||
private List<Keyframe> _deletedCurveKeys;
|
||||
|
||||
private bool _shouldSyncSelectionFromCurveToGradient;
|
||||
|
||||
#endregion
|
||||
|
||||
#endregion
|
||||
|
||||
#region Gradient Editor
|
||||
|
||||
private void InitGradientEditor(bool force = false)
|
||||
{
|
||||
if (_gradientEditor != null && !force) return;
|
||||
|
||||
var lastSelectedGradientKey = _gradientEditor != null && _selectedGradientKey != null ? new GradientEditor.Swatch(_selectedGradientKey.m_Time, _selectedGradientKey.m_Value, _selectedGradientKey.m_IsAlpha) : null;
|
||||
|
||||
var lwguiMergedCurves = new LwguiGradient.LwguiMergedColorCurves(lwguiGradient.rawCurves);
|
||||
_gradientEditor ??= new GradientEditor();
|
||||
_gradientEditor.Init(lwguiMergedCurves.ToGradient(ReflectionHelper.maxGradientKeyCount), 1024, colorSpace == ColorSpace.Linear, colorSpace);
|
||||
|
||||
// When Curve has only one key, Gradient Editor will automatically add a key
|
||||
{
|
||||
void FixAutoAddedGradientKey(List<GradientEditor.Swatch> swatches, LwguiGradient.Channel channel)
|
||||
{
|
||||
if (swatches.Count == 2 && lwguiMergedCurves.curves[(int)channel].Count == 1)
|
||||
{
|
||||
swatches.Clear();
|
||||
var curveKey = lwguiMergedCurves.curves[(int)channel][0];
|
||||
swatches.Add(channel == LwguiGradient.Channel.Alpha
|
||||
? new GradientEditor.Swatch(curveKey.time, new Color(curveKey.value, curveKey.value, curveKey.value, curveKey.value), true)
|
||||
: new GradientEditor.Swatch(curveKey.time, new Color(
|
||||
lwguiMergedCurves.curves[(int)LwguiGradient.Channel.Red][0].value,
|
||||
lwguiMergedCurves.curves[(int)LwguiGradient.Channel.Green][0].value,
|
||||
lwguiMergedCurves.curves[(int)LwguiGradient.Channel.Blue][0].value,
|
||||
1), false));
|
||||
}
|
||||
}
|
||||
|
||||
FixAutoAddedGradientKey(_gradientRGBSwatches, LwguiGradient.Channel.Red);
|
||||
FixAutoAddedGradientKey(_gradientAlphaSwatches, LwguiGradient.Channel.Alpha);
|
||||
}
|
||||
|
||||
// Keep selected key
|
||||
if (lastSelectedGradientKey != null)
|
||||
{
|
||||
_selectedGradientKey = (lastSelectedGradientKey.m_IsAlpha ? _gradientAlphaSwatches : _gradientRGBSwatches)
|
||||
.Find(swatch => Equal(swatch.m_Time, lastSelectedGradientKey.m_Time));
|
||||
}
|
||||
else
|
||||
{
|
||||
_selectedGradientKey = null;
|
||||
}
|
||||
}
|
||||
|
||||
private void OnGradientEditorGUI()
|
||||
{
|
||||
OnGradientEditFieldGUI();
|
||||
|
||||
EditorGUI.DrawPreviewTexture(_alphaGradientRect, lwguiGradient.GetPreviewRampTexture(1024, 1, colorSpace, LwguiGradient.ChannelMask.Alpha & viewChannelMask));
|
||||
EditorGUI.DrawPreviewTexture(_rgbGradientRect, lwguiGradient.GetPreviewRampTexture(1024, 1, colorSpace, LwguiGradient.ChannelMask.RGB & viewChannelMask));
|
||||
|
||||
// Swatch Array
|
||||
{
|
||||
PrepareSyncSelectionFromGradientToCurve();
|
||||
EditorGUI.BeginChangeCheck();
|
||||
ShowGradientSwatchArray(_alphaSwatchesRect, _gradientAlphaSwatches, LwguiGradient.ChannelMask.Alpha);
|
||||
ShowGradientSwatchArray(_rgbSwatchesRect, _gradientRGBSwatches, LwguiGradient.ChannelMask.RGB);
|
||||
if (EditorGUI.EndChangeCheck())
|
||||
{
|
||||
_changed = true;
|
||||
ApplyGradientChangesToCurve();
|
||||
}
|
||||
|
||||
SyncSelectionFromGradientToCurveWithoutChanges();
|
||||
}
|
||||
}
|
||||
|
||||
private void OnGradientEditFieldGUI()
|
||||
{
|
||||
// Prevent interrupting mouse drag event
|
||||
if (Event.current.type is EventType.MouseDrag or EventType.MouseDown or EventType.MouseMove or EventType.MouseUp
|
||||
&& (!_editFieldRect.Contains(Event.current.mousePosition)
|
||||
&& !_secondEditFieldRect.Contains(Event.current.mousePosition)))
|
||||
return;
|
||||
|
||||
float space = 20;
|
||||
float vectorValueWidth = 270;
|
||||
float locationWidth = 70;
|
||||
float locationTextWidth = 35;
|
||||
float alphaOrColorTextWidth = 40;
|
||||
float colorSpaceTextWidth = 87;
|
||||
float colorSpaceToggleWidth = 16;
|
||||
float channelsTextWidth = 60;
|
||||
float channelsMenuWidth = 85;
|
||||
float timeRangeTextWidth = 75;
|
||||
float timeRangeMenuWidth = 70;
|
||||
|
||||
Rect rect = _editFieldRect;
|
||||
|
||||
// Color Space
|
||||
{
|
||||
rect.x = rect.xMax - colorSpaceToggleWidth - colorSpaceTextWidth;
|
||||
rect.width = colorSpaceTextWidth + colorSpaceToggleWidth;
|
||||
var labelWidth = EditorGUIUtility.labelWidth;
|
||||
EditorGUIUtility.labelWidth = colorSpaceTextWidth;
|
||||
EditorGUI.BeginChangeCheck();
|
||||
colorSpace = EditorGUI.Toggle(rect, "sRGB Preview", colorSpace == ColorSpace.Gamma) ? ColorSpace.Gamma : ColorSpace.Linear;
|
||||
if (EditorGUI.EndChangeCheck())
|
||||
{
|
||||
_viewSettingschanged = true;
|
||||
InitGradientEditor(true);
|
||||
}
|
||||
EditorGUIUtility.labelWidth = labelWidth;
|
||||
}
|
||||
|
||||
// View Channel Mask
|
||||
{
|
||||
rect.x -= space + channelsMenuWidth + channelsTextWidth;
|
||||
rect.width = channelsMenuWidth + channelsTextWidth;
|
||||
var labelWidth = EditorGUIUtility.labelWidth;
|
||||
EditorGUIUtility.labelWidth = channelsTextWidth;
|
||||
EditorGUI.BeginChangeCheck();
|
||||
viewChannelMask = (LwguiGradient.ChannelMask)EditorGUI.EnumFlagsField(rect, "Channels", viewChannelMask);
|
||||
if (EditorGUI.EndChangeCheck())
|
||||
{
|
||||
_viewSettingschanged = true;
|
||||
InitGradientEditor(true);
|
||||
InitCurveEditor(true);
|
||||
}
|
||||
EditorGUIUtility.labelWidth = labelWidth;
|
||||
}
|
||||
|
||||
// Gradient Time Range
|
||||
{
|
||||
rect.x -= space + timeRangeMenuWidth + timeRangeTextWidth;
|
||||
rect.width = timeRangeMenuWidth + timeRangeTextWidth;
|
||||
var labelWidth = EditorGUIUtility.labelWidth;
|
||||
EditorGUIUtility.labelWidth = timeRangeTextWidth;
|
||||
EditorGUI.BeginChangeCheck();
|
||||
|
||||
gradientTimeRange = timeRangeMenuValues[EditorGUI.Popup(rect, "Time Range", timeRangeMenuValues.IndexOf(gradientTimeRange), timeRangeMenuNames)];
|
||||
if (EditorGUI.EndChangeCheck())
|
||||
{
|
||||
_viewSettingschanged = true;
|
||||
InitGradientEditor(true);
|
||||
InitCurveEditor(true);
|
||||
}
|
||||
EditorGUIUtility.labelWidth = labelWidth;
|
||||
}
|
||||
|
||||
// Key edit field (GradientEditor.OnGUI())
|
||||
if (_selectedCurves is { Count: > 0 })
|
||||
{
|
||||
var labelWidth = EditorGUIUtility.labelWidth;
|
||||
var showMixedValue = EditorGUI.showMixedValue;
|
||||
var selectionInfo = new CurveSelectionInfo(_curveEditor);
|
||||
|
||||
// Time
|
||||
{
|
||||
if (_useSignalLineEditField)
|
||||
{
|
||||
rect.x -= space + locationTextWidth + locationWidth;
|
||||
}
|
||||
else
|
||||
{
|
||||
rect = _secondEditFieldRect;
|
||||
rect.x = rect.xMax - (locationTextWidth + locationWidth);
|
||||
}
|
||||
rect.width = locationTextWidth + locationWidth;
|
||||
EditorGUIUtility.labelWidth = locationTextWidth;
|
||||
EditorGUI.showMixedValue = selectionInfo.hasMixedTime;
|
||||
EditorGUI.BeginChangeCheck();
|
||||
var newTime = EditorGUI.FloatField(rect, "Time", selectionInfo.selectedTime * (int)gradientTimeRange) / (int)gradientTimeRange;
|
||||
// When two keys have the same time, they will be merged, so avoid modifying the time in real time and only apply the changes at the end of the change
|
||||
var hasChange = EditorGUI.EndChangeCheck();
|
||||
if (hasChange) _lastEditingTime = newTime;
|
||||
if (_lastEditingTime != selectionInfo.selectedTime
|
||||
&& _lastEditingTime != float.NegativeInfinity
|
||||
// End editing text
|
||||
&& (EditorGUI.IsEditingTextField() && Event.current.keyCode is KeyCode.Return or KeyCode.KeypadEnter
|
||||
// Mouse drag
|
||||
|| !EditorGUI.IsEditingTextField() && hasChange))
|
||||
{
|
||||
_changed = true;
|
||||
_curveEditor.SetSelectedKeyPositions(Mathf.Clamp01(_lastEditingTime), 0, true, false);
|
||||
InitGradientEditor(true);
|
||||
SyncSelectionFromCurveToGradient(true);
|
||||
}
|
||||
}
|
||||
|
||||
// Vector Value
|
||||
{
|
||||
rect.x -= space + vectorValueWidth;
|
||||
rect.width = vectorValueWidth;
|
||||
// EditorGUI.VectorField()
|
||||
{
|
||||
int channelCount = (int)LwguiGradient.Channel.Num;
|
||||
float w = (rect.width - (channelCount - 1) * EditorGUI.kSpacingSubLabel) / channelCount;
|
||||
Rect nr = new Rect(rect) {width = w};
|
||||
int l = EditorGUI.indentLevel;
|
||||
EditorGUI.indentLevel = 0;
|
||||
for (int c = 0; c < channelCount; c++)
|
||||
{
|
||||
EditorGUIUtility.labelWidth = EditorGUI.GetLabelWidth(s_XYZWLabels[c], 0);
|
||||
EditorGUI.showMixedValue = selectionInfo.hasMixedChannelValue[c];
|
||||
EditorGUI.BeginChangeCheck();
|
||||
var newValue = EditorGUI.FloatField(nr, s_XYZWLabels[c], selectionInfo.selectedVectorValue[c]);
|
||||
if (EditorGUI.EndChangeCheck())
|
||||
{
|
||||
_changed = true;
|
||||
// Apply a curve's modification
|
||||
foreach (var selection in _selectedCurves.Where(selection => selection.curveID == c))
|
||||
{
|
||||
var cw = _curveEditor.animationCurves[selection.curveID];
|
||||
var key = cw.curve.keys[selection.key];
|
||||
key.value = newValue;
|
||||
cw.MoveKey(selection.key, ref key);
|
||||
cw.changed = true;
|
||||
AnimationUtility.UpdateTangentsFromMode(cw.curve);
|
||||
}
|
||||
_curveEditor.InvalidateSelectionBounds();
|
||||
InitGradientEditor(true);
|
||||
SyncSelectionFromCurveToGradient(true);
|
||||
}
|
||||
nr.x += w + EditorGUI.kSpacingSubLabel;
|
||||
}
|
||||
EditorGUI.indentLevel = l;
|
||||
}
|
||||
}
|
||||
|
||||
// Alpha or Color field
|
||||
{
|
||||
rect = new Rect(_editFieldRect.x, rect.y, rect.x - _editFieldRect.x - space, rect.height);
|
||||
EditorGUIUtility.labelWidth = alphaOrColorTextWidth;
|
||||
EditorGUI.BeginChangeCheck();
|
||||
if (selectionInfo.isOnlyColorKeySelected)
|
||||
{
|
||||
EditorGUI.showMixedValue = selectionInfo.hasMixedColorValue;
|
||||
var newColorValue = new Vector4(selectionInfo.selectedVectorValue.x, selectionInfo.selectedVectorValue.y, selectionInfo.selectedVectorValue.z, 1);
|
||||
newColorValue = EditorGUI.ColorField(rect, new GUIContent("Value"), newColorValue, true, false, colorSpace == ColorSpace.Linear);
|
||||
newColorValue.w = selectionInfo.selectedVectorValue.w;
|
||||
if (EditorGUI.EndChangeCheck())
|
||||
{
|
||||
_changed = true;
|
||||
// Use EventCommandNames.ColorPickerChanged event to avoid ShowSwatchArray() Errors
|
||||
Event.current.Use();
|
||||
// Apply RGB curve's modification
|
||||
foreach (var selection in _selectedCurves.Where(selection => selection.curveID < (int)LwguiGradient.Channel.Alpha))
|
||||
{
|
||||
var channelID = selection.curveID;
|
||||
var cw = _curveEditor.animationCurves[channelID];
|
||||
var key = cw.curve.keys[selection.key];
|
||||
key.value = newColorValue[channelID];
|
||||
cw.MoveKey(selection.key, ref key);
|
||||
cw.changed = true;
|
||||
AnimationUtility.UpdateTangentsFromMode(cw.curve);
|
||||
}
|
||||
_curveEditor.InvalidateSelectionBounds();
|
||||
InitGradientEditor(true);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
EditorGUI.showMixedValue = selectionInfo.hasMixedFloatValue;
|
||||
var newValue = EditorGUI.IntSlider(rect, "Value", (int)(selectionInfo.selectedFloatValue * 255), 0, 255) / 255f;
|
||||
if (EditorGUI.EndChangeCheck())
|
||||
{
|
||||
_changed = true;
|
||||
_curveEditor.SetSelectedKeyPositions(0, newValue, false, true);
|
||||
InitGradientEditor(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
EditorGUIUtility.labelWidth = labelWidth;
|
||||
EditorGUI.showMixedValue = showMixedValue;
|
||||
}
|
||||
}
|
||||
|
||||
private void ShowGradientSwatchArray(Rect rect, List<GradientEditor.Swatch> swatches, LwguiGradient.ChannelMask drawingChannelMask)
|
||||
{
|
||||
// GradientEditor.ShowSwatchArray()
|
||||
ReflectionHelper.GradientEditor_SetStyles();
|
||||
|
||||
_isAddGradientKeyFailure = false;
|
||||
_gradientEditor.ShowSwatchArray(rect, (viewChannelMask & drawingChannelMask) != drawingChannelMask ? new List<GradientEditor.Swatch>() : swatches, drawingChannelMask == LwguiGradient.ChannelMask.Alpha);
|
||||
|
||||
// Since the maximum number of Gradient Keys is hard-coded in the engine, keys that exceed the limit can only be displayed and edited in the Curve Editor
|
||||
if (_isAddGradientKeyFailure)
|
||||
{
|
||||
_changed = true;
|
||||
_curveEditor.SelectNone();
|
||||
float mouseSwatchTime = _gradientEditor.GetTime((Event.current.mousePosition.x - rect.x) / rect.width);
|
||||
for (int c = 0; c < (int)LwguiGradient.Channel.Num; c++)
|
||||
{
|
||||
if (!LwguiGradient.IsChannelIndexInMask(c, drawingChannelMask))
|
||||
continue;
|
||||
|
||||
var curveSelection = _curveEditor.AddKeyAtTime(_curveEditor.animationCurves[c], mouseSwatchTime);
|
||||
_curveEditor.AddSelection(curveSelection);
|
||||
}
|
||||
_curveEditor.InvalidateSelectionBounds();
|
||||
_selectedGradientKey = null;
|
||||
}
|
||||
}
|
||||
|
||||
private void ApplyGradientChangesToCurve()
|
||||
{
|
||||
var selectedKeyEqual = _selectedGradientKey == _lastSelectedGradientKey || Equal(_selectedGradientKey, _lastSelectedGradientKey);
|
||||
var rgbKeyCountEqual = _gradientRGBSwatches.Count == _lastGradientRGBSwatchesCount;
|
||||
var alphaKeyCountEqual = _gradientAlphaSwatches.Count == _lastGradientAlphaSwatchesCount;
|
||||
var addRGBKey = _gradientRGBSwatches.Count > _lastGradientRGBSwatchesCount;
|
||||
var addAlphaKey = _gradientAlphaSwatches.Count > _lastGradientAlphaSwatchesCount;
|
||||
var delRGBKey = _gradientRGBSwatches.Count < _lastGradientRGBSwatchesCount;
|
||||
var delAlphaKey = _gradientAlphaSwatches.Count < _lastGradientAlphaSwatchesCount;
|
||||
|
||||
if (selectedKeyEqual && rgbKeyCountEqual && alphaKeyCountEqual)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Change time or value
|
||||
if ((!selectedKeyEqual && rgbKeyCountEqual && alphaKeyCountEqual)
|
||||
// Del a key
|
||||
|| (delRGBKey || delAlphaKey))
|
||||
{
|
||||
foreach (var curveSelection in _selectedCurves.Where(selection => LwguiGradient.IsChannelIndexInMask(selection.curveID, viewChannelMask)))
|
||||
{
|
||||
var cw = _curveEditor.animationCurves[curveSelection.curveID];
|
||||
var selectedKey = cw.curve.keys[curveSelection.key];
|
||||
if (rgbKeyCountEqual && alphaKeyCountEqual)
|
||||
{
|
||||
var newKey = selectedKey;
|
||||
|
||||
// Change a key time
|
||||
if (_selectedGradientKey.m_Time != _lastSelectedGradientKey.m_Time)
|
||||
{
|
||||
newKey.time = _selectedGradientKey.m_Time;
|
||||
}
|
||||
// Change a key value
|
||||
else if (_selectedGradientKey.m_Value != _lastSelectedGradientKey.m_Value)
|
||||
{
|
||||
newKey.value = _selectedGradientKey.m_IsAlpha ? _selectedGradientKey.m_Value.r : _selectedGradientKey.m_Value[curveSelection.curveID];
|
||||
}
|
||||
newKey = CheckNewKeyTime(cw, newKey, selectedKey.time);
|
||||
curveSelection.key = cw.MoveKey(curveSelection.key, ref newKey);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Mouse drag out of the swatch rect, save the key
|
||||
if (_selectedGradientKey != null)
|
||||
{
|
||||
_deletedGradientKey = new GradientEditor.Swatch(_selectedGradientKey.m_Time, _selectedGradientKey.m_Value, _selectedGradientKey.m_IsAlpha);
|
||||
_deletedCurveKeys ??= new List<Keyframe>(new Keyframe[(int)LwguiGradient.Channel.Num]);
|
||||
_deletedCurveKeys[curveSelection.curveID] = selectedKey;
|
||||
}
|
||||
|
||||
// Del a key
|
||||
cw.curve.RemoveKey(curveSelection.key);
|
||||
}
|
||||
AnimationUtility.UpdateTangentsFromMode(cw.curve);
|
||||
cw.changed = true;
|
||||
}
|
||||
|
||||
if (delRGBKey || delAlphaKey)
|
||||
_curveEditor.SelectNone();
|
||||
}
|
||||
else
|
||||
{
|
||||
var curveSelections = new List<CurveSelection>();
|
||||
|
||||
for (int c = 0; c < (int)LwguiGradient.Channel.Num; c++)
|
||||
{
|
||||
if (!LwguiGradient.IsChannelIndexInMask(c, viewChannelMask))
|
||||
continue;
|
||||
|
||||
// Add a RGB Key
|
||||
if ((c < (int)LwguiGradient.Channel.Alpha && addRGBKey)
|
||||
// Add an Alpha Key
|
||||
|| (c == (int)LwguiGradient.Channel.Alpha && addAlphaKey))
|
||||
{
|
||||
var cw = _curveEditor.animationCurves[c];
|
||||
|
||||
// Mouse drag back to the swatch rect, restore the key
|
||||
if (_deletedGradientKey != null && _deletedCurveKeys != null
|
||||
&& _selectedGradientKey?.m_Value == _deletedGradientKey?.m_Value
|
||||
&& _selectedGradientKey?.m_IsAlpha == _deletedGradientKey?.m_IsAlpha)
|
||||
{
|
||||
var deletedKey = _deletedCurveKeys[c];
|
||||
var newKey = deletedKey;
|
||||
newKey.time = _selectedGradientKey.m_Time;
|
||||
newKey = CheckNewKeyTime(cw, newKey, deletedKey.time);
|
||||
var addedKeyIndex = cw.AddKey(newKey);
|
||||
curveSelections.Add(new CurveSelection(c, addedKeyIndex, CurveSelection.SelectionType.Key));
|
||||
}
|
||||
// Add a new key
|
||||
else
|
||||
{
|
||||
var curveSelection = _curveEditor.AddKeyAtTime(cw, _selectedGradientKey.m_Time);
|
||||
curveSelections.Add(curveSelection);
|
||||
}
|
||||
|
||||
cw.selected = CurveWrapper.SelectionMode.Selected;
|
||||
cw.changed = true;
|
||||
}
|
||||
}
|
||||
|
||||
_deletedGradientKey = null;
|
||||
_deletedCurveKeys = null;
|
||||
_curveEditor.SelectNone();
|
||||
curveSelections.ForEach(selection => _curveEditor.AddSelection(selection));
|
||||
InitGradientEditor(true);
|
||||
}
|
||||
|
||||
_curveEditor.InvalidateSelectionBounds();
|
||||
InitCurveEditor(true);
|
||||
|
||||
// Cannot overlap with the Time of an existing Key when adding or moving Keys
|
||||
Keyframe CheckNewKeyTime(CurveWrapper cw, Keyframe newKey, float oldKeyTime = 0)
|
||||
{
|
||||
try
|
||||
{
|
||||
var sameTimeKey = cw.curve.keys.First(keyframe => keyframe.time == newKey.time);
|
||||
if (newKey.time > oldKeyTime)
|
||||
newKey.time += 0.00001f;
|
||||
else
|
||||
newKey.time -= 0.00001f;
|
||||
}
|
||||
catch (InvalidOperationException) { }
|
||||
|
||||
return newKey;
|
||||
}
|
||||
}
|
||||
|
||||
private void PrepareSyncSelectionFromGradientToCurve()
|
||||
{
|
||||
_lastSelectedGradientKey = _selectedGradientKey != null ? new GradientEditor.Swatch(_selectedGradientKey.m_Time, _selectedGradientKey.m_Value, _selectedGradientKey.m_IsAlpha) : null;
|
||||
_lastGradientRGBSwatchesCount = _gradientRGBSwatches.Count;
|
||||
_lastGradientAlphaSwatchesCount = _gradientAlphaSwatches.Count;
|
||||
}
|
||||
|
||||
private void SyncSelectionFromGradientToCurveWithoutChanges()
|
||||
{
|
||||
// Only detect when switching selected Key without modifying it
|
||||
if (!_gradientEditorRect.Contains(Event.current.mousePosition)
|
||||
// || Event.current.type != EventType.MouseDown
|
||||
|| _changed
|
||||
|| _lastChanged
|
||||
|| Equal(_lastSelectedGradientKey, _selectedGradientKey))
|
||||
return;
|
||||
|
||||
if (_selectedGradientKey == null)
|
||||
{
|
||||
_curveEditor.SelectNone();
|
||||
return;
|
||||
}
|
||||
|
||||
// Get selected gradient key index
|
||||
var selectedGradientKeyIndexes = Enumerable.Repeat(-1, (int)LwguiGradient.Channel.Num).ToArray();
|
||||
|
||||
if (_selectedGradientKey.m_IsAlpha)
|
||||
{
|
||||
selectedGradientKeyIndexes[(int)LwguiGradient.Channel.Alpha] = _gradientAlphaSwatches.FindIndex(swatch => swatch == _selectedGradientKey);
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int c = 0; c < (int)LwguiGradient.Channel.Num - 1; c++)
|
||||
{
|
||||
selectedGradientKeyIndexes[c] = _gradientRGBSwatches.FindIndex(swatch => swatch == _selectedGradientKey);
|
||||
}
|
||||
}
|
||||
|
||||
// Get curve key index
|
||||
_curveEditor.SelectNone();
|
||||
var lwguiMergedCurves = new LwguiGradient.LwguiMergedColorCurves(lwguiGradient.rawCurves);
|
||||
for (int c = 0; c < (int)LwguiGradient.Channel.Num; c++)
|
||||
{
|
||||
if (selectedGradientKeyIndexes[c] < 0)
|
||||
continue;
|
||||
|
||||
var curveKeyIndex = lwguiMergedCurves.curves[c][selectedGradientKeyIndexes[c]].index;
|
||||
_selectedCurves.Add(new CurveSelection(c, curveKeyIndex));
|
||||
}
|
||||
_curveEditor.InvalidateSelectionBounds();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Curve Editor
|
||||
|
||||
private void InitCurveEditor(bool force = false)
|
||||
{
|
||||
if (_curveEditor != null && !force)
|
||||
return;
|
||||
|
||||
var firstOpenWindow = _curveEditor == null;
|
||||
_curveEditor = CurveEditorWindow.instance.GetCurveEditor();
|
||||
|
||||
var cws = new CurveWrapper[(int)LwguiGradient.Channel.Num];
|
||||
for (int c = 0; c < (int)LwguiGradient.Channel.Num; c++)
|
||||
{
|
||||
var curve = lwguiGradient.rawCurves[c];
|
||||
var cw = new CurveWrapper();
|
||||
cw.id = c;
|
||||
if (LwguiGradient.IsChannelIndexInMask(c, viewChannelMask))
|
||||
{
|
||||
cw.color = LwguiGradient.channelColors[c];
|
||||
cw.renderer = new NormalCurveRenderer(curve);
|
||||
cw.renderer.SetWrap(curve.preWrapMode, curve.postWrapMode);
|
||||
}
|
||||
else
|
||||
{
|
||||
cw.renderer = new NormalCurveRenderer(new AnimationCurve());
|
||||
}
|
||||
cws[c] = cw;
|
||||
}
|
||||
|
||||
_curveEditor.animationCurves = cws;
|
||||
_curveEditor.curvesUpdated = () =>
|
||||
{
|
||||
_curveEditorContextMenuChanged = true;
|
||||
};
|
||||
|
||||
SyncCurveEditorRect();
|
||||
|
||||
if (firstOpenWindow)
|
||||
{
|
||||
_curveEditor.Frame(new Bounds(new Vector2(0.5f, 0.5f), Vector2.one), true, true);
|
||||
_curveEditor.SelectNone();
|
||||
}
|
||||
}
|
||||
|
||||
private void OnCurveEditorGUI()
|
||||
{
|
||||
GUI.Label(_curveEditorRect, GUIContent.none, style_PopupCurveEditorBackground);
|
||||
EditorGUI.DrawRect(new Rect(_curveEditorRect.x, _curveEditorRect.y, _curveEditorRect.width, 1), new Color(0.5f, 0.5f, 0.5f, 0.5f));
|
||||
|
||||
PrepareSyncSelectionFromCurveToGradient();
|
||||
EditorGUI.BeginChangeCheck();
|
||||
_curveEditor.OnGUI();
|
||||
bool curveEditorChanged = EditorGUI.EndChangeCheck() || _curveEditorContextMenuChanged;
|
||||
_changed |= curveEditorChanged;
|
||||
if (curveEditorChanged)
|
||||
{
|
||||
InitGradientEditor(true);
|
||||
foreach (var cw in _curveEditor.animationCurves)
|
||||
{
|
||||
cw.changed = false;
|
||||
}
|
||||
_curveEditorContextMenuChanged = false;
|
||||
}
|
||||
SyncSelectionFromCurveToGradient();
|
||||
}
|
||||
|
||||
private void SyncCurveEditorRect()
|
||||
{
|
||||
_curveEditor.rect = _curveEditorRect;
|
||||
}
|
||||
|
||||
private void PrepareSyncSelectionFromCurveToGradient()
|
||||
{
|
||||
// var eventType = Event.current.GetTypeForControl(GUIUtility.GetControlID(897560, FocusType.Passive)); // CurveEditor.SelectPoints()
|
||||
var eventType = Event.current.type;
|
||||
|
||||
if (_curveEditorRect.Contains(Event.current.mousePosition)
|
||||
&& eventType is EventType.MouseDown or EventType.MouseDrag)
|
||||
_shouldSyncSelectionFromCurveToGradient = true;
|
||||
}
|
||||
|
||||
private void SyncSelectionFromCurveToGradient(bool force = false)
|
||||
{
|
||||
if (!_shouldSyncSelectionFromCurveToGradient && !force)
|
||||
return;
|
||||
|
||||
_shouldSyncSelectionFromCurveToGradient = false;
|
||||
_selectedGradientKey = null;
|
||||
|
||||
var selectedGradientKeys = new List<GradientEditor.Swatch>();
|
||||
var mergedCurves = new CurveSelectionInfo(_curveEditor).mergedCurves;
|
||||
|
||||
FindSelectedGradientKey((int)LwguiGradient.Channel.Red, _gradientRGBSwatches);
|
||||
FindSelectedGradientKey((int)LwguiGradient.Channel.Alpha, _gradientAlphaSwatches);
|
||||
|
||||
// Sync selection to Gradient Editor only when single selection
|
||||
if (selectedGradientKeys.Count == 1)
|
||||
_selectedGradientKey = selectedGradientKeys[0];
|
||||
return;
|
||||
|
||||
void FindSelectedGradientKey(int channel, List<GradientEditor.Swatch> list)
|
||||
{
|
||||
foreach (var lwguiKeyframe in mergedCurves.curves[channel])
|
||||
{
|
||||
if (selectedGradientKeys.Count > 1) return;
|
||||
|
||||
var key = list.Find(swatch => Equal(swatch.m_Time, lwguiKeyframe.time));
|
||||
if (key != null)
|
||||
selectedGradientKeys.Add(key);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Events
|
||||
|
||||
public void Init(Rect position, LwguiGradient gradient, ColorSpace colorSpace = ColorSpace.Gamma, LwguiGradient.ChannelMask viewChannelMask = LwguiGradient.ChannelMask.All, LwguiGradient.GradientTimeRange timeRange = LwguiGradient.GradientTimeRange.One, Action<LwguiGradient> onChange = null)
|
||||
{
|
||||
Clear();
|
||||
|
||||
this._position = position;
|
||||
this.lwguiGradient = gradient;
|
||||
this.colorSpace = colorSpace;
|
||||
this.viewChannelMask = viewChannelMask;
|
||||
this.gradientTimeRange = timeRange;
|
||||
this._onChange = onChange;
|
||||
}
|
||||
|
||||
public void OnGUI(Rect position)
|
||||
{
|
||||
if (lwguiGradient == null)
|
||||
return;
|
||||
|
||||
// Debug.Log(JsonUtility.ToJson(lwguiGradient));
|
||||
|
||||
this._position = position;
|
||||
|
||||
InitGradientEditor();
|
||||
InitCurveEditor();
|
||||
|
||||
// Gradient Editor
|
||||
OnGradientEditorGUI();
|
||||
|
||||
// Curve Editor
|
||||
SyncCurveEditorRect();
|
||||
OnCurveEditorGUI();
|
||||
|
||||
_lastChanged = _changed;
|
||||
_changed = false;
|
||||
|
||||
if (_lastChanged)
|
||||
{
|
||||
if (!EditorApplication.isPlaying)
|
||||
UnityEditor.SceneManagement.EditorSceneManager.MarkAllScenesDirty();
|
||||
|
||||
GUI.changed = true;
|
||||
_onChange?.Invoke(lwguiGradient);
|
||||
}
|
||||
|
||||
if (_viewSettingschanged)
|
||||
{
|
||||
_viewSettingschanged = false;
|
||||
GUI.changed = true;
|
||||
}
|
||||
}
|
||||
|
||||
public void Clear()
|
||||
{
|
||||
lwguiGradient = null;
|
||||
_gradientEditor = null;
|
||||
_curveEditor?.OnDisable();
|
||||
_curveEditor = null;
|
||||
_lastChanged = false;
|
||||
_lastEditingTime = float.NegativeInfinity;
|
||||
}
|
||||
|
||||
public static void CheckAddGradientKeyFailureLog(string logString, string stackTrace, LogType type)
|
||||
{
|
||||
if (type == LogType.Warning
|
||||
&& logString == "Max " + ReflectionHelper.maxGradientKeyCount + " color keys and " + ReflectionHelper.maxGradientKeyCount + " alpha keys are allowed in a gradient.")
|
||||
{
|
||||
_isAddGradientKeyFailure = true;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 0a472009f0e9429c8d503438262f3d34
|
||||
timeCreated: 1720769127
|
||||
@ -0,0 +1,195 @@
|
||||
// Copyright (c) Jason Ma
|
||||
|
||||
using System;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
using LWGUI.Runtime.LwguiGradient;
|
||||
|
||||
namespace LWGUI.LwguiGradientEditor
|
||||
{
|
||||
public static class LwguiGradientEditorHelper
|
||||
{
|
||||
private static readonly int s_LwguiGradientHash = "s_LwguiGradientHash".GetHashCode();
|
||||
private static int s_LwguiGradientID;
|
||||
|
||||
// GradientEditor.DrawGradientWithBackground()
|
||||
public static void DrawGradientWithBackground(Rect position, LwguiGradient gradient, ColorSpace colorSpace, LwguiGradient.ChannelMask viewChannelMask)
|
||||
{
|
||||
Texture2D gradientTexture = gradient.GetPreviewRampTexture(256, 1, colorSpace, viewChannelMask);
|
||||
Rect r2 = new Rect(position.x + 1, position.y + 1, position.width - 2, position.height - 2);
|
||||
|
||||
// Background checkers
|
||||
Texture2D backgroundTexture = GradientEditor.GetBackgroundTexture();
|
||||
Rect texCoordsRect = new Rect(0, 0, r2.width / backgroundTexture.width, r2.height / backgroundTexture.height);
|
||||
GUI.DrawTextureWithTexCoords(r2, backgroundTexture, texCoordsRect, false);
|
||||
|
||||
// Outline for Gradinet Texture, used to be Frame over texture.
|
||||
// LWGUI: GUI.Box() will cause subsequent attributes to be unable to be selected
|
||||
// GUI.Box(position, GUIContent.none);
|
||||
|
||||
// Gradient texture
|
||||
Color oldColor = GUI.color;
|
||||
GUI.color = Color.white; //Dont want the Playmode tint to be applied to gradient textures.
|
||||
if (gradientTexture != null)
|
||||
GUI.DrawTexture(r2, gradientTexture, ScaleMode.StretchToFill, true);
|
||||
GUI.color = oldColor;
|
||||
|
||||
// HDR label
|
||||
// float maxColorComponent = GetMaxColorComponent(gradient);
|
||||
// if (maxColorComponent > 1.0f)
|
||||
// {
|
||||
// GUI.Label(new Rect(position.x, position.y, position.width - 3, position.height), "HDR", EditorStyles.centeredGreyMiniLabel);
|
||||
// }
|
||||
}
|
||||
|
||||
public static void DrawGradientWithSeparateAlphaChannel(Rect position, LwguiGradient gradient, ColorSpace colorSpace, LwguiGradient.ChannelMask viewChannelMask)
|
||||
{
|
||||
if (!LwguiGradient.HasChannelMask(viewChannelMask, LwguiGradient.ChannelMask.Alpha) || viewChannelMask == LwguiGradient.ChannelMask.Alpha)
|
||||
{
|
||||
DrawGradientWithBackground(position, gradient, colorSpace, viewChannelMask);
|
||||
}
|
||||
else
|
||||
{
|
||||
var r2 = new Rect(position.x + 1, position.y + 1, position.width - 2, position.height - 2);
|
||||
var rgbRect = new Rect(r2.x, r2.y, r2.width, r2.height * 0.8f);
|
||||
var alphaRect = new Rect(rgbRect.x, rgbRect.yMax, r2.width, r2.height * 0.2f);
|
||||
|
||||
var rgbTexture = gradient.GetPreviewRampTexture(256, 1, colorSpace, viewChannelMask ^ LwguiGradient.ChannelMask.Alpha);
|
||||
var alphaTexture = gradient.GetPreviewRampTexture(256, 1, colorSpace, LwguiGradient.ChannelMask.Alpha);
|
||||
|
||||
Color oldColor = GUI.color;
|
||||
GUI.color = Color.white; //Dont want the Playmode tint to be applied to gradient textures.
|
||||
GUI.DrawTexture(rgbRect, rgbTexture, ScaleMode.StretchToFill, false);
|
||||
GUI.DrawTexture(alphaRect, alphaTexture, ScaleMode.StretchToFill, false);
|
||||
GUI.color = oldColor;
|
||||
}
|
||||
}
|
||||
|
||||
public static void GradientField(Rect position, GUIContent label, LwguiGradient gradient,
|
||||
ColorSpace colorSpace = ColorSpace.Gamma,
|
||||
LwguiGradient.ChannelMask viewChannelMask = LwguiGradient.ChannelMask.All,
|
||||
LwguiGradient.GradientTimeRange timeRange = LwguiGradient.GradientTimeRange.One,
|
||||
Action onOpenWindow = null)
|
||||
{
|
||||
int id = GUIUtility.GetControlID(s_LwguiGradientHash, FocusType.Keyboard, position);
|
||||
var rect = EditorGUI.PrefixLabel(position, id, label);
|
||||
var evt = Event.current;
|
||||
|
||||
|
||||
// internal static Gradient DoGradientField(Rect position, int id, Gradient value, SerializedProperty property, bool hdr, ColorSpace space)
|
||||
switch (evt.GetTypeForControl(id))
|
||||
{
|
||||
case EventType.MouseDown:
|
||||
if (rect.Contains(evt.mousePosition))
|
||||
{
|
||||
if (evt.button == 0)
|
||||
{
|
||||
s_LwguiGradientID = id;
|
||||
GUIUtility.keyboardControl = id;
|
||||
LwguiGradientWindow.Show(gradient, colorSpace, viewChannelMask, timeRange, GUIView.current);
|
||||
onOpenWindow?.Invoke();
|
||||
GUIUtility.ExitGUI();
|
||||
}
|
||||
else if (evt.button == 1)
|
||||
{
|
||||
// if (property != null)
|
||||
// GradientContextMenu.Show(property.Copy());
|
||||
// // TODO: make work for Gradient value
|
||||
}
|
||||
}
|
||||
break;
|
||||
case EventType.KeyDown:
|
||||
if (GUIUtility.keyboardControl == id && (evt.keyCode == KeyCode.Space || evt.keyCode == KeyCode.Return || evt.keyCode == KeyCode.KeypadEnter))
|
||||
{
|
||||
evt.Use();
|
||||
LwguiGradientWindow.Show(gradient, colorSpace, viewChannelMask, timeRange, GUIView.current);
|
||||
onOpenWindow?.Invoke();
|
||||
GUIUtility.ExitGUI();
|
||||
}
|
||||
|
||||
break;
|
||||
case EventType.Repaint:
|
||||
DrawGradientWithSeparateAlphaChannel(rect, gradient, colorSpace, viewChannelMask);
|
||||
break;
|
||||
case EventType.ExecuteCommand:
|
||||
// When drawing the modifying Gradient Field and it has changed
|
||||
if ((GUIUtility.keyboardControl == id || s_LwguiGradientID == id)
|
||||
&& (evt.commandName is LwguiGradientWindow.LwguiGradientChangedCommand))
|
||||
{
|
||||
GUI.changed = true;
|
||||
LwguiGradientHelper.ClearRampPreviewCaches();
|
||||
HandleUtility.Repaint();
|
||||
}
|
||||
break;
|
||||
case EventType.ValidateCommand:
|
||||
// Sync Undo/Redo result to editor window
|
||||
if (s_LwguiGradientID == id && evt.commandName == "UndoRedoPerformed")
|
||||
{
|
||||
LwguiGradientWindow.UpdateCurrentGradient(gradient);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/// Lwgui Gradient Field with full Undo/Redo/ContextMenu functions
|
||||
public static void GradientField(Rect position, GUIContent label, SerializedProperty property, LwguiGradient gradient,
|
||||
ColorSpace colorSpace = ColorSpace.Gamma,
|
||||
LwguiGradient.ChannelMask viewChannelMask = LwguiGradient.ChannelMask.All,
|
||||
LwguiGradient.GradientTimeRange timeRange = LwguiGradient.GradientTimeRange.One)
|
||||
{
|
||||
label = EditorGUI.BeginProperty(position, label, property);
|
||||
EditorGUI.BeginChangeCheck();
|
||||
|
||||
GradientField(position, label, gradient, colorSpace, viewChannelMask, timeRange,
|
||||
() => LwguiGradientWindow.RegisterSerializedObjectUndo(property.serializedObject.targetObject));
|
||||
|
||||
if (EditorGUI.EndChangeCheck())
|
||||
{
|
||||
GUI.changed = true;
|
||||
LwguiGradientWindow.RegisterSerializedObjectUndo(property.serializedObject.targetObject);
|
||||
}
|
||||
EditorGUI.EndProperty();
|
||||
}
|
||||
|
||||
public static bool GradientEditButton(Rect position, GUIContent icon, LwguiGradient gradient,
|
||||
ColorSpace colorSpace = ColorSpace.Gamma,
|
||||
LwguiGradient.ChannelMask viewChannelMask = LwguiGradient.ChannelMask.All,
|
||||
LwguiGradient.GradientTimeRange timeRange = LwguiGradient.GradientTimeRange.One,
|
||||
Func<bool> shouldOpenWindowAfterClickingEvent = null)
|
||||
{
|
||||
int id = GUIUtility.GetControlID(s_LwguiGradientHash, FocusType.Keyboard, position);
|
||||
var evt = Event.current;
|
||||
|
||||
// When drawing the modifying Gradient Field and it has changed
|
||||
if ((GUIUtility.keyboardControl == id || s_LwguiGradientID == id)
|
||||
&& evt.GetTypeForControl(id) == EventType.ExecuteCommand
|
||||
&& evt.commandName == LwguiGradientWindow.LwguiGradientChangedCommand)
|
||||
{
|
||||
GUI.changed = true;
|
||||
HandleUtility.Repaint();
|
||||
}
|
||||
|
||||
// Sync Undo/Redo result to editor window
|
||||
if (s_LwguiGradientID == id
|
||||
&& evt.commandName == "UndoRedoPerformed")
|
||||
{
|
||||
LwguiGradientWindow.UpdateCurrentGradient(gradient);
|
||||
}
|
||||
|
||||
// Open editor window
|
||||
var clicked = ReflectionHelper.GUI_Button(position, id, icon, GUI.skin.button);
|
||||
if (clicked)
|
||||
{
|
||||
if (shouldOpenWindowAfterClickingEvent == null || shouldOpenWindowAfterClickingEvent.Invoke())
|
||||
{
|
||||
s_LwguiGradientID = id;
|
||||
GUIUtility.keyboardControl = id;
|
||||
LwguiGradientWindow.Show(gradient, colorSpace, viewChannelMask, timeRange, GUIView.current);
|
||||
GUIUtility.ExitGUI();
|
||||
}
|
||||
}
|
||||
|
||||
return clicked;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 016014c82cb94b5d9f271b1b06986541
|
||||
timeCreated: 1720424032
|
||||
@ -0,0 +1,117 @@
|
||||
// Copyright (c) Jason Ma
|
||||
|
||||
using System.Collections.Generic;
|
||||
using LWGUI.Runtime.LwguiGradient;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Serialization;
|
||||
|
||||
namespace LWGUI.LwguiGradientEditor
|
||||
{
|
||||
[ExcludeFromPreset]
|
||||
class LwguiGradientPresetLibrary : PresetLibrary
|
||||
{
|
||||
[SerializeField]
|
||||
List<LwguiGradientPreset> m_Presets = new List<LwguiGradientPreset>();
|
||||
|
||||
public override int Count()
|
||||
{
|
||||
return m_Presets.Count;
|
||||
}
|
||||
|
||||
public override object GetPreset(int index)
|
||||
{
|
||||
return m_Presets[index].lwguiGradient;
|
||||
}
|
||||
|
||||
public override void Add(object presetObject, string presetName)
|
||||
{
|
||||
LwguiGradient gradient = presetObject as LwguiGradient;
|
||||
if (gradient == null)
|
||||
{
|
||||
Debug.LogError("Wrong type used in LwguiGradientPresetLibrary");
|
||||
return;
|
||||
}
|
||||
|
||||
m_Presets.Add(new LwguiGradientPreset(new LwguiGradient(gradient), presetName));
|
||||
}
|
||||
|
||||
public override void Replace(int index, object newPresetObject)
|
||||
{
|
||||
LwguiGradient gradient = newPresetObject as LwguiGradient;
|
||||
if (gradient == null)
|
||||
{
|
||||
Debug.LogError("Wrong type used in LwguiGradientPresetLibrary");
|
||||
return;
|
||||
}
|
||||
|
||||
m_Presets[index].lwguiGradient = new LwguiGradient(gradient);
|
||||
}
|
||||
|
||||
public override void Remove(int index)
|
||||
{
|
||||
m_Presets.RemoveAt(index);
|
||||
}
|
||||
|
||||
public override void Move(int index, int destIndex, bool insertAfterDestIndex)
|
||||
{
|
||||
PresetLibraryHelpers.MoveListItem(m_Presets, index, destIndex, insertAfterDestIndex);
|
||||
}
|
||||
|
||||
public override void Draw(Rect rect, int index)
|
||||
{
|
||||
Draw(rect, m_Presets[index].lwguiGradient, ColorSpace.Gamma, LwguiGradient.ChannelMask.All);
|
||||
}
|
||||
|
||||
public override void Draw(Rect rect, object presetObject)
|
||||
{
|
||||
Draw(rect, presetObject as LwguiGradient, ColorSpace.Gamma, LwguiGradient.ChannelMask.All);
|
||||
}
|
||||
|
||||
public void Draw(Rect rect, LwguiGradient gradient, ColorSpace colorSpace, LwguiGradient.ChannelMask viewChannelMask)
|
||||
{
|
||||
if (gradient == null)
|
||||
return;
|
||||
LwguiGradientEditorHelper.DrawGradientWithSeparateAlphaChannel(rect, gradient, colorSpace, viewChannelMask);
|
||||
}
|
||||
|
||||
public override string GetName(int index)
|
||||
{
|
||||
return m_Presets[index].name;
|
||||
}
|
||||
|
||||
public override void SetName(int index, string presetName)
|
||||
{
|
||||
m_Presets[index].name = presetName;
|
||||
}
|
||||
|
||||
|
||||
[System.Serializable]
|
||||
class LwguiGradientPreset
|
||||
{
|
||||
[SerializeField]
|
||||
string m_Name;
|
||||
|
||||
[SerializeField]
|
||||
LwguiGradient m_LwguiGradient;
|
||||
|
||||
public LwguiGradientPreset(LwguiGradient preset, string presetName)
|
||||
{
|
||||
lwguiGradient = preset;
|
||||
name = presetName;
|
||||
}
|
||||
|
||||
public LwguiGradient lwguiGradient
|
||||
{
|
||||
get => m_LwguiGradient;
|
||||
set => m_LwguiGradient = value;
|
||||
}
|
||||
|
||||
public string name
|
||||
{
|
||||
get => m_Name;
|
||||
set => m_Name = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 6aa6b41078c94b978a355082d28769f0
|
||||
timeCreated: 1721013180
|
||||
@ -0,0 +1,40 @@
|
||||
// Copyright (c) Jason Ma
|
||||
|
||||
using LWGUI.Runtime.LwguiGradient;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
|
||||
namespace LWGUI.LwguiGradientEditor
|
||||
{
|
||||
[CustomEditor(typeof(LwguiGradientPresetLibrary))]
|
||||
internal class LwguiGradientPresetLibraryEditor : Editor
|
||||
{
|
||||
private GenericPresetLibraryInspector<LwguiGradientPresetLibrary> m_GenericPresetLibraryInspector;
|
||||
|
||||
public void OnEnable()
|
||||
{
|
||||
m_GenericPresetLibraryInspector = new GenericPresetLibraryInspector<LwguiGradientPresetLibrary>(target, "Lwgui Gradient Preset Library", OnEditButtonClicked)
|
||||
{
|
||||
presetSize = new Vector2(72, 16),
|
||||
lineSpacing = 4f
|
||||
};
|
||||
}
|
||||
|
||||
public void OnDestroy()
|
||||
{
|
||||
m_GenericPresetLibraryInspector?.OnDestroy();
|
||||
}
|
||||
|
||||
public override void OnInspectorGUI()
|
||||
{
|
||||
m_GenericPresetLibraryInspector.itemViewMode = PresetLibraryEditorState.GetItemViewMode("LwguiGradient"); // ensure in-sync
|
||||
m_GenericPresetLibraryInspector?.OnInspectorGUI();
|
||||
}
|
||||
|
||||
private void OnEditButtonClicked(string libraryPath)
|
||||
{
|
||||
LwguiGradientWindow.Show(new LwguiGradient());
|
||||
LwguiGradientWindow.instance.currentPresetLibrary = libraryPath;
|
||||
}
|
||||
}
|
||||
} // namespace
|
||||
@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c5050da63672448d8f12cf3c82e12a6a
|
||||
timeCreated: 1721013226
|
||||
@ -0,0 +1,318 @@
|
||||
// Copyright (c) Jason Ma
|
||||
|
||||
using System;
|
||||
using UnityEngine;
|
||||
using UnityEditor;
|
||||
using LWGUI.Runtime.LwguiGradient;
|
||||
using UnityEngine.Serialization;
|
||||
using Object = UnityEngine.Object;
|
||||
|
||||
namespace LWGUI.LwguiGradientEditor
|
||||
{
|
||||
internal class PresetLibraryLwguiGradientEditor : PresetLibraryEditor<LwguiGradientPresetLibrary>
|
||||
{
|
||||
public PresetLibraryLwguiGradientEditor(ScriptableObjectSaveLoadHelper<LwguiGradientPresetLibrary> helper,
|
||||
PresetLibraryEditorState state,
|
||||
Action<int, object> itemClickedCallback
|
||||
) : base(helper, state, itemClickedCallback)
|
||||
{}
|
||||
|
||||
public ColorSpace colorSpace { get; set; }
|
||||
public LwguiGradient.ChannelMask viewChannelMask { get; set; }
|
||||
|
||||
protected override void DrawPreset(PresetLibrary lib, Rect rect, object presetObject)
|
||||
{
|
||||
((LwguiGradientPresetLibrary)lib).Draw(rect, presetObject as LwguiGradient, colorSpace, viewChannelMask);
|
||||
}
|
||||
}
|
||||
|
||||
public class LwguiGradientWindow : EditorWindow
|
||||
{
|
||||
#region Fields
|
||||
|
||||
private static LwguiGradientWindow _lwguiGradientWindow;
|
||||
public const string presetsEditorPrefID = "LwguiGradient";
|
||||
|
||||
private LwguiGradientEditor _lwguiGradientEditor;
|
||||
private PresetLibraryLwguiGradientEditor _lwguiGradientLibraryEditor;
|
||||
[SerializeField] private PresetLibraryEditorState _LwguiGradientLibraryEditorState;
|
||||
|
||||
[NonSerialized] public LwguiGradient lwguiGradient;
|
||||
[NonSerialized] public ColorSpace colorSpace;
|
||||
[NonSerialized] public LwguiGradient.ChannelMask viewChannelMask;
|
||||
[NonSerialized] public LwguiGradient.GradientTimeRange gradientTimeRange;
|
||||
|
||||
private GUIView _viewToUpdate;
|
||||
private Action<LwguiGradient> _onChange;
|
||||
|
||||
#endregion
|
||||
|
||||
#region GUI Layout
|
||||
|
||||
private static readonly Vector2 _minWindowSize = new (750, 500);
|
||||
private static readonly float _presetLibraryHeight = 100;
|
||||
private Rect _gradientEditorRect => new Rect(0, 0, position.width, position.height - _presetLibraryHeight);
|
||||
private Rect _presetLibraryRect => new Rect(0, position.height - _presetLibraryHeight, position.width, _presetLibraryHeight);
|
||||
|
||||
#endregion
|
||||
|
||||
public static LwguiGradientWindow instance
|
||||
{
|
||||
get
|
||||
{
|
||||
if (!_lwguiGradientWindow)
|
||||
Debug.LogError("Lwgui Gradient Window not initalized, did you call Show first?");
|
||||
return _lwguiGradientWindow;
|
||||
}
|
||||
}
|
||||
|
||||
public string currentPresetLibrary
|
||||
{
|
||||
get
|
||||
{
|
||||
Init(false);
|
||||
return _lwguiGradientLibraryEditor.currentLibraryWithoutExtension;
|
||||
}
|
||||
set
|
||||
{
|
||||
Init(false);
|
||||
_lwguiGradientLibraryEditor.currentLibraryWithoutExtension = value;
|
||||
}
|
||||
}
|
||||
|
||||
public static bool visible => _lwguiGradientWindow != null;
|
||||
|
||||
public void Init(bool force = true, bool forceRecreate = false)
|
||||
{
|
||||
if (_lwguiGradientEditor == null || force || forceRecreate)
|
||||
{
|
||||
if (_lwguiGradientEditor == null || forceRecreate)
|
||||
{
|
||||
_lwguiGradientEditor = new LwguiGradientEditor();
|
||||
}
|
||||
_lwguiGradientEditor.Init(_gradientEditorRect, lwguiGradient, colorSpace, viewChannelMask, gradientTimeRange, _onChange);
|
||||
}
|
||||
|
||||
if (_LwguiGradientLibraryEditorState == null || forceRecreate)
|
||||
{
|
||||
_LwguiGradientLibraryEditorState = new PresetLibraryEditorState(presetsEditorPrefID);
|
||||
_LwguiGradientLibraryEditorState.TransferEditorPrefsState(true);
|
||||
}
|
||||
|
||||
if (_lwguiGradientLibraryEditor == null || force || forceRecreate)
|
||||
{
|
||||
if (_lwguiGradientLibraryEditor == null || forceRecreate)
|
||||
{
|
||||
var saveLoadHelper = new ScriptableObjectSaveLoadHelper<LwguiGradientPresetLibrary>("lwguigradients", SaveType.Text);
|
||||
_lwguiGradientLibraryEditor = new PresetLibraryLwguiGradientEditor(saveLoadHelper, _LwguiGradientLibraryEditorState, PresetClickedCallback);
|
||||
UpdatePresetLibraryViewSettings();
|
||||
}
|
||||
_lwguiGradientLibraryEditor.showHeader = true;
|
||||
_lwguiGradientLibraryEditor.minMaxPreviewHeight = new Vector2(14f, 14f);
|
||||
}
|
||||
}
|
||||
|
||||
void UpdatePresetLibraryViewSettings()
|
||||
{
|
||||
_lwguiGradientLibraryEditor.colorSpace = _lwguiGradientEditor.colorSpace;
|
||||
_lwguiGradientLibraryEditor.viewChannelMask = _lwguiGradientEditor.viewChannelMask;
|
||||
}
|
||||
|
||||
/// Used to modify the LwguiGradient value externally, such as: Undo/Redo/Select Preset
|
||||
public static void UpdateCurrentGradient(LwguiGradient newGradient, bool doDeepCopy = false)
|
||||
{
|
||||
if (_lwguiGradientWindow == null)
|
||||
return;
|
||||
|
||||
if (doDeepCopy)
|
||||
{
|
||||
_lwguiGradientWindow.lwguiGradient.DeepCopyFrom(newGradient);
|
||||
}
|
||||
else
|
||||
{
|
||||
_lwguiGradientWindow.lwguiGradient = newGradient;
|
||||
}
|
||||
// Debug.Log("Update");
|
||||
_lwguiGradientWindow.Init();
|
||||
_lwguiGradientWindow.Repaint();
|
||||
GUI.changed = true;
|
||||
LwguiGradientHelper.ClearRampPreviewCaches();
|
||||
}
|
||||
|
||||
private static LwguiGradientWindow GetWindow(bool focus = true) => (LwguiGradientWindow)GetWindow(typeof(LwguiGradientWindow), true, "LWGUI Gradient Editor", focus);
|
||||
|
||||
internal static void Show(LwguiGradient gradient, ColorSpace colorSpace = ColorSpace.Gamma, LwguiGradient.ChannelMask viewChannelMask = LwguiGradient.ChannelMask.All, LwguiGradient.GradientTimeRange timeRange = LwguiGradient.GradientTimeRange.One, GUIView viewToUpdate = null, Action<LwguiGradient> onChange = null)
|
||||
{
|
||||
if (_lwguiGradientWindow == null)
|
||||
{
|
||||
_lwguiGradientWindow = GetWindow();
|
||||
_lwguiGradientWindow.minSize = _minWindowSize;
|
||||
_lwguiGradientWindow.RegisterEvents();
|
||||
}
|
||||
else
|
||||
{
|
||||
_lwguiGradientWindow = GetWindow();
|
||||
}
|
||||
|
||||
_lwguiGradientWindow.lwguiGradient = gradient;
|
||||
_lwguiGradientWindow.colorSpace = colorSpace;
|
||||
_lwguiGradientWindow.viewChannelMask = viewChannelMask;
|
||||
_lwguiGradientWindow.gradientTimeRange = timeRange;
|
||||
_lwguiGradientWindow._viewToUpdate = viewToUpdate;
|
||||
_lwguiGradientWindow._onChange = onChange;
|
||||
|
||||
_lwguiGradientWindow.Init();
|
||||
_lwguiGradientWindow.Show();
|
||||
// window.ShowAuxWindow();
|
||||
|
||||
LwguiGradientHelper.ClearRampPreviewCaches();
|
||||
}
|
||||
|
||||
public static void CloseWindow()
|
||||
{
|
||||
if (_lwguiGradientWindow == null)
|
||||
return;
|
||||
|
||||
_lwguiGradientWindow.UnregisterEvents();
|
||||
_lwguiGradientWindow.Close();
|
||||
// GUIUtility.ExitGUI();
|
||||
}
|
||||
|
||||
public static void RepaintWindow()
|
||||
{
|
||||
if (_lwguiGradientWindow == null)
|
||||
return;
|
||||
_lwguiGradientWindow.Repaint();
|
||||
}
|
||||
|
||||
public static void RegisterSerializedObjectUndo(Object targetObject)
|
||||
{
|
||||
Undo.RegisterCompleteObjectUndo(targetObject, "Lwgui Gradient Editor");
|
||||
EditorUtility.SetDirty(targetObject);
|
||||
}
|
||||
|
||||
public static void RegisterRampMapUndo(Object texture, Object assetImporter)
|
||||
{
|
||||
Undo.RecordObjects(new Object[]{ texture, assetImporter }, "Set Lwgui Gradient To Texture");
|
||||
EditorUtility.SetDirty(texture);
|
||||
EditorUtility.SetDirty(assetImporter);
|
||||
}
|
||||
|
||||
private void OnGUI()
|
||||
{
|
||||
if (lwguiGradient == null)
|
||||
return;
|
||||
|
||||
Init(false);
|
||||
|
||||
// Separator
|
||||
EditorGUI.DrawRect(new Rect(_presetLibraryRect.x, _presetLibraryRect.y - 1, _presetLibraryRect.width, 1), new Color(0, 0, 0, 0.3f));
|
||||
EditorGUI.DrawRect(new Rect(_presetLibraryRect.x, _presetLibraryRect.y, _presetLibraryRect.width, 1), new Color(1, 1, 1, 0.1f));
|
||||
|
||||
|
||||
EditorGUI.BeginChangeCheck();
|
||||
_lwguiGradientEditor.OnGUI(_gradientEditorRect);
|
||||
_lwguiGradientLibraryEditor.OnGUI(_presetLibraryRect, lwguiGradient);
|
||||
if (EditorGUI.EndChangeCheck())
|
||||
{
|
||||
LwguiGradientHelper.ClearRampPreviewCaches();
|
||||
UpdatePresetLibraryViewSettings();
|
||||
SendEvent(true);
|
||||
}
|
||||
}
|
||||
|
||||
public const string LwguiGradientChangedCommand = "LwguiGradientChanged";
|
||||
|
||||
void SendEvent(bool exitGUI)
|
||||
{
|
||||
if (_viewToUpdate != null)
|
||||
{
|
||||
Event e = EditorGUIUtility.CommandEvent(LwguiGradientChangedCommand);
|
||||
Repaint();
|
||||
_viewToUpdate.SendEvent(e);
|
||||
if (exitGUI)
|
||||
GUIUtility.ExitGUI();
|
||||
}
|
||||
if (_onChange != null)
|
||||
{
|
||||
_onChange(lwguiGradient);
|
||||
}
|
||||
}
|
||||
|
||||
private void OnEnable()
|
||||
{
|
||||
Application.logMessageReceived += LwguiGradientEditor.CheckAddGradientKeyFailureLog;
|
||||
hideFlags = HideFlags.DontSave;
|
||||
}
|
||||
|
||||
private void OnDisable()
|
||||
{
|
||||
Application.logMessageReceived -= LwguiGradientEditor.CheckAddGradientKeyFailureLog;
|
||||
|
||||
_LwguiGradientLibraryEditorState?.TransferEditorPrefsState(false);
|
||||
|
||||
UnregisterEvents();
|
||||
Clear();
|
||||
}
|
||||
|
||||
private void OnDestroy()
|
||||
{
|
||||
UnregisterEvents();
|
||||
_lwguiGradientLibraryEditor?.UnloadUsedLibraries();
|
||||
|
||||
Clear();
|
||||
}
|
||||
|
||||
private void Clear()
|
||||
{
|
||||
_lwguiGradientEditor = null;
|
||||
_lwguiGradientWindow = null;
|
||||
_lwguiGradientLibraryEditor = null;
|
||||
}
|
||||
|
||||
private void RegisterEvents()
|
||||
{
|
||||
#if UNITY_2022_2_OR_NEWER
|
||||
Undo.undoRedoEvent += OnUndoPerformed;
|
||||
#endif
|
||||
EditorApplication.playModeStateChanged += OnPlayModeStateChanged;
|
||||
}
|
||||
|
||||
private void UnregisterEvents()
|
||||
{
|
||||
#if UNITY_2022_2_OR_NEWER
|
||||
Undo.undoRedoEvent -= OnUndoPerformed;
|
||||
#endif
|
||||
EditorApplication.playModeStateChanged -= OnPlayModeStateChanged;
|
||||
}
|
||||
|
||||
#region Call Backs
|
||||
|
||||
#if UNITY_2022_2_OR_NEWER
|
||||
private void OnUndoPerformed(in UndoRedoInfo info)
|
||||
{
|
||||
// Debug.Log("Init");
|
||||
_lwguiGradientWindow.Init();
|
||||
_lwguiGradientWindow.Repaint();
|
||||
}
|
||||
#endif
|
||||
|
||||
void OnPlayModeStateChanged(PlayModeStateChange state)
|
||||
{
|
||||
Close();
|
||||
}
|
||||
|
||||
void PresetClickedCallback(int clickCount, object presetObject)
|
||||
{
|
||||
LwguiGradient gradient = presetObject as LwguiGradient;
|
||||
if (gradient == null)
|
||||
Debug.LogError("Incorrect object passed " + presetObject);
|
||||
|
||||
UpdateCurrentGradient(gradient, true);
|
||||
// UnityEditorInternal.GradientPreviewCache.ClearCache();
|
||||
// LwguiGradientHelper.ClearRampPreviewCaches();
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 097db44e7f52445b80daf9c3c3e9f26b
|
||||
timeCreated: 1716795885
|
||||
BIN
Assets/External/NiloToonURP/Editor/ShaderGUI/LWGUI-main/UnityEditorExtension/README.md
(Stored with Git LFS)
vendored
Normal file
BIN
Assets/External/NiloToonURP/Editor/ShaderGUI/LWGUI-main/UnityEditorExtension/README.md
(Stored with Git LFS)
vendored
Normal file
Binary file not shown.
7
Assets/External/NiloToonURP/Editor/ShaderGUI/LWGUI-main/UnityEditorExtension/README.md.meta
vendored
Normal file
7
Assets/External/NiloToonURP/Editor/ShaderGUI/LWGUI-main/UnityEditorExtension/README.md.meta
vendored
Normal file
@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 5d0d1d146a4108b4ebb49ce891131f50
|
||||
TextScriptImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
242
Assets/External/NiloToonURP/Editor/ShaderGUI/LWGUI-main/UnityEditorExtension/ReflectionHelper.cs
vendored
Normal file
242
Assets/External/NiloToonURP/Editor/ShaderGUI/LWGUI-main/UnityEditorExtension/ReflectionHelper.cs
vendored
Normal file
@ -0,0 +1,242 @@
|
||||
// Copyright (c) Jason Ma
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
|
||||
namespace LWGUI
|
||||
{
|
||||
public static class ReflectionHelper
|
||||
{
|
||||
#region MaterialPropertyHandler
|
||||
|
||||
private static readonly Type MaterialPropertyHandler_Type = Assembly.GetAssembly(typeof(Editor)).GetType("UnityEditor.MaterialPropertyHandler");
|
||||
private static readonly MethodInfo MaterialPropertyHandler_GetHandler_Method = MaterialPropertyHandler_Type.GetMethod("GetHandler", BindingFlags.Static | BindingFlags.NonPublic);
|
||||
private static readonly PropertyInfo MaterialPropertyHandler_PropertyDrawer_Property = MaterialPropertyHandler_Type.GetProperty("propertyDrawer");
|
||||
private static readonly FieldInfo MaterialPropertyHandler_DecoratorDrawers_Field = MaterialPropertyHandler_Type.GetField("m_DecoratorDrawers", BindingFlags.NonPublic | BindingFlags.Instance);
|
||||
|
||||
public static MaterialPropertyDrawer GetPropertyDrawer(Shader shader, MaterialProperty prop, out List<MaterialPropertyDrawer> decoratorDrawers)
|
||||
{
|
||||
decoratorDrawers = new List<MaterialPropertyDrawer>();
|
||||
var handler = MaterialPropertyHandler_GetHandler_Method.Invoke(null, new object[] { shader, prop.name });
|
||||
if (handler != null && handler.GetType() == MaterialPropertyHandler_Type)
|
||||
{
|
||||
decoratorDrawers = MaterialPropertyHandler_DecoratorDrawers_Field.GetValue(handler) as List<MaterialPropertyDrawer>;
|
||||
return MaterialPropertyHandler_PropertyDrawer_Property.GetValue(handler, null) as MaterialPropertyDrawer;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public static MaterialPropertyDrawer GetPropertyDrawer(Shader shader, MaterialProperty prop)
|
||||
{
|
||||
return GetPropertyDrawer(shader, prop, out _);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
#region MaterialEditor
|
||||
|
||||
public static float DoPowerRangeProperty(Rect position, MaterialProperty prop, GUIContent label, float power)
|
||||
{
|
||||
return MaterialEditor.DoPowerRangeProperty(position, prop, label, power);
|
||||
}
|
||||
|
||||
public static void DefaultShaderPropertyInternal(this MaterialEditor editor, Rect position, MaterialProperty prop, GUIContent label)
|
||||
{
|
||||
editor.DefaultShaderPropertyInternal(position, prop, label);
|
||||
}
|
||||
|
||||
public static List<Renderer> GetMeshRenderersByMaterialEditor(this MaterialEditor materialEditor)
|
||||
{
|
||||
var outRenderers = new List<Renderer>();
|
||||
|
||||
// MaterialEditor.ShouldEditorBeHidden()
|
||||
PropertyEditor property = materialEditor.propertyViewer as PropertyEditor;
|
||||
if (property)
|
||||
{
|
||||
GameObject gameObject = property.tracker.activeEditors[0].target as GameObject;
|
||||
if (gameObject)
|
||||
{
|
||||
outRenderers.AddRange(gameObject.GetComponents<MeshRenderer>());
|
||||
outRenderers.AddRange(gameObject.GetComponents<SkinnedMeshRenderer>());
|
||||
}
|
||||
}
|
||||
|
||||
return outRenderers;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
#region EditorUtility
|
||||
|
||||
public static void DisplayCustomMenuWithSeparators(Rect position, string[] options, bool[] enabled, bool[] separator, int[] selected, EditorUtility.SelectMenuItemFunction callback, object userData = null, bool showHotkey = false)
|
||||
{
|
||||
EditorUtility.DisplayCustomMenuWithSeparators(position, options, enabled, separator, selected, callback, userData, showHotkey);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
#region EditorGUI
|
||||
|
||||
public static float EditorGUI_Indent => EditorGUI.indentLevel;
|
||||
|
||||
#endregion
|
||||
|
||||
#region EditorGUILayout
|
||||
|
||||
public static float EditorGUILayout_kLabelFloatMinW => EditorGUILayout.kLabelFloatMinW;
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
#region MaterialEnumDrawer
|
||||
|
||||
// UnityEditor.MaterialEnumDrawer(string enumName)
|
||||
private static Type[] _types;
|
||||
|
||||
public static Type[] GetAllTypes()
|
||||
{
|
||||
if (_types == null)
|
||||
{
|
||||
_types = AppDomain.CurrentDomain.GetAssemblies()
|
||||
.SelectMany(assembly =>
|
||||
{
|
||||
if (assembly == null)
|
||||
return Type.EmptyTypes;
|
||||
try
|
||||
{
|
||||
return assembly.GetTypes();
|
||||
}
|
||||
catch (ReflectionTypeLoadException ex)
|
||||
{
|
||||
Debug.LogError(ex);
|
||||
return Type.EmptyTypes;
|
||||
}
|
||||
}).ToArray();
|
||||
}
|
||||
|
||||
return _types;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
#region MaterialProperty.PropertyData
|
||||
|
||||
#if UNITY_2022_1_OR_NEWER
|
||||
private static readonly Type MaterialProperty_Type = typeof(MaterialProperty);
|
||||
private static readonly Type PropertyData_Type = MaterialProperty_Type.GetNestedType("PropertyData", BindingFlags.NonPublic);
|
||||
private static readonly MethodInfo PropertyData_MergeStack_Method = PropertyData_Type.GetMethod("MergeStack", BindingFlags.Static | BindingFlags.NonPublic);
|
||||
private static readonly MethodInfo PropertyData_HandleApplyRevert_Method = PropertyData_Type.GetMethod("HandleApplyRevert", BindingFlags.Static | BindingFlags.NonPublic);
|
||||
|
||||
public static void HandleApplyRevert(GenericMenu menu, MaterialProperty prop)
|
||||
{
|
||||
var parameters = new object[3];
|
||||
PropertyData_MergeStack_Method.Invoke(null, parameters);
|
||||
var overriden = (bool)parameters[2];
|
||||
var singleEditing = prop.targets.Length == 1;
|
||||
|
||||
if (overriden)
|
||||
{
|
||||
PropertyData_HandleApplyRevert_Method.Invoke(null, new object[] { menu, singleEditing, prop.targets });
|
||||
menu.AddSeparator("");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#endregion
|
||||
|
||||
#region GUI
|
||||
|
||||
private static readonly MethodInfo gui_Button_Method = typeof(GUI).GetMethod("Button", BindingFlags.Static | BindingFlags.NonPublic);
|
||||
|
||||
public static bool GUI_Button(Rect position, int id, GUIContent content, GUIStyle style)
|
||||
{
|
||||
return (bool)gui_Button_Method.Invoke(null, new object[] { position, id, content, style });
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region GradientEditor
|
||||
|
||||
private static readonly FieldInfo k_MaxNumKeys_Field = typeof(GradientEditor).GetField("k_MaxNumKeys", BindingFlags.Static | BindingFlags.NonPublic);
|
||||
public static readonly int maxGradientKeyCount = (int)k_MaxNumKeys_Field.GetValue(null);
|
||||
|
||||
|
||||
private static readonly FieldInfo m_SelectedSwatch_Field = typeof(GradientEditor).GetField("m_SelectedSwatch", BindingFlags.Instance | BindingFlags.NonPublic);
|
||||
internal static GradientEditor.Swatch GetSelectedSwatch(this GradientEditor gradientEditor)
|
||||
{
|
||||
return m_SelectedSwatch_Field.GetValue(gradientEditor) as GradientEditor.Swatch;
|
||||
}
|
||||
|
||||
internal static void SetSelectedSwatch(this GradientEditor gradientEditor, GradientEditor.Swatch swatch)
|
||||
{
|
||||
m_SelectedSwatch_Field.SetValue(gradientEditor, swatch);
|
||||
}
|
||||
|
||||
|
||||
private static readonly FieldInfo m_RGBSwatches_Field = typeof(GradientEditor).GetField("m_RGBSwatches", BindingFlags.Instance | BindingFlags.NonPublic);
|
||||
internal static List<GradientEditor.Swatch> GetRGBdSwatches(this GradientEditor gradientEditor)
|
||||
{
|
||||
return m_RGBSwatches_Field.GetValue(gradientEditor) as List<GradientEditor.Swatch>;
|
||||
}
|
||||
|
||||
|
||||
private static readonly FieldInfo m_AlphaSwatches_Field = typeof(GradientEditor).GetField("m_AlphaSwatches", BindingFlags.Instance | BindingFlags.NonPublic);
|
||||
internal static List<GradientEditor.Swatch> GetAlphaSwatches(this GradientEditor gradientEditor)
|
||||
{
|
||||
return m_AlphaSwatches_Field.GetValue(gradientEditor) as List<GradientEditor.Swatch>;
|
||||
}
|
||||
|
||||
|
||||
private static object s_Styles_Value;
|
||||
private static readonly FieldInfo s_Styles_Field = typeof(GradientEditor).GetField("s_Styles", BindingFlags.Static | BindingFlags.NonPublic);
|
||||
public static void GradientEditor_SetStyles()
|
||||
{
|
||||
s_Styles_Value ??= Activator.CreateInstance(typeof(GradientEditor).GetNestedType("Styles", BindingFlags.NonPublic));
|
||||
s_Styles_Field.SetValue(null, s_Styles_Value);
|
||||
}
|
||||
|
||||
|
||||
private static readonly MethodInfo ShowSwatchArray_Method = typeof(GradientEditor)
|
||||
.GetMethod("ShowSwatchArray", BindingFlags.Instance | BindingFlags.NonPublic, null, new[] { typeof(Rect), typeof(List<GradientEditor.Swatch>), typeof(bool) }, null);
|
||||
|
||||
internal static void ShowSwatchArray(this GradientEditor gradientEditor, Rect position, List<GradientEditor.Swatch> swatches, bool isAlpha)
|
||||
{
|
||||
ShowSwatchArray_Method.Invoke(gradientEditor, new object[] { position, swatches, isAlpha });
|
||||
}
|
||||
|
||||
|
||||
private static readonly MethodInfo GetTime_Method = typeof(GradientEditor).GetMethod("GetTime", BindingFlags.Instance | BindingFlags.NonPublic);
|
||||
internal static float GetTime(this GradientEditor gradientEditor, float actualTime)
|
||||
{
|
||||
return (float)GetTime_Method.Invoke(gradientEditor, new object[] { actualTime });
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region CurveEditor
|
||||
|
||||
private static readonly FieldInfo m_CurveEditor_Field = typeof(CurveEditorWindow).GetField("m_CurveEditor", BindingFlags.Instance | BindingFlags.NonPublic);
|
||||
internal static CurveEditor GetCurveEditor(this CurveEditorWindow curveEditorWindow)
|
||||
{
|
||||
return m_CurveEditor_Field.GetValue(curveEditorWindow) as CurveEditor;
|
||||
}
|
||||
|
||||
|
||||
private static readonly MethodInfo AddKeyAtTime_Method = typeof(CurveEditor).GetMethod("AddKeyAtTime", BindingFlags.Instance | BindingFlags.NonPublic);
|
||||
internal static CurveSelection AddKeyAtTime(this CurveEditor curveEditor, CurveWrapper cw, float time)
|
||||
{
|
||||
return AddKeyAtTime_Method.Invoke(curveEditor, new object[] { cw, time }) as CurveSelection;
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,18 @@
|
||||
{
|
||||
"name": "Unity.InternalAPIEditorBridge.020",
|
||||
"rootNamespace": "",
|
||||
"references": [
|
||||
"LWGUI.Runtime"
|
||||
],
|
||||
"includePlatforms": [
|
||||
"Editor"
|
||||
],
|
||||
"excludePlatforms": [],
|
||||
"allowUnsafeCode": false,
|
||||
"overrideReferences": false,
|
||||
"precompiledReferences": [],
|
||||
"autoReferenced": true,
|
||||
"defineConstraints": [],
|
||||
"versionDefines": [],
|
||||
"noEngineReferences": false
|
||||
}
|
||||
@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: d40b1b73ac7645c43af711c92abd00b3
|
||||
AssemblyDefinitionImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@ -0,0 +1,57 @@
|
||||
// Copyright (c) Jason Ma
|
||||
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
using Object = UnityEngine.Object;
|
||||
|
||||
namespace LWGUI
|
||||
{
|
||||
public static class UnityEditorExtension
|
||||
{
|
||||
|
||||
#region MaterialEditor
|
||||
|
||||
// For Developers: Call this after a material has modified in code
|
||||
public static void ApplyMaterialPropertyAndDecoratorDrawers(Material material)
|
||||
{
|
||||
var objs = new Object[] { material };
|
||||
ApplyMaterialPropertyAndDecoratorDrawers(objs);
|
||||
}
|
||||
|
||||
// Called after edit or undo
|
||||
public static void ApplyMaterialPropertyAndDecoratorDrawers(Object[] targets)
|
||||
{
|
||||
if (!EditorMaterialUtility.disableApplyMaterialPropertyDrawers)
|
||||
{
|
||||
if (targets == null || targets.Length == 0)
|
||||
return;
|
||||
var target = targets[0] as Material;
|
||||
if (target == null)
|
||||
return;
|
||||
|
||||
var shader = target.shader;
|
||||
string[] propNames = MaterialEditor.GetMaterialPropertyNames(targets);
|
||||
for (int i = 0; i < propNames.Length; i++)
|
||||
{
|
||||
var prop = MaterialEditor.GetMaterialProperty(targets, i);
|
||||
var drawer = ReflectionHelper.GetPropertyDrawer(shader, prop, out var decoratorDrawers);
|
||||
|
||||
if (drawer != null)
|
||||
{
|
||||
drawer.Apply(prop);
|
||||
}
|
||||
if (decoratorDrawers != null)
|
||||
{
|
||||
foreach (var decoratorDrawer in decoratorDrawers)
|
||||
{
|
||||
decoratorDrawer.Apply(prop);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c461331302de45948d270b0842238473
|
||||
timeCreated: 1726212440
|
||||
BIN
Assets/External/NiloToonURP/Editor/ShaderGUI/LWGUI-main/package.json
(Stored with Git LFS)
vendored
BIN
Assets/External/NiloToonURP/Editor/ShaderGUI/LWGUI-main/package.json
(Stored with Git LFS)
vendored
Binary file not shown.
@ -18,9 +18,11 @@ namespace NiloToon.NiloToonURP
|
||||
{
|
||||
List<string> messages = new List<string>();
|
||||
|
||||
messages.Add("- Like URP14's Bloom but with more controls.\n" +
|
||||
"- Can supplement or replace URP's Bloom.\n" +
|
||||
"* This Bloom is slower than URP's Bloom (GPU)");
|
||||
messages.Add("- Similar to URP's Bloom but with more controls\n" +
|
||||
"- Great for preventing character become over bloom\n" +
|
||||
"- Allows different setting for Character & non-Character pixels\n" +
|
||||
"- Can supplement or replace URP's Bloom\n" +
|
||||
"* This Bloom is slower than URP's Bloom (GPU), only recommended for PC/Console");
|
||||
|
||||
messages.Add(IsPostProcessMessage);
|
||||
|
||||
|
||||
@ -19,7 +19,7 @@ namespace NiloToon.NiloToonURP
|
||||
List<string> messages = new List<string>();
|
||||
|
||||
messages.Add(
|
||||
"- Great for helping NiloToon characters blend into any environment\n" +
|
||||
"- Great for helping NiloToon characters to blend into any environment\n" +
|
||||
"- Great for artist-controlled lighting and rim light on NiloToon characters");
|
||||
|
||||
messages.Add(NonPostProcess_NotAffectPerformance_Message);
|
||||
|
||||
@ -19,10 +19,10 @@ namespace NiloToon.NiloToonURP
|
||||
List<string> messages = new List<string>();
|
||||
|
||||
messages.Add(
|
||||
"Make NiloToon characters convert all received additional light into rim light.\n" +
|
||||
"Useful if you want characters to receive many bright additional lights,\n" +
|
||||
"yet maintain a pleasing lighting effect, without becoming overly bright or unappealing.\n" +
|
||||
"(e.g., ideal for concert stage live performances or cinematic cut scenes)"
|
||||
"- Converts all received additional light into rim light for NiloToon characters\n" +
|
||||
"- Useful if you want characters to receive many bright additional lights,\n" +
|
||||
" yet maintain a pleasing lighting effect, without becoming overly bright or unappealing.\n" +
|
||||
"- Ideal for concert stage live performances or cinematic cut scenes"
|
||||
);
|
||||
|
||||
messages.Add(NonPostProcess_NotAffectPerformance_Message);
|
||||
|
||||
@ -17,7 +17,9 @@ namespace NiloToon.NiloToonURP
|
||||
protected override List<string> GetHelpBoxContent()
|
||||
{
|
||||
List<string> messages = new List<string>();
|
||||
|
||||
|
||||
messages.Add("- For extra color control of NiloToon_Environment shader\n" +
|
||||
"- Or for debug which material is using NiloToon_Environment shader" );
|
||||
messages.Add(NonPostProcess_NotAffectPerformance_Message);
|
||||
|
||||
return messages;
|
||||
|
||||
30
Assets/External/NiloToonURP/Editor/Volume/NiloToonMotionBlurVolumeEditor.cs
vendored
Normal file
30
Assets/External/NiloToonURP/Editor/Volume/NiloToonMotionBlurVolumeEditor.cs
vendored
Normal file
@ -0,0 +1,30 @@
|
||||
using System.Collections.Generic;
|
||||
using NiloToon.NiloToonURP;
|
||||
using UnityEditor;
|
||||
using UnityEditor.Rendering;
|
||||
|
||||
namespace NiloToon.NiloToonURP
|
||||
{
|
||||
[CanEditMultipleObjects]
|
||||
#if UNITY_2022_2_OR_NEWER
|
||||
[CustomEditor(typeof(NiloToonMotionBlurVolume))]
|
||||
#else
|
||||
[VolumeComponentEditor(typeof(NiloToonMotionBlurVolume))]
|
||||
#endif
|
||||
public class NiloToonMotionBlurVolumeEditor : NiloToonVolumeComponentEditor<NiloToonMotionBlurVolume>
|
||||
{
|
||||
// Override GetHelpBoxContent to provide specific help box content
|
||||
protected override List<string> GetHelpBoxContent()
|
||||
{
|
||||
List<string> messages = new List<string>();
|
||||
|
||||
messages.Add(
|
||||
"[Requires Unity2022.3 or above]\n" +
|
||||
"- Cinematic object motion blur, usually used for character dance animations in music videos (MVs). It is better than URP's object motion blur but comes with a much higher GPU cost.\n" +
|
||||
"- Recommended for PC/Console only");
|
||||
messages.Add(IsPostProcessMessage);
|
||||
|
||||
return messages;
|
||||
}
|
||||
}
|
||||
}
|
||||
11
Assets/External/NiloToonURP/Editor/Volume/NiloToonMotionBlurVolumeEditor.cs.meta
vendored
Normal file
11
Assets/External/NiloToonURP/Editor/Volume/NiloToonMotionBlurVolumeEditor.cs.meta
vendored
Normal file
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 2706839ba1d17584890ca7454f75e0ce
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@ -18,7 +18,12 @@ namespace NiloToon.NiloToonURP
|
||||
{
|
||||
List<string> messages = new List<string>();
|
||||
|
||||
messages.Add(NonPostProcess_NotAffectPerformance_Message);
|
||||
messages.Add(
|
||||
"- For producing NiloToon Character or Environment's screen space outline\n" +
|
||||
"- Requires enabling 'Enable ScreenSpace Outline' in NiloToonAllInOne renderer feature\n" +
|
||||
"- Requires temporal AA like TAA/STP/DLSS/XeSS/FSR... to produce stable result");
|
||||
|
||||
messages.Add(NonPostProcess_MayAffectPerformance_Message);
|
||||
|
||||
return messages;
|
||||
}
|
||||
|
||||
@ -19,8 +19,9 @@ namespace NiloToon.NiloToonURP
|
||||
List<string> messages = new List<string>();
|
||||
|
||||
messages.Add(
|
||||
"- If overridden, will use settings here instead of NiloToonAllInOneRendererFeature.\n" +
|
||||
"- If not overridden, will use NiloToonAllInOneRendererFeature's settings.");
|
||||
"- Great for controlling NiloToon characters' shadow results (e.g., shadow tint color)\n" +
|
||||
"- When overridden, uses settings from here instead of NiloToonAllInOneRendererFeature\n" +
|
||||
"- When not overridden, uses NiloToonAllInOneRendererFeature's settings");
|
||||
|
||||
messages.Add(NonPostProcess_MayAffectPerformance_Message);
|
||||
|
||||
|
||||
BIN
Assets/External/NiloToonURP/NiloToonURP user document.pdf
(Stored with Git LFS)
vendored
BIN
Assets/External/NiloToonURP/NiloToonURP user document.pdf
(Stored with Git LFS)
vendored
Binary file not shown.
@ -1,5 +1,5 @@
|
||||
fileFormatVersion: 2
|
||||
guid: a0890936ec94ed749881904e977d840d
|
||||
guid: faa27ea2c11a8a34a99a3c5a2288129b
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user