269 lines
11 KiB
C#
269 lines
11 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using System.Reflection;
|
|
using MCPForUnity.Editor.Helpers;
|
|
using MCPForUnity.Runtime.Helpers;
|
|
using Newtonsoft.Json.Linq;
|
|
using UnityEditor;
|
|
using UnityEngine;
|
|
|
|
namespace MCPForUnity.Editor.Tools.Graphics
|
|
{
|
|
internal static class GraphicsHelpers
|
|
{
|
|
private static bool? _hasVolumeSystem;
|
|
private static Type _volumeType;
|
|
private static Type _volumeProfileType;
|
|
private static Type _volumeComponentType;
|
|
private static Type _volumeParameterType;
|
|
|
|
internal static bool HasVolumeSystem
|
|
{
|
|
get
|
|
{
|
|
if (_hasVolumeSystem == null) DetectPackages();
|
|
return _hasVolumeSystem.Value;
|
|
}
|
|
}
|
|
|
|
internal static bool HasURP =>
|
|
RenderPipelineUtility.GetActivePipeline() == RenderPipelineUtility.PipelineKind.Universal;
|
|
|
|
internal static bool HasHDRP =>
|
|
RenderPipelineUtility.GetActivePipeline() == RenderPipelineUtility.PipelineKind.HighDefinition;
|
|
|
|
internal static Type VolumeType
|
|
{
|
|
get
|
|
{
|
|
if (_hasVolumeSystem == null) DetectPackages();
|
|
return _volumeType;
|
|
}
|
|
}
|
|
|
|
internal static Type VolumeProfileType
|
|
{
|
|
get
|
|
{
|
|
if (_hasVolumeSystem == null) DetectPackages();
|
|
return _volumeProfileType;
|
|
}
|
|
}
|
|
|
|
internal static Type VolumeComponentType
|
|
{
|
|
get
|
|
{
|
|
if (_hasVolumeSystem == null) DetectPackages();
|
|
return _volumeComponentType;
|
|
}
|
|
}
|
|
|
|
internal static Type VolumeParameterType
|
|
{
|
|
get
|
|
{
|
|
if (_hasVolumeSystem == null) DetectPackages();
|
|
return _volumeParameterType;
|
|
}
|
|
}
|
|
|
|
private static void DetectPackages()
|
|
{
|
|
_volumeType = Type.GetType("UnityEngine.Rendering.Volume, Unity.RenderPipelines.Core.Runtime");
|
|
_volumeProfileType = Type.GetType("UnityEngine.Rendering.VolumeProfile, Unity.RenderPipelines.Core.Runtime");
|
|
_volumeComponentType = Type.GetType("UnityEngine.Rendering.VolumeComponent, Unity.RenderPipelines.Core.Runtime");
|
|
_volumeParameterType = Type.GetType("UnityEngine.Rendering.VolumeParameter, Unity.RenderPipelines.Core.Runtime");
|
|
_hasVolumeSystem = _volumeType != null && _volumeProfileType != null;
|
|
}
|
|
|
|
internal static Type ResolveVolumeComponentType(string effectName)
|
|
{
|
|
if (string.IsNullOrEmpty(effectName) || VolumeComponentType == null)
|
|
return null;
|
|
|
|
var derivedTypes = TypeCache.GetTypesDerivedFrom(VolumeComponentType);
|
|
foreach (var t in derivedTypes)
|
|
{
|
|
if (t.IsAbstract) continue;
|
|
if (string.Equals(t.Name, effectName, StringComparison.OrdinalIgnoreCase))
|
|
return t;
|
|
}
|
|
return null;
|
|
}
|
|
|
|
internal static List<Type> GetAvailableEffectTypes()
|
|
{
|
|
if (VolumeComponentType == null)
|
|
return new List<Type>();
|
|
var derivedTypes = TypeCache.GetTypesDerivedFrom(VolumeComponentType);
|
|
return derivedTypes
|
|
.Where(t => !t.IsAbstract && !t.IsGenericType)
|
|
.OrderBy(t => t.Name)
|
|
.ToList();
|
|
}
|
|
|
|
internal static Component FindVolume(JObject @params)
|
|
{
|
|
var p = new ToolParams(@params);
|
|
string target = p.Get("target");
|
|
if (string.IsNullOrEmpty(target))
|
|
{
|
|
var allVolumes = UnityFindObjectsCompat.FindAll(VolumeType);
|
|
return allVolumes.Length > 0 ? allVolumes[0] as Component : null;
|
|
}
|
|
|
|
if (int.TryParse(target, out int instanceId))
|
|
{
|
|
var byId = GameObjectLookup.ResolveInstanceID(instanceId) as GameObject;
|
|
if (byId != null) return byId.GetComponent(VolumeType);
|
|
}
|
|
|
|
var go = GameObject.Find(target);
|
|
if (go != null) return go.GetComponent(VolumeType);
|
|
|
|
return null;
|
|
}
|
|
|
|
internal static string GetPipelineName()
|
|
{
|
|
return RenderPipelineUtility.GetActivePipeline() switch
|
|
{
|
|
RenderPipelineUtility.PipelineKind.Universal => "Universal (URP)",
|
|
RenderPipelineUtility.PipelineKind.HighDefinition => "High Definition (HDRP)",
|
|
RenderPipelineUtility.PipelineKind.BuiltIn => "Built-in",
|
|
RenderPipelineUtility.PipelineKind.Custom => "Custom",
|
|
_ => "Unknown"
|
|
};
|
|
}
|
|
|
|
internal static object ReadSerializedValue(SerializedProperty prop)
|
|
{
|
|
return prop.propertyType switch
|
|
{
|
|
SerializedPropertyType.Boolean => prop.boolValue,
|
|
SerializedPropertyType.Integer => prop.type == "long" ? prop.longValue : (object)prop.intValue,
|
|
SerializedPropertyType.Float => prop.floatValue,
|
|
SerializedPropertyType.String => prop.stringValue,
|
|
SerializedPropertyType.Enum => prop.enumValueIndex < prop.enumNames.Length
|
|
? prop.enumNames[prop.enumValueIndex]
|
|
: (object)prop.enumValueIndex,
|
|
SerializedPropertyType.ObjectReference => prop.objectReferenceValue != null
|
|
? (object)new
|
|
{
|
|
name = prop.objectReferenceValue.name,
|
|
path = AssetDatabase.GetAssetPath(prop.objectReferenceValue)
|
|
}
|
|
: null,
|
|
SerializedPropertyType.Color => new[] { prop.colorValue.r, prop.colorValue.g, prop.colorValue.b, prop.colorValue.a },
|
|
SerializedPropertyType.Vector2 => new[] { prop.vector2Value.x, prop.vector2Value.y },
|
|
SerializedPropertyType.Vector3 => new[] { prop.vector3Value.x, prop.vector3Value.y, prop.vector3Value.z },
|
|
SerializedPropertyType.LayerMask => prop.intValue,
|
|
_ => prop.propertyType.ToString()
|
|
};
|
|
}
|
|
|
|
internal static bool SetSerializedValue(SerializedProperty prop, JToken value)
|
|
{
|
|
try
|
|
{
|
|
switch (prop.propertyType)
|
|
{
|
|
case SerializedPropertyType.Boolean:
|
|
prop.boolValue = ParamCoercion.CoerceBool(value, false);
|
|
return true;
|
|
case SerializedPropertyType.Integer:
|
|
if (prop.type == "long")
|
|
prop.longValue = ParamCoercion.CoerceLong(value, 0);
|
|
else
|
|
prop.intValue = ParamCoercion.CoerceInt(value, 0);
|
|
return true;
|
|
case SerializedPropertyType.Float:
|
|
prop.floatValue = ParamCoercion.CoerceFloat(value, 0f);
|
|
return true;
|
|
case SerializedPropertyType.String:
|
|
prop.stringValue = value.ToString();
|
|
return true;
|
|
case SerializedPropertyType.Enum:
|
|
if (value.Type == JTokenType.String)
|
|
{
|
|
for (int i = 0; i < prop.enumNames.Length; i++)
|
|
{
|
|
if (string.Equals(prop.enumNames[i], value.ToString(), StringComparison.OrdinalIgnoreCase))
|
|
{ prop.enumValueIndex = i; return true; }
|
|
}
|
|
}
|
|
prop.enumValueIndex = ParamCoercion.CoerceInt(value, 0);
|
|
return true;
|
|
case SerializedPropertyType.ObjectReference:
|
|
if (value.Type == JTokenType.String)
|
|
{
|
|
string path = value.ToString();
|
|
var asset = AssetDatabase.LoadAssetAtPath<UnityEngine.Object>(path);
|
|
if (asset != null) { prop.objectReferenceValue = asset; return true; }
|
|
}
|
|
else if (value.Type == JTokenType.Object)
|
|
{
|
|
string path = value["path"]?.ToString();
|
|
if (!string.IsNullOrEmpty(path))
|
|
{
|
|
var asset = AssetDatabase.LoadAssetAtPath<UnityEngine.Object>(path);
|
|
if (asset != null) { prop.objectReferenceValue = asset; return true; }
|
|
}
|
|
}
|
|
else if (value.Type == JTokenType.Null)
|
|
{
|
|
prop.objectReferenceValue = null;
|
|
return true;
|
|
}
|
|
return false;
|
|
case SerializedPropertyType.Color:
|
|
if (value is JArray colorArr && colorArr.Count >= 3)
|
|
{
|
|
prop.colorValue = new Color(
|
|
(float)colorArr[0], (float)colorArr[1], (float)colorArr[2],
|
|
colorArr.Count >= 4 ? (float)colorArr[3] : 1f);
|
|
return true;
|
|
}
|
|
return false;
|
|
case SerializedPropertyType.Vector2:
|
|
if (value is JArray v2Arr && v2Arr.Count >= 2)
|
|
{
|
|
prop.vector2Value = new Vector2((float)v2Arr[0], (float)v2Arr[1]);
|
|
return true;
|
|
}
|
|
return false;
|
|
case SerializedPropertyType.Vector3:
|
|
if (value is JArray v3Arr && v3Arr.Count >= 3)
|
|
{
|
|
prop.vector3Value = new Vector3((float)v3Arr[0], (float)v3Arr[1], (float)v3Arr[2]);
|
|
return true;
|
|
}
|
|
return false;
|
|
case SerializedPropertyType.LayerMask:
|
|
prop.intValue = ParamCoercion.CoerceInt(value, 0);
|
|
return true;
|
|
default:
|
|
return false;
|
|
}
|
|
}
|
|
catch { return false; }
|
|
}
|
|
|
|
internal static void MarkDirty(UnityEngine.Object obj)
|
|
{
|
|
if (obj == null) return;
|
|
EditorUtility.SetDirty(obj);
|
|
if (obj is Component comp)
|
|
{
|
|
var prefabStage = UnityEditor.SceneManagement.PrefabStageUtility.GetCurrentPrefabStage();
|
|
if (prefabStage != null)
|
|
UnityEditor.SceneManagement.EditorSceneManager.MarkSceneDirty(prefabStage.scene);
|
|
else
|
|
UnityEditor.SceneManagement.EditorSceneManager.MarkSceneDirty(comp.gameObject.scene);
|
|
}
|
|
}
|
|
}
|
|
}
|