浏览代码
Merge remote-tracking branch 'origin/master' into hdrp-xr-lighting
Merge remote-tracking branch 'origin/master' into hdrp-xr-lighting
Manual fixup of some LightLoop stuff (stereo + decals living together in light cull data)/main
Robert Srinivasiah
7 年前
当前提交
6f2b52f2
共有 240 个文件被更改,包括 4561 次插入 和 806 次删除
-
2.gitmodules
-
15ScriptableRenderPipeline/Core/CoreRP/Camera/CameraSwitcher.cs
-
2ScriptableRenderPipeline/Core/CoreRP/Camera/FreeCamera.cs
-
4ScriptableRenderPipeline/Core/CoreRP/ShaderLibrary/Sampling/Fibonacci.hlsl
-
34ScriptableRenderPipeline/Core/CoreRP/Shadow/Shadow.cs
-
10ScriptableRenderPipeline/Core/CoreRP/Shadow/ShadowBase.cs
-
4ScriptableRenderPipeline/Core/CoreRP/TextureCache.cs
-
2ScriptableRenderPipeline/Core/package.json
-
7ScriptableRenderPipeline/HDRenderPipeline/HDRP/Camera/HDCamera.cs
-
7ScriptableRenderPipeline/HDRenderPipeline/HDRP/Debug/ColorPickerDebug.cs
-
369ScriptableRenderPipeline/HDRenderPipeline/HDRP/Debug/DebugDisplay.cs
-
10ScriptableRenderPipeline/HDRenderPipeline/HDRP/Debug/LightingDebug.cs
-
658ScriptableRenderPipeline/HDRenderPipeline/HDRP/Debug/MaterialDebug.cs
-
371ScriptableRenderPipeline/HDRenderPipeline/HDRP/Decal/DecalSystem.cs
-
12ScriptableRenderPipeline/HDRenderPipeline/HDRP/Editor/HDAssetFactory.cs
-
20ScriptableRenderPipeline/HDRenderPipeline/HDRP/Editor/Lighting/HDLightEditor.Styles.cs
-
18ScriptableRenderPipeline/HDRenderPipeline/HDRP/Editor/Lighting/HDLightEditor.cs
-
14ScriptableRenderPipeline/HDRenderPipeline/HDRP/Editor/Lighting/Reflection/HDReflectionProbeEditorUtility.cs
-
1ScriptableRenderPipeline/HDRenderPipeline/HDRP/Editor/RenderLoopSettings/RenderPipelineSettingsUI.cs
-
2ScriptableRenderPipeline/HDRenderPipeline/HDRP/Editor/RenderLoopSettings/SerializedRenderPipelineSettings.cs
-
3ScriptableRenderPipeline/HDRenderPipeline/HDRP/HDCustomSamplerId.cs
-
50ScriptableRenderPipeline/HDRenderPipeline/HDRP/HDRenderPipeline.cs
-
12ScriptableRenderPipeline/HDRenderPipeline/HDRP/HDRenderPipelineAsset.asset
-
8ScriptableRenderPipeline/HDRenderPipeline/HDRP/HDStringConstants.cs
-
2ScriptableRenderPipeline/HDRenderPipeline/HDRP/Lighting/Light/HDAdditionalShadowData.cs
-
63ScriptableRenderPipeline/HDRenderPipeline/HDRP/Lighting/LightLoop/LightLoop.cs
-
3ScriptableRenderPipeline/HDRenderPipeline/HDRP/Lighting/LightLoop/LightLoop.cs.hlsl
-
41ScriptableRenderPipeline/HDRenderPipeline/HDRP/Lighting/LightLoop/LightLoopSettings.cs
-
1ScriptableRenderPipeline/HDRenderPipeline/HDRP/Lighting/LightLoop/lightlistbuild-bigtile.compute
-
4ScriptableRenderPipeline/HDRenderPipeline/HDRP/Lighting/LightLoop/lightlistbuild-clustered.compute
-
4ScriptableRenderPipeline/HDRenderPipeline/HDRP/Lighting/LightLoop/lightlistbuild.compute
-
10ScriptableRenderPipeline/HDRenderPipeline/HDRP/Lighting/Reflection/PlanarReflectionProbeCache.cs
-
17ScriptableRenderPipeline/HDRenderPipeline/HDRP/Lighting/Reflection/ReflectionProbeCache.cs
-
11ScriptableRenderPipeline/HDRenderPipeline/HDRP/Material/Decal/Decal.cs
-
16ScriptableRenderPipeline/HDRenderPipeline/HDRP/Material/Decal/Decal.cs.hlsl
-
10ScriptableRenderPipeline/HDRenderPipeline/HDRP/Material/Decal/Decal.hlsl
-
7ScriptableRenderPipeline/HDRenderPipeline/HDRP/Material/Decal/DecalData.hlsl
-
96ScriptableRenderPipeline/HDRenderPipeline/HDRP/Material/Decal/DecalUtilities.hlsl
-
4ScriptableRenderPipeline/HDRenderPipeline/HDRP/Material/DiffusionProfile/DiffusionProfileSettings.cs
-
3ScriptableRenderPipeline/HDRenderPipeline/HDRP/Material/LayeredLit/LayeredLit.shader
-
2ScriptableRenderPipeline/HDRenderPipeline/HDRP/Material/LayeredLit/LayeredLitData.hlsl
-
3ScriptableRenderPipeline/HDRenderPipeline/HDRP/Material/LayeredLit/LayeredLitTessellation.shader
-
3ScriptableRenderPipeline/HDRenderPipeline/HDRP/Material/Lit/Lit.shader
-
2ScriptableRenderPipeline/HDRenderPipeline/HDRP/Material/Lit/LitData.hlsl
-
3ScriptableRenderPipeline/HDRenderPipeline/HDRP/Material/Lit/LitTessellation.shader
-
65ScriptableRenderPipeline/HDRenderPipeline/HDRP/Material/SubsurfaceScattering/SubsurfaceScattering.compute
-
9ScriptableRenderPipeline/HDRenderPipeline/HDRP/Material/SubsurfaceScattering/SubsurfaceScatteringManager.cs
-
3ScriptableRenderPipeline/HDRenderPipeline/HDRP/Material/Unlit/Unlit.shader
-
129ScriptableRenderPipeline/HDRenderPipeline/HDRP/RenderPipeline/FrameSettings.cs
-
1ScriptableRenderPipeline/HDRenderPipeline/HDRP/RenderPipeline/RenderPipelineSettings.cs
-
6ScriptableRenderPipeline/HDRenderPipeline/HDRP/RenderPipelineResources/HDRenderPipelineResources.asset
-
9ScriptableRenderPipeline/HDRenderPipeline/HDRP/RenderPipelineResources/RenderPipelineResources.cs
-
2ScriptableRenderPipeline/HDRenderPipeline/HDRP/ShaderPass/ShaderPassDBuffer.hlsl
-
4ScriptableRenderPipeline/HDRenderPipeline/package.json
-
4ScriptableRenderPipeline/LightweightPipeline/package.json
-
2ScriptableRenderPipeline/master-package.json
-
2Tests/GraphicsTests/RenderPipeline/HDRenderPipeline/CommonAssets/RP_Assets/HDRP_Test_Def.asset
-
4ScriptableRenderPipeline/Core/CoreRP/Shadow/ShadowBlurMoments.compute
-
8ScriptableRenderPipeline/Core/CoreRP/CoreResources.meta
-
289ScriptableRenderPipeline/Core/CoreRP/Debugging/DebugManager.Actions.cs
-
11ScriptableRenderPipeline/Core/CoreRP/Debugging/DebugManager.Actions.cs.meta
-
231ScriptableRenderPipeline/Core/CoreRP/Debugging/DebugManager.cs
-
11ScriptableRenderPipeline/Core/CoreRP/Debugging/DebugManager.cs.meta
-
127ScriptableRenderPipeline/Core/CoreRP/Debugging/DebugUI.Containers.cs
-
11ScriptableRenderPipeline/Core/CoreRP/Debugging/DebugUI.Containers.cs.meta
-
180ScriptableRenderPipeline/Core/CoreRP/Debugging/DebugUI.Fields.cs
-
11ScriptableRenderPipeline/Core/CoreRP/Debugging/DebugUI.Fields.cs.meta
-
70ScriptableRenderPipeline/Core/CoreRP/Debugging/DebugUI.Panel.cs
-
11ScriptableRenderPipeline/Core/CoreRP/Debugging/DebugUI.Panel.cs.meta
-
99ScriptableRenderPipeline/Core/CoreRP/Debugging/DebugUI.cs
-
11ScriptableRenderPipeline/Core/CoreRP/Debugging/DebugUI.cs.meta
-
24ScriptableRenderPipeline/Core/CoreRP/Debugging/DebugUpdater.cs
-
11ScriptableRenderPipeline/Core/CoreRP/Debugging/DebugUpdater.cs.meta
-
8ScriptableRenderPipeline/Core/CoreRP/Debugging/Prefabs.meta
-
8ScriptableRenderPipeline/Core/CoreRP/Editor/CoreResources.meta
-
97ScriptableRenderPipeline/Core/CoreRP/Editor/Debugging/DebugState.cs
-
11ScriptableRenderPipeline/Core/CoreRP/Editor/Debugging/DebugState.cs.meta
-
304ScriptableRenderPipeline/Core/CoreRP/Editor/Debugging/DebugUIDrawer.Builtins.cs
-
11ScriptableRenderPipeline/Core/CoreRP/Editor/Debugging/DebugUIDrawer.Builtins.cs.meta
-
62ScriptableRenderPipeline/Core/CoreRP/Editor/Debugging/DebugUIDrawer.cs
-
11ScriptableRenderPipeline/Core/CoreRP/Editor/Debugging/DebugUIDrawer.cs.meta
-
78ScriptableRenderPipeline/Core/CoreRP/Editor/Debugging/DebugUIHandlerCanvasEditor.cs
-
11ScriptableRenderPipeline/Core/CoreRP/Editor/Debugging/DebugUIHandlerCanvasEditor.cs.meta
-
438ScriptableRenderPipeline/Core/CoreRP/Editor/Debugging/DebugWindow.cs
-
11ScriptableRenderPipeline/Core/CoreRP/Editor/Debugging/DebugWindow.cs.meta
-
34ScriptableRenderPipeline/Core/CoreRP/Editor/Debugging/UIFoldoutEditor.cs
-
11ScriptableRenderPipeline/Core/CoreRP/Editor/Debugging/UIFoldoutEditor.cs.meta
-
146ScriptableRenderPipeline/Core/CoreRP/ObservableList.cs
-
11ScriptableRenderPipeline/Core/CoreRP/ObservableList.cs.meta
-
43ScriptableRenderPipeline/Core/CoreRP/SerializedDictionary.cs
-
11ScriptableRenderPipeline/Core/CoreRP/SerializedDictionary.cs.meta
-
8ScriptableRenderPipeline/Core/CoreRP/Debugging/Prefabs/Fonts.meta
-
564ScriptableRenderPipeline/Core/CoreRP/Debugging/Prefabs/Fonts/Perfect DOS VGA 437.ttf
-
22ScriptableRenderPipeline/Core/CoreRP/Debugging/Prefabs/Fonts/Perfect DOS VGA 437.ttf.meta
-
8ScriptableRenderPipeline/Core/CoreRP/Debugging/Prefabs/Resources.meta
-
166ScriptableRenderPipeline/Core/CoreRP/Debugging/Prefabs/Resources/DebugUI Canvas.prefab
-
8ScriptableRenderPipeline/Core/CoreRP/Debugging/Prefabs/Resources/DebugUI Canvas.prefab.meta
|
|||
{ |
|||
"name": "com.unity.render-pipelines.core", |
|||
"description": "Core library for Unity render pipelines.", |
|||
"version": "0.1.30", |
|||
"version": "0.1.32", |
|||
"unity": "2018.1", |
|||
"dependencies": { |
|||
"com.unity.postprocessing": "0.1.8" |
|
|||
using System.Collections.Generic; |
|||
using UnityEngine; |
|||
using System; |
|||
|
|||
namespace UnityEngine.Experimental.Rendering.HDPipeline |
|||
{ |
|||
namespace Attributes |
|||
{ |
|||
// 0 is reserved!
|
|||
[GenerateHLSL] |
|||
public enum DebugViewVarying |
|||
{ |
|||
None = 0, |
|||
Texcoord0 = 1, |
|||
Texcoord1, |
|||
Texcoord2, |
|||
Texcoord3, |
|||
VertexTangentWS, |
|||
VertexBitangentWS, |
|||
VertexNormalWS, |
|||
VertexColor, |
|||
VertexColorAlpha, |
|||
Last, |
|||
}; |
|||
|
|||
// Number must be contiguous
|
|||
[GenerateHLSL] |
|||
public enum DebugViewGbuffer |
|||
{ |
|||
None = 0, |
|||
Depth = DebugViewVarying.Last, |
|||
BakeDiffuseLightingWithAlbedoPlusEmissive, |
|||
BakeShadowMask0, |
|||
BakeShadowMask1, |
|||
BakeShadowMask2, |
|||
BakeShadowMask3, |
|||
Last, |
|||
} |
|||
|
|||
// Number must be contiguous
|
|||
[GenerateHLSL] |
|||
public enum DebugViewProperties |
|||
{ |
|||
None = 0, |
|||
Tessellation = DebugViewGbuffer.Last, |
|||
PixelDisplacement, |
|||
VertexDisplacement, |
|||
TessellationDisplacement, |
|||
DepthOffset, |
|||
Lightmap, |
|||
Instancing, |
|||
Last, |
|||
} |
|||
} |
|||
|
|||
[Serializable] |
|||
public class MaterialDebugSettings |
|||
{ |
|||
private static bool isDebugViewMaterialInit = false; |
|||
|
|||
public static GUIContent[] debugViewMaterialStrings = null; |
|||
public static int[] debugViewMaterialValues = null; |
|||
public static GUIContent[] debugViewEngineStrings = null; |
|||
public static int[] debugViewEngineValues = null; |
|||
public static GUIContent[] debugViewMaterialVaryingStrings = null; |
|||
public static int[] debugViewMaterialVaryingValues = null; |
|||
public static GUIContent[] debugViewMaterialPropertiesStrings = null; |
|||
public static int[] debugViewMaterialPropertiesValues = null; |
|||
public static GUIContent[] debugViewMaterialTextureStrings = null; |
|||
public static int[] debugViewMaterialTextureValues = null; |
|||
public static GUIContent[] debugViewMaterialGBufferStrings = null; |
|||
public static int[] debugViewMaterialGBufferValues = null; |
|||
|
|||
public MaterialDebugSettings() |
|||
{ |
|||
BuildDebugRepresentation(); |
|||
} |
|||
|
|||
// className include the additional "/"
|
|||
void FillWithProperties(Type type, ref List<GUIContent> debugViewMaterialStringsList, ref List<int> debugViewMaterialValuesList, string className) |
|||
{ |
|||
var attributes = type.GetCustomAttributes(true); |
|||
// Get attribute to get the start number of the value for the enum
|
|||
var attr = attributes[0] as GenerateHLSL; |
|||
|
|||
if (!attr.needParamDebug) |
|||
{ |
|||
return; |
|||
} |
|||
|
|||
var fields = type.GetFields(); |
|||
|
|||
var localIndex = 0; |
|||
foreach (var field in fields) |
|||
{ |
|||
// Note: One field can have multiple name. This is to allow to have different debug view mode for the same field
|
|||
// like for example display normal in world space or in view space. Same field but two different modes.
|
|||
List<String> displayNames = new List<string>(); |
|||
displayNames.Add(field.Name); |
|||
|
|||
// Check if the display name have been override by the users
|
|||
if (Attribute.IsDefined(field, typeof(SurfaceDataAttributes))) |
|||
{ |
|||
var propertyAttr = (SurfaceDataAttributes[])field.GetCustomAttributes(typeof(SurfaceDataAttributes), false); |
|||
if (propertyAttr[0].displayNames.Length > 0 && propertyAttr[0].displayNames[0] != "") |
|||
{ |
|||
displayNames.Clear(); |
|||
|
|||
displayNames.AddRange(propertyAttr[0].displayNames); |
|||
} |
|||
} |
|||
|
|||
foreach (string fieldName in displayNames) |
|||
{ |
|||
debugViewMaterialStringsList.Add(new GUIContent(className + fieldName)); |
|||
debugViewMaterialValuesList.Add(attr.paramDefinesStart + (int)localIndex); |
|||
localIndex++; |
|||
} |
|||
} |
|||
} |
|||
|
|||
void FillWithPropertiesEnum(Type type, ref List<GUIContent> debugViewMaterialStringsList, ref List<int> debugViewMaterialValuesList, string prefix) |
|||
{ |
|||
var names = Enum.GetNames(type); |
|||
|
|||
var localIndex = 0; |
|||
foreach (var value in Enum.GetValues(type)) |
|||
{ |
|||
var valueName = prefix + names[localIndex]; |
|||
|
|||
debugViewMaterialStringsList.Add(new GUIContent(valueName)); |
|||
debugViewMaterialValuesList.Add((int)value); |
|||
localIndex++; |
|||
} |
|||
} |
|||
|
|||
public class MaterialItem |
|||
{ |
|||
public String className; |
|||
public Type surfaceDataType; |
|||
public Type bsdfDataType; |
|||
}; |
|||
|
|||
void BuildDebugRepresentation() |
|||
{ |
|||
if (!isDebugViewMaterialInit) |
|||
{ |
|||
List<RenderPipelineMaterial> materialList = HDUtils.GetRenderPipelineMaterialList(); |
|||
|
|||
// TODO: Share this code to retrieve deferred material with HDRenderPipeline
|
|||
// Find first material that have non 0 Gbuffer count and assign it as deferredMaterial
|
|||
Type bsdfDataDeferredType = null; |
|||
foreach (RenderPipelineMaterial material in materialList) |
|||
{ |
|||
if (material.GetMaterialGBufferCount() > 0) |
|||
{ |
|||
bsdfDataDeferredType = material.GetType().GetNestedType("BSDFData"); |
|||
} |
|||
} |
|||
|
|||
// TODO: Handle the case of no Gbuffer material
|
|||
Debug.Assert(bsdfDataDeferredType != null); |
|||
|
|||
List<MaterialItem> materialItems = new List<MaterialItem>(); |
|||
|
|||
int numSurfaceDataFields = 0; |
|||
int numBSDFDataFields = 0; |
|||
foreach (RenderPipelineMaterial material in materialList) |
|||
{ |
|||
MaterialItem item = new MaterialItem(); |
|||
|
|||
item.className = material.GetType().Name + "/"; |
|||
|
|||
item.surfaceDataType = material.GetType().GetNestedType("SurfaceData"); |
|||
numSurfaceDataFields += item.surfaceDataType.GetFields().Length; |
|||
|
|||
item.bsdfDataType = material.GetType().GetNestedType("BSDFData"); |
|||
numBSDFDataFields += item.bsdfDataType.GetFields().Length; |
|||
|
|||
materialItems.Add(item); |
|||
} |
|||
|
|||
// Init list
|
|||
List<GUIContent> debugViewMaterialStringsList = new List<GUIContent>(); |
|||
List<int> debugViewMaterialValuesList = new List<int>(); |
|||
List<GUIContent> debugViewEngineStringsList = new List<GUIContent>(); |
|||
List<int> debugViewEngineValuesList = new List<int>(); |
|||
List<GUIContent> debugViewMaterialVaryingStringsList = new List<GUIContent>(); |
|||
List<int> debugViewMaterialVaryingValuesList = new List<int>(); |
|||
List<GUIContent> debugViewMaterialPropertiesStringsList = new List<GUIContent>(); |
|||
List<int> debugViewMaterialPropertiesValuesList = new List<int>(); |
|||
List<GUIContent> debugViewMaterialTextureStringsList = new List<GUIContent>(); |
|||
List<int> debugViewMaterialTextureValuesList = new List<int>(); |
|||
List<GUIContent> debugViewMaterialGBufferStringsList = new List<GUIContent>(); |
|||
List<int> debugViewMaterialGBufferValuesList = new List<int>(); |
|||
|
|||
// First element is a reserved location and should not be used (allow to track error)
|
|||
// Special case for None since it cannot be inferred from SurfaceData/BuiltinData
|
|||
debugViewMaterialStringsList.Add(new GUIContent("None")); |
|||
debugViewMaterialValuesList.Add(0); |
|||
|
|||
foreach (MaterialItem item in materialItems) |
|||
{ |
|||
// BuiltinData are duplicated for each material
|
|||
FillWithProperties(typeof(Builtin.BuiltinData), ref debugViewMaterialStringsList, ref debugViewMaterialValuesList, item.className); |
|||
FillWithProperties(item.surfaceDataType, ref debugViewMaterialStringsList, ref debugViewMaterialValuesList, item.className); |
|||
} |
|||
|
|||
// Engine properties debug
|
|||
// First element is a reserved location and should not be used (allow to track error)
|
|||
// Special case for None since it cannot be inferred from SurfaceData/BuiltinData
|
|||
debugViewEngineStringsList.Add(new GUIContent("None")); |
|||
debugViewEngineValuesList.Add(0); |
|||
|
|||
foreach (MaterialItem item in materialItems) |
|||
{ |
|||
FillWithProperties(item.bsdfDataType, ref debugViewEngineStringsList, ref debugViewEngineValuesList, item.className); |
|||
} |
|||
|
|||
// For the following, no need to reserve the 0 case as it is handled in the Enum
|
|||
|
|||
// Attributes debug
|
|||
FillWithPropertiesEnum(typeof(Attributes.DebugViewVarying), ref debugViewMaterialVaryingStringsList, ref debugViewMaterialVaryingValuesList, ""); |
|||
|
|||
// Properties debug
|
|||
FillWithPropertiesEnum(typeof(Attributes.DebugViewProperties), ref debugViewMaterialPropertiesStringsList, ref debugViewMaterialPropertiesValuesList, ""); |
|||
|
|||
// Gbuffer debug
|
|||
FillWithPropertiesEnum(typeof(Attributes.DebugViewGbuffer), ref debugViewMaterialGBufferStringsList, ref debugViewMaterialGBufferValuesList, ""); |
|||
FillWithProperties(typeof(Lit.BSDFData), ref debugViewMaterialGBufferStringsList, ref debugViewMaterialGBufferValuesList, ""); |
|||
|
|||
// Convert to array for UI
|
|||
debugViewMaterialStrings = debugViewMaterialStringsList.ToArray(); |
|||
debugViewMaterialValues = debugViewMaterialValuesList.ToArray(); |
|||
|
|||
debugViewEngineStrings = debugViewEngineStringsList.ToArray(); |
|||
debugViewEngineValues = debugViewEngineValuesList.ToArray(); |
|||
|
|||
debugViewMaterialVaryingStrings = debugViewMaterialVaryingStringsList.ToArray(); |
|||
debugViewMaterialVaryingValues = debugViewMaterialVaryingValuesList.ToArray(); |
|||
|
|||
debugViewMaterialPropertiesStrings = debugViewMaterialPropertiesStringsList.ToArray(); |
|||
debugViewMaterialPropertiesValues = debugViewMaterialPropertiesValuesList.ToArray(); |
|||
|
|||
debugViewMaterialTextureStrings = debugViewMaterialTextureStringsList.ToArray(); |
|||
debugViewMaterialTextureValues = debugViewMaterialTextureValuesList.ToArray(); |
|||
|
|||
debugViewMaterialGBufferStrings = debugViewMaterialGBufferStringsList.ToArray(); |
|||
debugViewMaterialGBufferValues = debugViewMaterialGBufferValuesList.ToArray(); |
|||
|
|||
isDebugViewMaterialInit = true; |
|||
} |
|||
} |
|||
|
|||
public int debugViewMaterial { get { return m_DebugViewMaterial; } } |
|||
public int debugViewEngine { get { return m_DebugViewEngine; } } |
|||
public Attributes.DebugViewVarying debugViewVarying { get { return m_DebugViewVarying; } } |
|||
public Attributes.DebugViewProperties debugViewProperties { get { return m_DebugViewProperties; } } |
|||
public int debugViewGBuffer { get { return m_DebugViewGBuffer; } } |
|||
|
|||
int m_DebugViewMaterial = 0; // No enum there because everything is generated from materials.
|
|||
int m_DebugViewEngine = 0; // No enum there because everything is generated from BSDFData
|
|||
Attributes.DebugViewVarying m_DebugViewVarying = Attributes.DebugViewVarying.None; |
|||
Attributes.DebugViewProperties m_DebugViewProperties = Attributes.DebugViewProperties.None; |
|||
int m_DebugViewGBuffer = 0; // Can't use GBuffer enum here because the values are actually split between this enum and values from Lit.BSDFData
|
|||
|
|||
public int GetDebugMaterialIndex() |
|||
{ |
|||
// This value is used in the shader for the actual debug display.
|
|||
// There is only one uniform parameter for that so we just add all of them
|
|||
// They are all mutually exclusive so return the sum will return the right index.
|
|||
return m_DebugViewGBuffer + m_DebugViewMaterial + m_DebugViewEngine + (int)m_DebugViewVarying + (int)m_DebugViewProperties; |
|||
} |
|||
|
|||
public void DisableMaterialDebug() |
|||
{ |
|||
m_DebugViewMaterial = 0; |
|||
m_DebugViewEngine = 0; |
|||
m_DebugViewVarying = Attributes.DebugViewVarying.None; |
|||
m_DebugViewProperties = Attributes.DebugViewProperties.None; |
|||
m_DebugViewGBuffer = 0; |
|||
} |
|||
|
|||
public void SetDebugViewMaterial(int value) |
|||
{ |
|||
if (value != 0) |
|||
DisableMaterialDebug(); |
|||
m_DebugViewMaterial = value; |
|||
} |
|||
|
|||
public void SetDebugViewEngine(int value) |
|||
{ |
|||
if (value != 0) |
|||
DisableMaterialDebug(); |
|||
m_DebugViewEngine = value; |
|||
} |
|||
|
|||
public void SetDebugViewVarying(Attributes.DebugViewVarying value) |
|||
{ |
|||
if (value != 0) |
|||
DisableMaterialDebug(); |
|||
m_DebugViewVarying = value; |
|||
} |
|||
public void SetDebugViewProperties(Attributes.DebugViewProperties value) |
|||
{ |
|||
if (value != 0) |
|||
DisableMaterialDebug(); |
|||
m_DebugViewProperties = value; |
|||
} |
|||
|
|||
public void SetDebugViewGBuffer(int value) |
|||
{ |
|||
if (value != 0) |
|||
DisableMaterialDebug(); |
|||
m_DebugViewGBuffer = value; |
|||
} |
|||
|
|||
|
|||
public bool IsDebugGBufferEnabled() |
|||
{ |
|||
return m_DebugViewGBuffer != 0; |
|||
} |
|||
|
|||
public bool IsDebugDisplayEnabled() |
|||
{ |
|||
return (m_DebugViewEngine != 0 || m_DebugViewMaterial != 0 || m_DebugViewVarying != Attributes.DebugViewVarying.None || m_DebugViewProperties != Attributes.DebugViewProperties.None || m_DebugViewGBuffer != 0); |
|||
} |
|||
} |
|||
} |
|||
using System.Collections.Generic; |
|||
using System; |
|||
using UnityEngine.Experimental.Rendering.HDPipeline.Attributes; |
|||
|
|||
namespace UnityEngine.Experimental.Rendering.HDPipeline |
|||
{ |
|||
namespace Attributes |
|||
{ |
|||
// 0 is reserved!
|
|||
[GenerateHLSL] |
|||
public enum DebugViewVarying |
|||
{ |
|||
None = 0, |
|||
Texcoord0 = 1, |
|||
Texcoord1, |
|||
Texcoord2, |
|||
Texcoord3, |
|||
VertexTangentWS, |
|||
VertexBitangentWS, |
|||
VertexNormalWS, |
|||
VertexColor, |
|||
VertexColorAlpha, |
|||
Last, |
|||
}; |
|||
|
|||
// Number must be contiguous
|
|||
[GenerateHLSL] |
|||
public enum DebugViewGbuffer |
|||
{ |
|||
None = 0, |
|||
Depth = DebugViewVarying.Last, |
|||
BakeDiffuseLightingWithAlbedoPlusEmissive, |
|||
BakeShadowMask0, |
|||
BakeShadowMask1, |
|||
BakeShadowMask2, |
|||
BakeShadowMask3, |
|||
Last, |
|||
} |
|||
|
|||
// Number must be contiguous
|
|||
[GenerateHLSL] |
|||
public enum DebugViewProperties |
|||
{ |
|||
None = 0, |
|||
Tessellation = DebugViewGbuffer.Last, |
|||
PixelDisplacement, |
|||
VertexDisplacement, |
|||
TessellationDisplacement, |
|||
DepthOffset, |
|||
Lightmap, |
|||
Instancing, |
|||
Last, |
|||
} |
|||
} |
|||
|
|||
[Serializable] |
|||
public class MaterialDebugSettings |
|||
{ |
|||
static bool isDebugViewMaterialInit = false; |
|||
|
|||
public static GUIContent[] debugViewMaterialStrings = null; |
|||
public static int[] debugViewMaterialValues = null; |
|||
public static GUIContent[] debugViewEngineStrings = null; |
|||
public static int[] debugViewEngineValues = null; |
|||
public static GUIContent[] debugViewMaterialVaryingStrings = null; |
|||
public static int[] debugViewMaterialVaryingValues = null; |
|||
public static GUIContent[] debugViewMaterialPropertiesStrings = null; |
|||
public static int[] debugViewMaterialPropertiesValues = null; |
|||
public static GUIContent[] debugViewMaterialTextureStrings = null; |
|||
public static int[] debugViewMaterialTextureValues = null; |
|||
public static GUIContent[] debugViewMaterialGBufferStrings = null; |
|||
public static int[] debugViewMaterialGBufferValues = null; |
|||
|
|||
public MaterialDebugSettings() |
|||
{ |
|||
BuildDebugRepresentation(); |
|||
} |
|||
|
|||
// className include the additional "/"
|
|||
void FillWithProperties(Type type, ref List<GUIContent> debugViewMaterialStringsList, ref List<int> debugViewMaterialValuesList, string className) |
|||
{ |
|||
var attributes = type.GetCustomAttributes(true); |
|||
// Get attribute to get the start number of the value for the enum
|
|||
var attr = attributes[0] as GenerateHLSL; |
|||
|
|||
if (!attr.needParamDebug) |
|||
{ |
|||
return; |
|||
} |
|||
|
|||
var fields = type.GetFields(); |
|||
|
|||
var localIndex = 0; |
|||
foreach (var field in fields) |
|||
{ |
|||
// Note: One field can have multiple name. This is to allow to have different debug view mode for the same field
|
|||
// like for example display normal in world space or in view space. Same field but two different modes.
|
|||
List<String> displayNames = new List<string>(); |
|||
displayNames.Add(field.Name); |
|||
|
|||
// Check if the display name have been override by the users
|
|||
if (Attribute.IsDefined(field, typeof(SurfaceDataAttributes))) |
|||
{ |
|||
var propertyAttr = (SurfaceDataAttributes[])field.GetCustomAttributes(typeof(SurfaceDataAttributes), false); |
|||
if (propertyAttr[0].displayNames.Length > 0 && propertyAttr[0].displayNames[0] != "") |
|||
{ |
|||
displayNames.Clear(); |
|||
|
|||
displayNames.AddRange(propertyAttr[0].displayNames); |
|||
} |
|||
} |
|||
|
|||
foreach (string fieldName in displayNames) |
|||
{ |
|||
debugViewMaterialStringsList.Add(new GUIContent(className + fieldName)); |
|||
debugViewMaterialValuesList.Add(attr.paramDefinesStart + (int)localIndex); |
|||
localIndex++; |
|||
} |
|||
} |
|||
} |
|||
|
|||
void FillWithPropertiesEnum(Type type, ref List<GUIContent> debugViewMaterialStringsList, ref List<int> debugViewMaterialValuesList, string prefix) |
|||
{ |
|||
var names = Enum.GetNames(type); |
|||
|
|||
var localIndex = 0; |
|||
foreach (var value in Enum.GetValues(type)) |
|||
{ |
|||
var valueName = prefix + names[localIndex]; |
|||
|
|||
debugViewMaterialStringsList.Add(new GUIContent(valueName)); |
|||
debugViewMaterialValuesList.Add((int)value); |
|||
localIndex++; |
|||
} |
|||
} |
|||
|
|||
public class MaterialItem |
|||
{ |
|||
public String className; |
|||
public Type surfaceDataType; |
|||
public Type bsdfDataType; |
|||
}; |
|||
|
|||
void BuildDebugRepresentation() |
|||
{ |
|||
if (!isDebugViewMaterialInit) |
|||
{ |
|||
List<RenderPipelineMaterial> materialList = HDUtils.GetRenderPipelineMaterialList(); |
|||
|
|||
// TODO: Share this code to retrieve deferred material with HDRenderPipeline
|
|||
// Find first material that have non 0 Gbuffer count and assign it as deferredMaterial
|
|||
Type bsdfDataDeferredType = null; |
|||
foreach (RenderPipelineMaterial material in materialList) |
|||
{ |
|||
if (material.GetMaterialGBufferCount() > 0) |
|||
{ |
|||
bsdfDataDeferredType = material.GetType().GetNestedType("BSDFData"); |
|||
} |
|||
} |
|||
|
|||
// TODO: Handle the case of no Gbuffer material
|
|||
Debug.Assert(bsdfDataDeferredType != null); |
|||
|
|||
List<MaterialItem> materialItems = new List<MaterialItem>(); |
|||
|
|||
int numSurfaceDataFields = 0; |
|||
int numBSDFDataFields = 0; |
|||
foreach (RenderPipelineMaterial material in materialList) |
|||
{ |
|||
MaterialItem item = new MaterialItem(); |
|||
|
|||
item.className = material.GetType().Name + "/"; |
|||
|
|||
item.surfaceDataType = material.GetType().GetNestedType("SurfaceData"); |
|||
numSurfaceDataFields += item.surfaceDataType.GetFields().Length; |
|||
|
|||
item.bsdfDataType = material.GetType().GetNestedType("BSDFData"); |
|||
numBSDFDataFields += item.bsdfDataType.GetFields().Length; |
|||
|
|||
materialItems.Add(item); |
|||
} |
|||
|
|||
// Init list
|
|||
List<GUIContent> debugViewMaterialStringsList = new List<GUIContent>(); |
|||
List<int> debugViewMaterialValuesList = new List<int>(); |
|||
List<GUIContent> debugViewEngineStringsList = new List<GUIContent>(); |
|||
List<int> debugViewEngineValuesList = new List<int>(); |
|||
List<GUIContent> debugViewMaterialVaryingStringsList = new List<GUIContent>(); |
|||
List<int> debugViewMaterialVaryingValuesList = new List<int>(); |
|||
List<GUIContent> debugViewMaterialPropertiesStringsList = new List<GUIContent>(); |
|||
List<int> debugViewMaterialPropertiesValuesList = new List<int>(); |
|||
List<GUIContent> debugViewMaterialTextureStringsList = new List<GUIContent>(); |
|||
List<int> debugViewMaterialTextureValuesList = new List<int>(); |
|||
List<GUIContent> debugViewMaterialGBufferStringsList = new List<GUIContent>(); |
|||
List<int> debugViewMaterialGBufferValuesList = new List<int>(); |
|||
|
|||
// First element is a reserved location and should not be used (allow to track error)
|
|||
// Special case for None since it cannot be inferred from SurfaceData/BuiltinData
|
|||
debugViewMaterialStringsList.Add(new GUIContent("None")); |
|||
debugViewMaterialValuesList.Add(0); |
|||
|
|||
foreach (MaterialItem item in materialItems) |
|||
{ |
|||
// BuiltinData are duplicated for each material
|
|||
FillWithProperties(typeof(Builtin.BuiltinData), ref debugViewMaterialStringsList, ref debugViewMaterialValuesList, item.className); |
|||
FillWithProperties(item.surfaceDataType, ref debugViewMaterialStringsList, ref debugViewMaterialValuesList, item.className); |
|||
} |
|||
|
|||
// Engine properties debug
|
|||
// First element is a reserved location and should not be used (allow to track error)
|
|||
// Special case for None since it cannot be inferred from SurfaceData/BuiltinData
|
|||
debugViewEngineStringsList.Add(new GUIContent("None")); |
|||
debugViewEngineValuesList.Add(0); |
|||
|
|||
foreach (MaterialItem item in materialItems) |
|||
{ |
|||
FillWithProperties(item.bsdfDataType, ref debugViewEngineStringsList, ref debugViewEngineValuesList, item.className); |
|||
} |
|||
|
|||
// For the following, no need to reserve the 0 case as it is handled in the Enum
|
|||
|
|||
// Attributes debug
|
|||
FillWithPropertiesEnum(typeof(DebugViewVarying), ref debugViewMaterialVaryingStringsList, ref debugViewMaterialVaryingValuesList, ""); |
|||
|
|||
// Properties debug
|
|||
FillWithPropertiesEnum(typeof(DebugViewProperties), ref debugViewMaterialPropertiesStringsList, ref debugViewMaterialPropertiesValuesList, ""); |
|||
|
|||
// Gbuffer debug
|
|||
FillWithPropertiesEnum(typeof(DebugViewGbuffer), ref debugViewMaterialGBufferStringsList, ref debugViewMaterialGBufferValuesList, ""); |
|||
FillWithProperties(typeof(Lit.BSDFData), ref debugViewMaterialGBufferStringsList, ref debugViewMaterialGBufferValuesList, ""); |
|||
|
|||
// Convert to array for UI
|
|||
debugViewMaterialStrings = debugViewMaterialStringsList.ToArray(); |
|||
debugViewMaterialValues = debugViewMaterialValuesList.ToArray(); |
|||
|
|||
debugViewEngineStrings = debugViewEngineStringsList.ToArray(); |
|||
debugViewEngineValues = debugViewEngineValuesList.ToArray(); |
|||
|
|||
debugViewMaterialVaryingStrings = debugViewMaterialVaryingStringsList.ToArray(); |
|||
debugViewMaterialVaryingValues = debugViewMaterialVaryingValuesList.ToArray(); |
|||
|
|||
debugViewMaterialPropertiesStrings = debugViewMaterialPropertiesStringsList.ToArray(); |
|||
debugViewMaterialPropertiesValues = debugViewMaterialPropertiesValuesList.ToArray(); |
|||
|
|||
debugViewMaterialTextureStrings = debugViewMaterialTextureStringsList.ToArray(); |
|||
debugViewMaterialTextureValues = debugViewMaterialTextureValuesList.ToArray(); |
|||
|
|||
debugViewMaterialGBufferStrings = debugViewMaterialGBufferStringsList.ToArray(); |
|||
debugViewMaterialGBufferValues = debugViewMaterialGBufferValuesList.ToArray(); |
|||
|
|||
isDebugViewMaterialInit = true; |
|||
} |
|||
} |
|||
|
|||
public int debugViewMaterial { get { return m_DebugViewMaterial; } } |
|||
public int debugViewEngine { get { return m_DebugViewEngine; } } |
|||
public DebugViewVarying debugViewVarying { get { return m_DebugViewVarying; } } |
|||
public DebugViewProperties debugViewProperties { get { return m_DebugViewProperties; } } |
|||
public int debugViewGBuffer { get { return m_DebugViewGBuffer; } } |
|||
|
|||
int m_DebugViewMaterial = 0; // No enum there because everything is generated from materials.
|
|||
int m_DebugViewEngine = 0; // No enum there because everything is generated from BSDFData
|
|||
DebugViewVarying m_DebugViewVarying = DebugViewVarying.None; |
|||
DebugViewProperties m_DebugViewProperties = DebugViewProperties.None; |
|||
int m_DebugViewGBuffer = 0; // Can't use GBuffer enum here because the values are actually split between this enum and values from Lit.BSDFData
|
|||
|
|||
public int GetDebugMaterialIndex() |
|||
{ |
|||
// This value is used in the shader for the actual debug display.
|
|||
// There is only one uniform parameter for that so we just add all of them
|
|||
// They are all mutually exclusive so return the sum will return the right index.
|
|||
return m_DebugViewGBuffer + m_DebugViewMaterial + m_DebugViewEngine + (int)m_DebugViewVarying + (int)m_DebugViewProperties; |
|||
} |
|||
|
|||
public void DisableMaterialDebug() |
|||
{ |
|||
m_DebugViewMaterial = 0; |
|||
m_DebugViewEngine = 0; |
|||
m_DebugViewVarying = DebugViewVarying.None; |
|||
m_DebugViewProperties = DebugViewProperties.None; |
|||
m_DebugViewGBuffer = 0; |
|||
} |
|||
|
|||
public void SetDebugViewMaterial(int value) |
|||
{ |
|||
if (value != 0) |
|||
DisableMaterialDebug(); |
|||
m_DebugViewMaterial = value; |
|||
} |
|||
|
|||
public void SetDebugViewEngine(int value) |
|||
{ |
|||
if (value != 0) |
|||
DisableMaterialDebug(); |
|||
m_DebugViewEngine = value; |
|||
} |
|||
|
|||
public void SetDebugViewVarying(DebugViewVarying value) |
|||
{ |
|||
if (value != 0) |
|||
DisableMaterialDebug(); |
|||
m_DebugViewVarying = value; |
|||
} |
|||
public void SetDebugViewProperties(DebugViewProperties value) |
|||
{ |
|||
if (value != 0) |
|||
DisableMaterialDebug(); |
|||
m_DebugViewProperties = value; |
|||
} |
|||
|
|||
public void SetDebugViewGBuffer(int value) |
|||
{ |
|||
if (value != 0) |
|||
DisableMaterialDebug(); |
|||
m_DebugViewGBuffer = value; |
|||
} |
|||
|
|||
|
|||
public bool IsDebugGBufferEnabled() |
|||
{ |
|||
return m_DebugViewGBuffer != 0; |
|||
} |
|||
|
|||
public bool IsDebugDisplayEnabled() |
|||
{ |
|||
return (m_DebugViewEngine != 0 || m_DebugViewMaterial != 0 || m_DebugViewVarying != DebugViewVarying.None || m_DebugViewProperties != DebugViewProperties.None || m_DebugViewGBuffer != 0); |
|||
} |
|||
} |
|||
} |
|
|||
{ |
|||
"name": "com.unity.render-pipelines.high-definition", |
|||
"description": "HD Render Pipeline for Unity.", |
|||
"version": "0.1.30", |
|||
"version": "0.1.32", |
|||
"com.unity.render-pipelines.core": "0.1.30" |
|||
"com.unity.render-pipelines.core": "0.1.32" |
|||
} |
|||
} |
|
|||
{ |
|||
"name": "com.unity.render-pipelines.lightweight", |
|||
"description": "Lightweight Render Pipeline for Unity.", |
|||
"version": "0.1.30", |
|||
"version": "0.1.32", |
|||
"com.unity.render-pipelines.core": "0.1.30" |
|||
"com.unity.render-pipelines.core": "0.1.32" |
|||
} |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: 9b76b9e7a4790f14ca7a8b57cd46600d |
|||
folderAsset: yes |
|||
DefaultImporter: |
|||
externalObjects: {} |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
using System.Collections.Generic; |
|||
|
|||
namespace UnityEngine.Experimental.Rendering |
|||
{ |
|||
public enum DebugAction |
|||
{ |
|||
EnableDebugMenu, |
|||
PreviousDebugPanel, |
|||
NextDebugPanel, |
|||
Action, |
|||
MakePersistent, |
|||
MoveVertical, |
|||
MoveHorizontal, |
|||
Multiplier, |
|||
DebugActionCount |
|||
} |
|||
|
|||
enum DebugActionRepeatMode |
|||
{ |
|||
Never, |
|||
Delay |
|||
} |
|||
|
|||
public sealed partial class DebugManager |
|||
{ |
|||
const string kEnableDebugBtn1 = "Enable Debug Button 1"; |
|||
const string kEnableDebugBtn2 = "Enable Debug Button 2"; |
|||
const string kDebugPreviousBtn = "Debug Previous"; |
|||
const string kDebugNextBtn = "Debug Next"; |
|||
const string kValidateBtn = "Debug Validate"; |
|||
const string kPersistentBtn = "Debug Persistent"; |
|||
const string kDPadVertical = "Debug Vertical"; |
|||
const string kDPadHorizontal = "Debug Horizontal"; |
|||
const string kMultiplierBtn = "Debug Multiplier"; |
|||
|
|||
DebugActionDesc[] m_DebugActions; |
|||
DebugActionState[] m_DebugActionStates; |
|||
|
|||
void RegisterActions() |
|||
{ |
|||
m_DebugActions = new DebugActionDesc[(int)DebugAction.DebugActionCount]; |
|||
m_DebugActionStates = new DebugActionState[(int)DebugAction.DebugActionCount]; |
|||
|
|||
var enableDebugMenu = new DebugActionDesc(); |
|||
enableDebugMenu.buttonTriggerList.Add(new[] { kEnableDebugBtn1, kEnableDebugBtn2 }); |
|||
enableDebugMenu.keyTriggerList.Add(new[] { KeyCode.LeftControl, KeyCode.Backspace }); |
|||
enableDebugMenu.repeatMode = DebugActionRepeatMode.Never; |
|||
AddAction(DebugAction.EnableDebugMenu, enableDebugMenu); |
|||
|
|||
var nextDebugPanel = new DebugActionDesc(); |
|||
nextDebugPanel.buttonTriggerList.Add(new[] { kDebugNextBtn }); |
|||
nextDebugPanel.repeatMode = DebugActionRepeatMode.Never; |
|||
AddAction(DebugAction.NextDebugPanel, nextDebugPanel); |
|||
|
|||
var previousDebugPanel = new DebugActionDesc(); |
|||
previousDebugPanel.buttonTriggerList.Add(new[] { kDebugPreviousBtn }); |
|||
previousDebugPanel.repeatMode = DebugActionRepeatMode.Never; |
|||
AddAction(DebugAction.PreviousDebugPanel, previousDebugPanel); |
|||
|
|||
var validate = new DebugActionDesc(); |
|||
validate.buttonTriggerList.Add(new[] { kValidateBtn }); |
|||
validate.repeatMode = DebugActionRepeatMode.Never; |
|||
AddAction(DebugAction.Action, validate); |
|||
|
|||
var persistent = new DebugActionDesc(); |
|||
persistent.buttonTriggerList.Add(new[] { kPersistentBtn }); |
|||
persistent.repeatMode = DebugActionRepeatMode.Never; |
|||
AddAction(DebugAction.MakePersistent, persistent); |
|||
|
|||
var multiplier = new DebugActionDesc(); |
|||
multiplier.buttonTriggerList.Add(new[] { kMultiplierBtn }); |
|||
multiplier.repeatMode = DebugActionRepeatMode.Delay; |
|||
validate.repeatDelay = 0f; |
|||
AddAction(DebugAction.Multiplier, multiplier); |
|||
|
|||
AddAction(DebugAction.MoveVertical, new DebugActionDesc { axisTrigger = kDPadVertical, repeatMode = DebugActionRepeatMode.Delay, repeatDelay = 0.16f }); |
|||
AddAction(DebugAction.MoveHorizontal, new DebugActionDesc { axisTrigger = kDPadHorizontal, repeatMode = DebugActionRepeatMode.Delay, repeatDelay = 0.16f }); |
|||
} |
|||
|
|||
void AddAction(DebugAction action, DebugActionDesc desc) |
|||
{ |
|||
int index = (int)action; |
|||
m_DebugActions[index] = desc; |
|||
m_DebugActionStates[index] = new DebugActionState(); |
|||
} |
|||
|
|||
void SampleAction(int actionIndex) |
|||
{ |
|||
var desc = m_DebugActions[actionIndex]; |
|||
var state = m_DebugActionStates[actionIndex]; |
|||
|
|||
//bool canSampleAction = (state.actionTriggered == false) || (desc.repeatMode == DebugActionRepeatMode.Delay && state.timer > desc.repeatDelay);
|
|||
if (state.runningAction == false) |
|||
{ |
|||
// Check button triggers
|
|||
for (int buttonListIndex = 0; buttonListIndex < desc.buttonTriggerList.Count; ++buttonListIndex) |
|||
{ |
|||
var buttons = desc.buttonTriggerList[buttonListIndex]; |
|||
bool allButtonPressed = true; |
|||
|
|||
foreach (var button in buttons) |
|||
{ |
|||
allButtonPressed = Input.GetButton(button); |
|||
if (!allButtonPressed) |
|||
break; |
|||
} |
|||
|
|||
if (allButtonPressed) |
|||
{ |
|||
state.TriggerWithButton(buttons, 1f); |
|||
break; |
|||
} |
|||
} |
|||
|
|||
// Check axis triggers
|
|||
if (desc.axisTrigger != "") |
|||
{ |
|||
float axisValue = Input.GetAxis(desc.axisTrigger); |
|||
|
|||
if (axisValue != 0f) |
|||
state.TriggerWithAxis(desc.axisTrigger, axisValue); |
|||
} |
|||
|
|||
// Check key triggers
|
|||
for (int keyListIndex = 0; keyListIndex < desc.keyTriggerList.Count; ++keyListIndex) |
|||
{ |
|||
var keys = desc.keyTriggerList[keyListIndex]; |
|||
bool allKeyPressed = true; |
|||
|
|||
foreach (var key in keys) |
|||
{ |
|||
allKeyPressed = Input.GetKey(key); |
|||
if (!allKeyPressed) |
|||
break; |
|||
} |
|||
|
|||
if (allKeyPressed) |
|||
{ |
|||
state.TriggerWithKey(keys, 1f); |
|||
break; |
|||
} |
|||
} |
|||
} |
|||
} |
|||
|
|||
void UpdateAction(int actionIndex) |
|||
{ |
|||
var desc = m_DebugActions[actionIndex]; |
|||
var state = m_DebugActionStates[actionIndex]; |
|||
|
|||
if (state.runningAction) |
|||
state.Update(desc); |
|||
} |
|||
|
|||
public void UpdateActions() |
|||
{ |
|||
for (int actionIndex = 0; actionIndex < m_DebugActions.Length; ++actionIndex) |
|||
{ |
|||
UpdateAction(actionIndex); |
|||
SampleAction(actionIndex); |
|||
} |
|||
} |
|||
|
|||
public float GetAction(DebugAction action) |
|||
{ |
|||
return m_DebugActionStates[(int)action].actionState; |
|||
} |
|||
|
|||
void RegisterInputs() |
|||
{ |
|||
#if UNITY_EDITOR
|
|||
var inputEntries = new List<InputManagerEntry> |
|||
{ |
|||
new InputManagerEntry { name = kEnableDebugBtn1, kind = InputManagerEntry.Kind.KeyOrButton, btnPositive = "left ctrl", altBtnPositive = "joystick button 8" }, |
|||
new InputManagerEntry { name = kEnableDebugBtn2, kind = InputManagerEntry.Kind.KeyOrButton, btnPositive = "backspace", altBtnPositive = "joystick button 9" }, |
|||
new InputManagerEntry { name = kDebugNextBtn, kind = InputManagerEntry.Kind.KeyOrButton, btnPositive = "page down", altBtnPositive = "joystick button 5" }, |
|||
new InputManagerEntry { name = kDebugPreviousBtn, kind = InputManagerEntry.Kind.KeyOrButton, btnPositive = "page up", altBtnPositive = "joystick button 4" }, |
|||
new InputManagerEntry { name = kValidateBtn, kind = InputManagerEntry.Kind.KeyOrButton, btnPositive = "return", altBtnPositive = "joystick button 0" }, |
|||
new InputManagerEntry { name = kPersistentBtn, kind = InputManagerEntry.Kind.KeyOrButton, btnPositive = "right shift", altBtnPositive = "joystick button 2" }, |
|||
new InputManagerEntry { name = kMultiplierBtn, kind = InputManagerEntry.Kind.KeyOrButton, btnPositive = "left shift", altBtnPositive = "joystick button 3" }, |
|||
new InputManagerEntry { name = kDPadHorizontal, kind = InputManagerEntry.Kind.KeyOrButton, btnPositive = "right", btnNegative = "left", gravity = 1000f, deadZone = 0.001f, sensitivity = 1000f }, |
|||
new InputManagerEntry { name = kDPadVertical, kind = InputManagerEntry.Kind.KeyOrButton, btnPositive = "up", btnNegative = "down", gravity = 1000f, deadZone = 0.001f, sensitivity = 1000f }, |
|||
new InputManagerEntry { name = kDPadVertical, kind = InputManagerEntry.Kind.Axis, axis = InputManagerEntry.Axis.Seventh, btnPositive = "up", btnNegative = "down", gravity = 1000f, deadZone = 0.001f, sensitivity = 1000f }, |
|||
new InputManagerEntry { name = kDPadHorizontal, kind = InputManagerEntry.Kind.Axis, axis = InputManagerEntry.Axis.Sixth, btnPositive = "right", btnNegative = "left", gravity = 1000f, deadZone = 0.001f, sensitivity = 1000f }, |
|||
}; |
|||
|
|||
InputRegistering.RegisterInputs(inputEntries); |
|||
#endif
|
|||
} |
|||
} |
|||
|
|||
class DebugActionDesc |
|||
{ |
|||
public List<string[]> buttonTriggerList = new List<string[]>(); |
|||
public string axisTrigger = ""; |
|||
public List<KeyCode[]> keyTriggerList = new List<KeyCode[]>(); |
|||
public DebugActionRepeatMode repeatMode = DebugActionRepeatMode.Never; |
|||
public float repeatDelay; |
|||
} |
|||
|
|||
class DebugActionState |
|||
{ |
|||
enum DebugActionKeyType |
|||
{ |
|||
Button, |
|||
Axis, |
|||
Key |
|||
} |
|||
|
|||
DebugActionKeyType m_Type; |
|||
string[] m_PressedButtons; |
|||
string m_PressedAxis = ""; |
|||
KeyCode[] m_PressedKeys; |
|||
bool[] m_TriggerPressedUp; |
|||
float m_Timer; |
|||
|
|||
internal bool runningAction { get; private set; } |
|||
internal float actionState { get; private set; } |
|||
|
|||
void Trigger(int triggerCount, float state) |
|||
{ |
|||
actionState = state; |
|||
runningAction = true; |
|||
m_Timer = 0f; |
|||
|
|||
m_TriggerPressedUp = new bool[triggerCount]; |
|||
for (int i = 0; i < m_TriggerPressedUp.Length; ++i) |
|||
m_TriggerPressedUp[i] = false; |
|||
} |
|||
|
|||
public void TriggerWithButton(string[] buttons, float state) |
|||
{ |
|||
m_Type = DebugActionKeyType.Button; |
|||
m_PressedButtons = buttons; |
|||
m_PressedAxis = ""; |
|||
Trigger(buttons.Length, state); |
|||
} |
|||
|
|||
public void TriggerWithAxis(string axis, float state) |
|||
{ |
|||
m_Type = DebugActionKeyType.Axis; |
|||
m_PressedAxis = axis; |
|||
Trigger(1, state); |
|||
} |
|||
|
|||
public void TriggerWithKey(KeyCode[] keys, float state) |
|||
{ |
|||
m_Type = DebugActionKeyType.Key; |
|||
m_PressedKeys = keys; |
|||
m_PressedAxis = ""; |
|||
Trigger(keys.Length, state); |
|||
} |
|||
|
|||
void Reset() |
|||
{ |
|||
runningAction = false; |
|||
m_Timer = 0f; |
|||
m_TriggerPressedUp = null; |
|||
} |
|||
|
|||
public void Update(DebugActionDesc desc) |
|||
{ |
|||
// Always reset this so that the action can only be caught once until repeat/reset
|
|||
actionState = 0f; |
|||
|
|||
if (m_TriggerPressedUp != null) |
|||
{ |
|||
m_Timer += Time.deltaTime; |
|||
|
|||
for (int i = 0; i < m_TriggerPressedUp.Length; ++i) |
|||
{ |
|||
if (m_Type == DebugActionKeyType.Button) |
|||
m_TriggerPressedUp[i] |= Input.GetButtonUp(m_PressedButtons[i]); |
|||
else if (m_Type == DebugActionKeyType.Axis) |
|||
m_TriggerPressedUp[i] |= Mathf.Approximately(Input.GetAxis(m_PressedAxis), 0f); |
|||
else |
|||
m_TriggerPressedUp[i] |= Input.GetKeyUp(m_PressedKeys[i]); |
|||
} |
|||
|
|||
bool allTriggerUp = true; |
|||
foreach (bool value in m_TriggerPressedUp) |
|||
allTriggerUp &= value; |
|||
|
|||
if (allTriggerUp || (m_Timer > desc.repeatDelay && desc.repeatMode == DebugActionRepeatMode.Delay)) |
|||
Reset(); |
|||
} |
|||
} |
|||
} |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: b9ea0a15a47dead4ebc52bd3f7a926c1 |
|||
MonoImporter: |
|||
externalObjects: {} |
|||
serializedVersion: 2 |
|||
defaultReferences: [] |
|||
executionOrder: 0 |
|||
icon: {instanceID: 0} |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Collections.ObjectModel; |
|||
using UnityEngine.Experimental.Rendering.UI; |
|||
|
|||
namespace UnityEngine.Experimental.Rendering |
|||
{ |
|||
using UnityObject = UnityEngine.Object; |
|||
|
|||
public sealed partial class DebugManager |
|||
{ |
|||
static readonly DebugManager s_Instance = new DebugManager(); |
|||
public static DebugManager instance { get { return s_Instance; } } |
|||
|
|||
// Explicit static constructor to tell the C# compiler not to mark type as beforefieldinit
|
|||
static DebugManager() { } |
|||
|
|||
ReadOnlyCollection<DebugUI.Panel> m_ReadOnlyPanels; |
|||
readonly List<DebugUI.Panel> m_Panels = new List<DebugUI.Panel>(); |
|||
|
|||
public ReadOnlyCollection<DebugUI.Panel> panels |
|||
{ |
|||
get |
|||
{ |
|||
if (m_ReadOnlyPanels == null) |
|||
m_ReadOnlyPanels = m_Panels.AsReadOnly(); |
|||
|
|||
return m_ReadOnlyPanels; |
|||
} |
|||
} |
|||
|
|||
public event Action<bool> onDisplayRuntimeUIChanged = delegate { }; |
|||
public event Action onSetDirty = delegate { }; |
|||
|
|||
GameObject m_Root; |
|||
DebugUIHandlerCanvas m_RootUICanvas; |
|||
|
|||
GameObject m_PersistentRoot; |
|||
DebugUIHandlerPersistentCanvas m_RootUIPersistentCanvas; |
|||
|
|||
public bool displayRuntimeUI |
|||
{ |
|||
get |
|||
{ |
|||
return m_Root != null && m_Root.activeInHierarchy; |
|||
} |
|||
set |
|||
{ |
|||
if (value && m_Root == null) |
|||
{ |
|||
var uiManager = UnityObject.FindObjectOfType<DebugUIHandlerCanvas>(); |
|||
|
|||
if (uiManager != null) |
|||
{ |
|||
m_Root = uiManager.gameObject; |
|||
return; |
|||
} |
|||
|
|||
m_Root = UnityObject.Instantiate(Resources.Load<Transform>("DebugUI Canvas")).gameObject; |
|||
m_Root.name = "[Debug Canvas]"; |
|||
m_Root.transform.localPosition = Vector3.zero; |
|||
m_RootUICanvas = m_Root.GetComponent<DebugUIHandlerCanvas>(); |
|||
} |
|||
|
|||
if (m_Root != null) |
|||
m_Root.SetActive(value); |
|||
|
|||
onDisplayRuntimeUIChanged(value); |
|||
} |
|||
} |
|||
|
|||
public bool displayPersistentRuntimeUI |
|||
{ |
|||
get { return m_RootUIPersistentCanvas != null && m_PersistentRoot.activeInHierarchy; } |
|||
set |
|||
{ |
|||
CheckPersistentCanvas(); |
|||
m_PersistentRoot.SetActive(value); |
|||
} |
|||
} |
|||
|
|||
DebugManager() |
|||
{ |
|||
RegisterInputs(); |
|||
RegisterActions(); |
|||
} |
|||
|
|||
public void Reset() |
|||
{ |
|||
if (m_Panels != null) |
|||
m_Panels.Clear(); |
|||
} |
|||
|
|||
public int GetState() |
|||
{ |
|||
int hash = 17; |
|||
|
|||
foreach (var panel in m_Panels) |
|||
hash = hash * 23 + panel.GetHashCode(); |
|||
|
|||
return hash; |
|||
} |
|||
|
|||
internal void ChangeSelection(DebugUIHandlerWidget widget, bool fromNext) |
|||
{ |
|||
m_RootUICanvas.ChangeSelection(widget, fromNext); |
|||
} |
|||
|
|||
void CheckPersistentCanvas() |
|||
{ |
|||
if (m_RootUIPersistentCanvas == null) |
|||
{ |
|||
var uiManager = UnityObject.FindObjectOfType<DebugUIHandlerPersistentCanvas>(); |
|||
|
|||
if (uiManager == null) |
|||
{ |
|||
m_PersistentRoot = UnityObject.Instantiate(Resources.Load<Transform>("DebugUI Persistent Canvas")).gameObject; |
|||
m_PersistentRoot.name = "[Debug Canvas - Persistent]"; |
|||
m_PersistentRoot.transform.localPosition = Vector3.zero; |
|||
} |
|||
else |
|||
{ |
|||
m_PersistentRoot = uiManager.gameObject; |
|||
} |
|||
|
|||
m_RootUIPersistentCanvas = m_PersistentRoot.GetComponent<DebugUIHandlerPersistentCanvas>(); |
|||
} |
|||
} |
|||
|
|||
public void TogglePersistent(DebugUI.Widget widget) |
|||
{ |
|||
if (widget == null) |
|||
return; |
|||
|
|||
var valueWidget = widget as DebugUI.Value; |
|||
if (valueWidget == null) |
|||
{ |
|||
Debug.Log("Only DebugUI.Value items can be made persistent."); |
|||
return; |
|||
} |
|||
|
|||
CheckPersistentCanvas(); |
|||
m_RootUIPersistentCanvas.Toggle(valueWidget); |
|||
} |
|||
|
|||
void OnPanelDirty(DebugUI.Panel panel) |
|||
{ |
|||
onSetDirty(); |
|||
} |
|||
|
|||
// TODO: Optimally we should use a query path here instead of a display name
|
|||
public DebugUI.Panel GetPanel(string displayName, bool createIfNull = false) |
|||
{ |
|||
foreach (var panel in m_Panels) |
|||
{ |
|||
if (panel.displayName == displayName) |
|||
return panel; |
|||
} |
|||
|
|||
DebugUI.Panel p = null; |
|||
|
|||
if (createIfNull) |
|||
{ |
|||
p = new DebugUI.Panel { displayName = displayName }; |
|||
p.onSetDirty += OnPanelDirty; |
|||
m_Panels.Add(p); |
|||
m_ReadOnlyPanels = m_Panels.AsReadOnly(); |
|||
} |
|||
|
|||
return p; |
|||
} |
|||
|
|||
// TODO: Use a query path here as well instead of a display name
|
|||
public void RemovePanel(string displayName) |
|||
{ |
|||
DebugUI.Panel panel = null; |
|||
|
|||
foreach (var p in m_Panels) |
|||
{ |
|||
if (p.displayName == displayName) |
|||
{ |
|||
p.onSetDirty -= OnPanelDirty; |
|||
panel = p; |
|||
break; |
|||
} |
|||
} |
|||
|
|||
RemovePanel(panel); |
|||
} |
|||
|
|||
public void RemovePanel(DebugUI.Panel panel) |
|||
{ |
|||
if (panel == null) |
|||
return; |
|||
|
|||
m_Panels.Remove(panel); |
|||
m_ReadOnlyPanels = m_Panels.AsReadOnly(); |
|||
} |
|||
|
|||
public DebugUI.Widget GetItem(string queryPath) |
|||
{ |
|||
foreach (var panel in m_Panels) |
|||
{ |
|||
var w = GetItem(queryPath, panel); |
|||
if (w != null) |
|||
return w; |
|||
} |
|||
|
|||
return null; |
|||
} |
|||
|
|||
DebugUI.Widget GetItem(string queryPath, DebugUI.IContainer container) |
|||
{ |
|||
foreach (var child in container.children) |
|||
{ |
|||
if (child.queryPath == queryPath) |
|||
return child; |
|||
|
|||
var containerChild = child as DebugUI.IContainer; |
|||
if (containerChild != null) |
|||
{ |
|||
var w = GetItem(queryPath, containerChild); |
|||
if (w != null) |
|||
return w; |
|||
} |
|||
} |
|||
|
|||
return null; |
|||
} |
|||
} |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: a09c907f481d4894a96697283a87c352 |
|||
MonoImporter: |
|||
externalObjects: {} |
|||
serializedVersion: 2 |
|||
defaultReferences: [] |
|||
executionOrder: 0 |
|||
icon: {instanceID: 0} |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
namespace UnityEngine.Experimental.Rendering |
|||
{ |
|||
public partial class DebugUI |
|||
{ |
|||
// Base class for "container" type widgets, although it can be used on its own (if a display
|
|||
// name is set then it'll behave as a group with a header)
|
|||
public class Container : Widget, IContainer |
|||
{ |
|||
public ObservableList<Widget> children { get; private set; } |
|||
|
|||
public override Panel panel |
|||
{ |
|||
get { return m_Panel; } |
|||
internal set |
|||
{ |
|||
m_Panel = value; |
|||
|
|||
// Bubble down
|
|||
foreach (var child in children) |
|||
child.panel = value; |
|||
} |
|||
} |
|||
|
|||
public Container() |
|||
{ |
|||
displayName = ""; |
|||
children = new ObservableList<Widget>(); |
|||
children.ItemAdded += OnItemAdded; |
|||
children.ItemRemoved += OnItemRemoved; |
|||
} |
|||
|
|||
internal override void GenerateQueryPath() |
|||
{ |
|||
base.GenerateQueryPath(); |
|||
|
|||
foreach (var child in children) |
|||
child.GenerateQueryPath(); |
|||
} |
|||
|
|||
protected virtual void OnItemAdded(ObservableList<Widget> sender, ListChangedEventArgs<Widget> e) |
|||
{ |
|||
if (e.item != null) |
|||
{ |
|||
e.item.panel = m_Panel; |
|||
e.item.parent = this; |
|||
} |
|||
|
|||
if (m_Panel != null) |
|||
m_Panel.SetDirty(); |
|||
} |
|||
|
|||
protected virtual void OnItemRemoved(ObservableList<Widget> sender, ListChangedEventArgs<Widget> e) |
|||
{ |
|||
if (e.item != null) |
|||
{ |
|||
e.item.panel = null; |
|||
e.item.parent = null; |
|||
} |
|||
|
|||
if (m_Panel != null) |
|||
m_Panel.SetDirty(); |
|||
} |
|||
|
|||
public override int GetHashCode() |
|||
{ |
|||
int hash = 17; |
|||
hash = hash * 23 + queryPath.GetHashCode(); |
|||
|
|||
foreach (var child in children) |
|||
hash = hash * 23 + child.GetHashCode(); |
|||
|
|||
return hash; |
|||
} |
|||
} |
|||
|
|||
// Unity-like foldout that can be collapsed
|
|||
public class Foldout : Container, IValueField |
|||
{ |
|||
public bool isReadOnly { get { return false; } } |
|||
|
|||
public bool opened; |
|||
|
|||
public bool GetValue() |
|||
{ |
|||
return opened; |
|||
} |
|||
|
|||
object IValueField.GetValue() |
|||
{ |
|||
return GetValue(); |
|||
} |
|||
|
|||
public void SetValue(object value) |
|||
{ |
|||
SetValue((bool)value); |
|||
} |
|||
|
|||
public object ValidateValue(object value) |
|||
{ |
|||
return value; |
|||
} |
|||
|
|||
public void SetValue(bool value) |
|||
{ |
|||
opened = value; |
|||
} |
|||
} |
|||
|
|||
// Horizontal layout
|
|||
public class HBox : Container |
|||
{ |
|||
public HBox() |
|||
{ |
|||
displayName = "HBox"; |
|||
} |
|||
} |
|||
|
|||
// Vertical layout
|
|||
public class VBox : Container |
|||
{ |
|||
public VBox() |
|||
{ |
|||
displayName = "VBox"; |
|||
} |
|||
} |
|||
} |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: 02feae31429679949ab4a4a40c8ad34e |
|||
MonoImporter: |
|||
externalObjects: {} |
|||
serializedVersion: 2 |
|||
defaultReferences: [] |
|||
executionOrder: 0 |
|||
icon: {instanceID: 0} |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
using System; |
|||
using System.Linq; |
|||
using UnityEngine.Assertions; |
|||
|
|||
namespace UnityEngine.Experimental.Rendering |
|||
{ |
|||
public partial class DebugUI |
|||
{ |
|||
// Generic field - will be serialized in the editor if it's not read-only
|
|||
public abstract class Field<T> : Widget, IValueField |
|||
{ |
|||
public Func<T> getter { get; set; } |
|||
public Action<T> setter { get; set; } |
|||
|
|||
// This should be an `event` but they don't play nice with object initializers in the
|
|||
// version of C# we use.
|
|||
public Action<Field<T>, T> onValueChanged; |
|||
|
|||
object IValueField.ValidateValue(object value) |
|||
{ |
|||
return ValidateValue((T)value); |
|||
} |
|||
|
|||
public virtual T ValidateValue(T value) |
|||
{ |
|||
return value; |
|||
} |
|||
|
|||
object IValueField.GetValue() |
|||
{ |
|||
return GetValue(); |
|||
} |
|||
|
|||
public T GetValue() |
|||
{ |
|||
Assert.IsNotNull(getter); |
|||
return getter(); |
|||
} |
|||
|
|||
public void SetValue(object value) |
|||
{ |
|||
SetValue((T)value); |
|||
} |
|||
|
|||
public void SetValue(T value) |
|||
{ |
|||
Assert.IsNotNull(setter); |
|||
var v = ValidateValue(value); |
|||
|
|||
if (!v.Equals(getter())) |
|||
{ |
|||
setter(v); |
|||
|
|||
if (onValueChanged != null) |
|||
onValueChanged(this, v); |
|||
} |
|||
} |
|||
} |
|||
|
|||
public class BoolField : Field<bool> { } |
|||
|
|||
public class IntField : Field<int> |
|||
{ |
|||
public Func<int> min; |
|||
public Func<int> max; |
|||
|
|||
// Runtime-only
|
|||
public int incStep = 1; |
|||
public int intStepMult = 10; |
|||
|
|||
public override int ValidateValue(int value) |
|||
{ |
|||
if (min != null) value = Mathf.Max(value, min()); |
|||
if (max != null) value = Mathf.Min(value, max()); |
|||
return value; |
|||
} |
|||
} |
|||
|
|||
public class UIntField : Field<uint> |
|||
{ |
|||
public Func<uint> min; |
|||
public Func<uint> max; |
|||
|
|||
// Runtime-only
|
|||
public uint incStep = 1u; |
|||
public uint intStepMult = 10u; |
|||
|
|||
public override uint ValidateValue(uint value) |
|||
{ |
|||
if (min != null) value = (uint)Mathf.Max((int)value, (int)min()); |
|||
if (max != null) value = (uint)Mathf.Min((int)value, (int)max()); |
|||
return value; |
|||
} |
|||
} |
|||
|
|||
public class FloatField : Field<float> |
|||
{ |
|||
public Func<float> min; |
|||
public Func<float> max; |
|||
|
|||
// Runtime-only
|
|||
public float incStep = 0.1f; |
|||
public float incStepMult = 10f; |
|||
public int decimals = 3; |
|||
|
|||
public override float ValidateValue(float value) |
|||
{ |
|||
if (min != null) value = Mathf.Max(value, min()); |
|||
if (max != null) value = Mathf.Min(value, max()); |
|||
return value; |
|||
} |
|||
} |
|||
|
|||
public class EnumField : Field<int> |
|||
{ |
|||
public GUIContent[] enumNames; |
|||
public int[] enumValues; |
|||
|
|||
public Type autoEnum |
|||
{ |
|||
set |
|||
{ |
|||
enumNames = Enum.GetNames(value).Select(x => new GUIContent(x)).ToArray(); |
|||
enumValues = Enum.GetValues(value).Cast<int>().ToArray(); |
|||
} |
|||
} |
|||
} |
|||
|
|||
public class ColorField : Field<Color> |
|||
{ |
|||
public bool hdr = false; |
|||
public bool showAlpha = true; |
|||
|
|||
// Editor-only
|
|||
public bool showPicker = true; |
|||
|
|||
// Runtime-only
|
|||
public float incStep = 0.025f; |
|||
public float incStepMult = 5f; |
|||
public int decimals = 3; |
|||
|
|||
public override Color ValidateValue(Color value) |
|||
{ |
|||
if (!hdr) |
|||
{ |
|||
value.r = Mathf.Clamp01(value.r); |
|||
value.g = Mathf.Clamp01(value.g); |
|||
value.b = Mathf.Clamp01(value.b); |
|||
value.a = Mathf.Clamp01(value.a); |
|||
} |
|||
|
|||
return value; |
|||
} |
|||
} |
|||
|
|||
public class Vector2Field : Field<Vector2> |
|||
{ |
|||
// Runtime-only
|
|||
public float incStep = 0.025f; |
|||
public float incStepMult = 10f; |
|||
public int decimals = 3; |
|||
} |
|||
|
|||
public class Vector3Field : Field<Vector3> |
|||
{ |
|||
// Runtime-only
|
|||
public float incStep = 0.025f; |
|||
public float incStepMult = 10f; |
|||
public int decimals = 3; |
|||
} |
|||
|
|||
public class Vector4Field : Field<Vector4> |
|||
{ |
|||
// Runtime-only
|
|||
public float incStep = 0.025f; |
|||
public float incStepMult = 10f; |
|||
public int decimals = 3; |
|||
} |
|||
} |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: 332920c028664644e9e4e1bf5a1631d5 |
|||
MonoImporter: |
|||
externalObjects: {} |
|||
serializedVersion: 2 |
|||
defaultReferences: [] |
|||
executionOrder: 0 |
|||
icon: {instanceID: 0} |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
using System; |
|||
|
|||
namespace UnityEngine.Experimental.Rendering |
|||
{ |
|||
public partial class DebugUI |
|||
{ |
|||
// Root panel class - we don't want to extend Container here because we need a clear
|
|||
// separation between debug panels and actual widgets
|
|||
public class Panel : IContainer |
|||
{ |
|||
public Flags flags { get; set; } |
|||
public string displayName { get; set; } |
|||
public string queryPath { get { return displayName; } } |
|||
|
|||
public bool isEditorOnly { get { return (flags & Flags.EditorOnly) != 0; } } |
|||
public bool isRuntimeOnly { get { return (flags & Flags.RuntimeOnly) != 0; } } |
|||
|
|||
public ObservableList<Widget> children { get; private set; } |
|||
public event Action<Panel> onSetDirty = delegate { }; |
|||
|
|||
public Panel() |
|||
{ |
|||
children = new ObservableList<Widget>(); |
|||
children.ItemAdded += OnItemAdded; |
|||
children.ItemRemoved += OnItemRemoved; |
|||
} |
|||
|
|||
protected virtual void OnItemAdded(ObservableList<Widget> sender, ListChangedEventArgs<Widget> e) |
|||
{ |
|||
if (e.item != null) |
|||
{ |
|||
e.item.panel = this; |
|||
e.item.parent = this; |
|||
} |
|||
|
|||
SetDirty(); |
|||
} |
|||
|
|||
protected virtual void OnItemRemoved(ObservableList<Widget> sender, ListChangedEventArgs<Widget> e) |
|||
{ |
|||
if (e.item != null) |
|||
{ |
|||
e.item.panel = null; |
|||
e.item.parent = null; |
|||
} |
|||
|
|||
SetDirty(); |
|||
} |
|||
|
|||
public void SetDirty() |
|||
{ |
|||
foreach (var child in children) |
|||
child.GenerateQueryPath(); |
|||
|
|||
onSetDirty(this); |
|||
} |
|||
|
|||
public override int GetHashCode() |
|||
{ |
|||
int hash = 17; |
|||
hash = hash * 23 + displayName.GetHashCode(); |
|||
|
|||
foreach (var child in children) |
|||
hash = hash * 23 + child.GetHashCode(); |
|||
|
|||
return hash; |
|||
} |
|||
} |
|||
} |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: 9a33c6b643214f847b2e0cf1721a64db |
|||
MonoImporter: |
|||
externalObjects: {} |
|||
serializedVersion: 2 |
|||
defaultReferences: [] |
|||
executionOrder: 0 |
|||
icon: {instanceID: 0} |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
using System; |
|||
using UnityEngine.Assertions; |
|||
|
|||
namespace UnityEngine.Experimental.Rendering |
|||
{ |
|||
public partial class DebugUI |
|||
{ |
|||
[Flags] |
|||
public enum Flags |
|||
{ |
|||
None = 0, |
|||
EditorOnly = 1 << 1, |
|||
RuntimeOnly = 1 << 2 |
|||
} |
|||
|
|||
// Base class for all debug UI widgets
|
|||
public abstract class Widget |
|||
{ |
|||
// Set to null until it's added to a panel, be careful
|
|||
protected Panel m_Panel; |
|||
public virtual Panel panel |
|||
{ |
|||
get { return m_Panel; } |
|||
internal set { m_Panel = value; } |
|||
} |
|||
|
|||
protected IContainer m_Parent; |
|||
public virtual IContainer parent |
|||
{ |
|||
get { return m_Parent; } |
|||
internal set { m_Parent = value; } |
|||
} |
|||
|
|||
public Flags flags { get; set; } |
|||
public string displayName { get; set; } |
|||
|
|||
public string queryPath { get; private set; } |
|||
|
|||
public bool isEditorOnly { get { return (flags & Flags.EditorOnly) != 0; } } |
|||
public bool isRuntimeOnly { get { return (flags & Flags.RuntimeOnly) != 0; } } |
|||
|
|||
internal virtual void GenerateQueryPath() |
|||
{ |
|||
queryPath = displayName.Trim(); |
|||
|
|||
if (m_Parent != null) |
|||
queryPath = m_Parent.queryPath + " -> " + queryPath; |
|||
} |
|||
|
|||
public override int GetHashCode() |
|||
{ |
|||
return queryPath.GetHashCode(); |
|||
} |
|||
|
|||
public void RemoveSelf() |
|||
{ |
|||
if (parent != null) |
|||
parent.children.Remove(this); |
|||
} |
|||
} |
|||
|
|||
// Any widget that can holds other widgets must implement this interface
|
|||
public interface IContainer |
|||
{ |
|||
ObservableList<Widget> children { get; } |
|||
string displayName { get; set; } |
|||
string queryPath { get; } |
|||
} |
|||
|
|||
// Any widget that implements this will be considered for serialization (only if the setter
|
|||
// is set and thus is not read-only)
|
|||
public interface IValueField |
|||
{ |
|||
object GetValue(); |
|||
void SetValue(object value); |
|||
object ValidateValue(object value); |
|||
} |
|||
|
|||
// Miscellaneous
|
|||
public class Button : Widget |
|||
{ |
|||
public Action action { get; set; } |
|||
} |
|||
|
|||
public class Value : Widget |
|||
{ |
|||
public Func<object> getter { get; set; } |
|||
|
|||
// Runtime-only
|
|||
public float refreshRate = 0.1f; |
|||
|
|||
public object GetValue() |
|||
{ |
|||
Assert.IsNotNull(getter); |
|||
return getter(); |
|||
} |
|||
} |
|||
} |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: 4cce618ad8a6d934dbdc631f979b3aa6 |
|||
MonoImporter: |
|||
externalObjects: {} |
|||
serializedVersion: 2 |
|||
defaultReferences: [] |
|||
executionOrder: 0 |
|||
icon: {instanceID: 0} |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
namespace UnityEngine.Experimental.Rendering |
|||
{ |
|||
public class DebugUpdater : MonoBehaviour |
|||
{ |
|||
[RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.AfterSceneLoad)] |
|||
static void RuntimeInit() |
|||
{ |
|||
if (FindObjectOfType<DebugUpdater>() != null) |
|||
return; |
|||
|
|||
var go = new GameObject { name = "[Debug Updater]" }; |
|||
go.AddComponent<DebugUpdater>(); |
|||
DontDestroyOnLoad(go); |
|||
} |
|||
|
|||
void Update() |
|||
{ |
|||
DebugManager.instance.UpdateActions(); |
|||
|
|||
if (DebugManager.instance.GetAction(DebugAction.EnableDebugMenu) != 0.0f) |
|||
DebugManager.instance.displayRuntimeUI = !DebugManager.instance.displayRuntimeUI; |
|||
} |
|||
} |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: 6fa749f6d8ed4b441af9aa005fe0f895 |
|||
MonoImporter: |
|||
externalObjects: {} |
|||
serializedVersion: 2 |
|||
defaultReferences: [] |
|||
executionOrder: 0 |
|||
icon: {instanceID: 0} |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
fileFormatVersion: 2 |
|||
guid: d2160913896effa4aa65b93012ff3465 |
|||
folderAsset: yes |
|||
DefaultImporter: |
|||
externalObjects: {} |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
fileFormatVersion: 2 |
|||
guid: a6209f4861b884a41ba167d4c8b50646 |
|||
folderAsset: yes |
|||
DefaultImporter: |
|||
externalObjects: {} |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
using System; |
|||
using UnityEngine; |
|||
using UnityEngine.Experimental.Rendering; |
|||
|
|||
namespace UnityEditor.Experimental.Rendering |
|||
{ |
|||
[Serializable] |
|||
public abstract class DebugState : ScriptableObject |
|||
{ |
|||
[SerializeField] |
|||
protected string m_QueryPath; |
|||
|
|||
public string queryPath |
|||
{ |
|||
get { return m_QueryPath; } |
|||
internal set { m_QueryPath = value; } |
|||
} |
|||
|
|||
public abstract object GetValue(); |
|||
|
|||
public abstract void SetValue(object value, DebugUI.IValueField field); |
|||
|
|||
public virtual void OnEnable() |
|||
{ |
|||
hideFlags = HideFlags.HideAndDontSave; |
|||
} |
|||
} |
|||
|
|||
[Serializable] |
|||
public class DebugState<T> : DebugState |
|||
{ |
|||
[SerializeField] |
|||
protected T m_Value; |
|||
|
|||
public virtual T value |
|||
{ |
|||
get { return m_Value; } |
|||
set { m_Value = value; } |
|||
} |
|||
|
|||
public override object GetValue() |
|||
{ |
|||
return value; |
|||
} |
|||
|
|||
public override void SetValue(object value, DebugUI.IValueField field) |
|||
{ |
|||
this.value = (T)field.ValidateValue(value); |
|||
} |
|||
|
|||
public override int GetHashCode() |
|||
{ |
|||
unchecked |
|||
{ |
|||
int hash = 13; |
|||
hash = hash * 23 + m_QueryPath.GetHashCode(); |
|||
hash = hash * 23 + m_Value.GetHashCode(); |
|||
return hash; |
|||
} |
|||
} |
|||
} |
|||
|
|||
public sealed class DebugStateAttribute : Attribute |
|||
{ |
|||
public readonly Type[] types; |
|||
|
|||
public DebugStateAttribute(params Type[] types) |
|||
{ |
|||
this.types = types; |
|||
} |
|||
} |
|||
|
|||
// Builtins
|
|||
[Serializable, DebugState(typeof(DebugUI.BoolField), typeof(DebugUI.Foldout))] |
|||
public sealed class DebugStateBool : DebugState<bool> { } |
|||
|
|||
[Serializable, DebugState(typeof(DebugUI.IntField), typeof(DebugUI.EnumField))] |
|||
public sealed class DebugStateInt : DebugState<int> { } |
|||
|
|||
[Serializable, DebugState(typeof(DebugUI.UIntField))] |
|||
public sealed class DebugStateUInt : DebugState<uint> { } |
|||
|
|||
[Serializable, DebugState(typeof(DebugUI.FloatField))] |
|||
public sealed class DebugStateFloat : DebugState<float> { } |
|||
|
|||
[Serializable, DebugState(typeof(DebugUI.ColorField))] |
|||
public sealed class DebugStateColor : DebugState<Color> { } |
|||
|
|||
[Serializable, DebugState(typeof(DebugUI.Vector2Field))] |
|||
public sealed class DebugStateVector2 : DebugState<Vector2> { } |
|||
|
|||
[Serializable, DebugState(typeof(DebugUI.Vector3Field))] |
|||
public sealed class DebugStateVector3 : DebugState<Vector3> { } |
|||
|
|||
[Serializable, DebugState(typeof(DebugUI.Vector4Field))] |
|||
public sealed class DebugStateVector4 : DebugState<Vector4> { } |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: 7270f3dffc138834da5642e5943f5072 |
|||
MonoImporter: |
|||
externalObjects: {} |
|||
serializedVersion: 2 |
|||
defaultReferences: [] |
|||
executionOrder: 0 |
|||
icon: {instanceID: 0} |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
using UnityEngine; |
|||
using UnityEngine.Experimental.Rendering; |
|||
|
|||
namespace UnityEditor.Experimental.Rendering |
|||
{ |
|||
[DebugUIDrawer(typeof(DebugUI.Value))] |
|||
public sealed class DebugUIDrawerValue : DebugUIDrawer |
|||
{ |
|||
public override bool OnGUI(DebugUI.Widget widget, DebugState state) |
|||
{ |
|||
var w = Cast<DebugUI.Value>(widget); |
|||
var rect = PrepareControlRect(); |
|||
EditorGUI.LabelField(rect, CoreEditorUtils.GetContent(w.displayName), CoreEditorUtils.GetContent(w.GetValue().ToString())); |
|||
return true; |
|||
} |
|||
} |
|||
|
|||
[DebugUIDrawer(typeof(DebugUI.Button))] |
|||
public sealed class DebugUIDrawerButton : DebugUIDrawer |
|||
{ |
|||
public override bool OnGUI(DebugUI.Widget widget, DebugState state) |
|||
{ |
|||
var w = Cast<DebugUI.Button>(widget); |
|||
|
|||
var rect = EditorGUI.IndentedRect(EditorGUILayout.GetControlRect()); |
|||
if (GUI.Button(rect, w.displayName, EditorStyles.miniButton)) |
|||
{ |
|||
if (w.action != null) |
|||
w.action(); |
|||
} |
|||
|
|||
return true; |
|||
} |
|||
} |
|||
|
|||
[DebugUIDrawer(typeof(DebugUI.BoolField))] |
|||
public sealed class DebugUIDrawerBoolField : DebugUIDrawer |
|||
{ |
|||
public override bool OnGUI(DebugUI.Widget widget, DebugState state) |
|||
{ |
|||
var w = Cast<DebugUI.BoolField>(widget); |
|||
var s = Cast<DebugStateBool>(state); |
|||
|
|||
EditorGUI.BeginChangeCheck(); |
|||
|
|||
var rect = PrepareControlRect(); |
|||
bool value = EditorGUI.Toggle(rect, CoreEditorUtils.GetContent(w.displayName), s.value); |
|||
|
|||
if (EditorGUI.EndChangeCheck()) |
|||
Apply(w, s, value); |
|||
|
|||
return true; |
|||
} |
|||
} |
|||
|
|||
[DebugUIDrawer(typeof(DebugUI.IntField))] |
|||
public sealed class DebugUIDrawerIntField : DebugUIDrawer |
|||
{ |
|||
public override bool OnGUI(DebugUI.Widget widget, DebugState state) |
|||
{ |
|||
var w = Cast<DebugUI.IntField>(widget); |
|||
var s = Cast<DebugStateInt>(state); |
|||
|
|||
EditorGUI.BeginChangeCheck(); |
|||
|
|||
var rect = PrepareControlRect(); |
|||
int value = w.min != null && w.max != null |
|||
? EditorGUI.IntSlider(rect, CoreEditorUtils.GetContent(w.displayName), s.value, w.min(), w.max()) |
|||
: EditorGUI.IntField(rect, CoreEditorUtils.GetContent(w.displayName), s.value); |
|||
|
|||
if (EditorGUI.EndChangeCheck()) |
|||
Apply(w, s, value); |
|||
|
|||
return true; |
|||
} |
|||
} |
|||
|
|||
[DebugUIDrawer(typeof(DebugUI.UIntField))] |
|||
public sealed class DebugUIDrawerUIntField : DebugUIDrawer |
|||
{ |
|||
public override bool OnGUI(DebugUI.Widget widget, DebugState state) |
|||
{ |
|||
var w = Cast<DebugUI.UIntField>(widget); |
|||
var s = Cast<DebugStateUInt>(state); |
|||
|
|||
EditorGUI.BeginChangeCheck(); |
|||
|
|||
// No UIntField so we need to max to 0 ourselves or the value will wrap around
|
|||
var rect = PrepareControlRect(); |
|||
int tmp = w.min != null && w.max != null |
|||
? EditorGUI.IntSlider(rect, CoreEditorUtils.GetContent(w.displayName), Mathf.Max(0, (int)s.value), Mathf.Max(0, (int)w.min()), Mathf.Max(0, (int)w.max())) |
|||
: EditorGUI.IntField(rect, CoreEditorUtils.GetContent(w.displayName), Mathf.Max(0, (int)s.value)); |
|||
|
|||
uint value = (uint)Mathf.Max(0, tmp); |
|||
|
|||
if (EditorGUI.EndChangeCheck()) |
|||
Apply(w, s, value); |
|||
|
|||
return true; |
|||
} |
|||
} |
|||
|
|||
[DebugUIDrawer(typeof(DebugUI.FloatField))] |
|||
public sealed class DebugUIDrawerFloatField : DebugUIDrawer |
|||
{ |
|||
public override bool OnGUI(DebugUI.Widget widget, DebugState state) |
|||
{ |
|||
var w = Cast<DebugUI.FloatField>(widget); |
|||
var s = Cast<DebugStateFloat>(state); |
|||
|
|||
EditorGUI.BeginChangeCheck(); |
|||
|
|||
var rect = PrepareControlRect(); |
|||
float value = w.min != null && w.max != null |
|||
? EditorGUI.Slider(rect, CoreEditorUtils.GetContent(w.displayName), s.value, w.min(), w.max()) |
|||
: EditorGUI.FloatField(rect, CoreEditorUtils.GetContent(w.displayName), s.value); |
|||
|
|||
if (EditorGUI.EndChangeCheck()) |
|||
Apply(w, s, value); |
|||
|
|||
return true; |
|||
} |
|||
} |
|||
|
|||
[DebugUIDrawer(typeof(DebugUI.EnumField))] |
|||
public sealed class DebugUIDrawerEnumField : DebugUIDrawer |
|||
{ |
|||
public override bool OnGUI(DebugUI.Widget widget, DebugState state) |
|||
{ |
|||
var w = Cast<DebugUI.EnumField>(widget); |
|||
var s = Cast<DebugStateInt>(state); |
|||
|
|||
EditorGUI.BeginChangeCheck(); |
|||
|
|||
int value = s.value; |
|||
if (w.enumNames == null || w.enumValues == null) |
|||
{ |
|||
EditorGUILayout.LabelField("Can't draw an empty enumeration."); |
|||
} |
|||
else |
|||
{ |
|||
var rect = PrepareControlRect(); |
|||
value = EditorGUI.IntPopup(rect, CoreEditorUtils.GetContent(w.displayName), s.value, w.enumNames, w.enumValues); |
|||
} |
|||
|
|||
if (EditorGUI.EndChangeCheck()) |
|||
Apply(w, s, value); |
|||
|
|||
return true; |
|||
} |
|||
} |
|||
|
|||
[DebugUIDrawer(typeof(DebugUI.Foldout))] |
|||
public sealed class DebugUIDrawerFoldout : DebugUIDrawer |
|||
{ |
|||
public override void Begin(DebugUI.Widget widget, DebugState state) |
|||
{ |
|||
var w = Cast<DebugUI.Foldout>(widget); |
|||
var s = Cast<DebugStateBool>(state); |
|||
|
|||
EditorGUI.BeginChangeCheck(); |
|||
|
|||
bool value = EditorGUILayout.Foldout(s.value, CoreEditorUtils.GetContent(w.displayName), true); |
|||
|
|||
if (EditorGUI.EndChangeCheck()) |
|||
Apply(w, s, value); |
|||
|
|||
EditorGUI.indentLevel++; |
|||
} |
|||
|
|||
public override bool OnGUI(DebugUI.Widget node, DebugState state) |
|||
{ |
|||
var s = Cast<DebugStateBool>(state); |
|||
return s.value; |
|||
} |
|||
|
|||
public override void End(DebugUI.Widget node, DebugState state) |
|||
{ |
|||
EditorGUI.indentLevel--; |
|||
} |
|||
} |
|||
|
|||
[DebugUIDrawer(typeof(DebugUI.ColorField))] |
|||
public sealed class DebugUIDrawerColorField : DebugUIDrawer |
|||
{ |
|||
public override bool OnGUI(DebugUI.Widget widget, DebugState state) |
|||
{ |
|||
var w = Cast<DebugUI.ColorField>(widget); |
|||
var s = Cast<DebugStateColor>(state); |
|||
|
|||
EditorGUI.BeginChangeCheck(); |
|||
|
|||
var rect = PrepareControlRect(); |
|||
var value = EditorGUI.ColorField(rect, CoreEditorUtils.GetContent(w.displayName), s.value, w.showPicker, w.showAlpha, w.hdr); |
|||
|
|||
if (EditorGUI.EndChangeCheck()) |
|||
Apply(w, s, value); |
|||
|
|||
return true; |
|||
} |
|||
} |
|||
|
|||
[DebugUIDrawer(typeof(DebugUI.Vector2Field))] |
|||
public sealed class DebugUIDrawerVector2Field : DebugUIDrawer |
|||
{ |
|||
public override bool OnGUI(DebugUI.Widget widget, DebugState state) |
|||
{ |
|||
var w = Cast<DebugUI.Vector2Field>(widget); |
|||
var s = Cast<DebugStateVector2>(state); |
|||
|
|||
EditorGUI.BeginChangeCheck(); |
|||
|
|||
var value = EditorGUILayout.Vector2Field(w.displayName, s.value); |
|||
|
|||
if (EditorGUI.EndChangeCheck()) |
|||
Apply(w, s, value); |
|||
|
|||
return true; |
|||
} |
|||
} |
|||
|
|||
[DebugUIDrawer(typeof(DebugUI.Vector3Field))] |
|||
public sealed class DebugUIDrawerVector3Field : DebugUIDrawer |
|||
{ |
|||
public override bool OnGUI(DebugUI.Widget widget, DebugState state) |
|||
{ |
|||
var w = Cast<DebugUI.Vector3Field>(widget); |
|||
var s = Cast<DebugStateVector3>(state); |
|||
|
|||
EditorGUI.BeginChangeCheck(); |
|||
|
|||
var value = EditorGUILayout.Vector3Field(w.displayName, s.value); |
|||
|
|||
if (EditorGUI.EndChangeCheck()) |
|||
Apply(w, s, value); |
|||
|
|||
return true; |
|||
} |
|||
} |
|||
|
|||
[DebugUIDrawer(typeof(DebugUI.Vector4Field))] |
|||
public sealed class DebugUIDrawerVector4Field : DebugUIDrawer |
|||
{ |
|||
public override bool OnGUI(DebugUI.Widget widget, DebugState state) |
|||
{ |
|||
var w = Cast<DebugUI.Vector4Field>(widget); |
|||
var s = Cast<DebugStateVector4>(state); |
|||
|
|||
EditorGUI.BeginChangeCheck(); |
|||
|
|||
var value = EditorGUILayout.Vector4Field(w.displayName, s.value); |
|||
|
|||
if (EditorGUI.EndChangeCheck()) |
|||
Apply(w, s, value); |
|||
|
|||
return true; |
|||
} |
|||
} |
|||
|
|||
[DebugUIDrawer(typeof(DebugUI.Container))] |
|||
public sealed class DebugUIDrawerContainer : DebugUIDrawer |
|||
{ |
|||
public override void Begin(DebugUI.Widget widget, DebugState state) |
|||
{ |
|||
if (!string.IsNullOrEmpty(widget.displayName)) |
|||
EditorGUILayout.LabelField(widget.displayName, EditorStyles.boldLabel); |
|||
|
|||
EditorGUI.indentLevel++; |
|||
} |
|||
|
|||
public override void End(DebugUI.Widget widget, DebugState state) |
|||
{ |
|||
EditorGUI.indentLevel--; |
|||
} |
|||
} |
|||
|
|||
[DebugUIDrawer(typeof(DebugUI.HBox))] |
|||
public sealed class DebugUIDrawerHBox : DebugUIDrawer |
|||
{ |
|||
public override void Begin(DebugUI.Widget widget, DebugState state) |
|||
{ |
|||
EditorGUILayout.BeginHorizontal(); |
|||
} |
|||
|
|||
public override void End(DebugUI.Widget widget, DebugState state) |
|||
{ |
|||
EditorGUILayout.EndHorizontal(); |
|||
} |
|||
} |
|||
|
|||
[DebugUIDrawer(typeof(DebugUI.VBox))] |
|||
public sealed class DebugUIDrawerVBox : DebugUIDrawer |
|||
{ |
|||
public override void Begin(DebugUI.Widget widget, DebugState state) |
|||
{ |
|||
EditorGUILayout.BeginVertical(); |
|||
} |
|||
|
|||
public override void End(DebugUI.Widget widget, DebugState state) |
|||
{ |
|||
EditorGUILayout.EndVertical(); |
|||
} |
|||
} |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: 7f9e548e5e2920b47987881c21171ef6 |
|||
MonoImporter: |
|||
externalObjects: {} |
|||
serializedVersion: 2 |
|||
defaultReferences: [] |
|||
executionOrder: 0 |
|||
icon: {instanceID: 0} |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
using System; |
|||
using UnityEngine; |
|||
using UnityEngine.Experimental.Rendering; |
|||
|
|||
namespace UnityEditor.Experimental.Rendering |
|||
{ |
|||
public class DebugUIDrawerAttribute : Attribute |
|||
{ |
|||
public readonly Type type; |
|||
|
|||
public DebugUIDrawerAttribute(Type type) |
|||
{ |
|||
this.type = type; |
|||
} |
|||
} |
|||
|
|||
public class DebugUIDrawer |
|||
{ |
|||
protected T Cast<T>(object o) |
|||
where T : class |
|||
{ |
|||
var casted = o as T; |
|||
string typeName = o == null ? "null" : o.GetType().ToString(); |
|||
|
|||
if (casted == null) |
|||
throw new InvalidOperationException("Can't cast " + typeName + " to " + typeof(T)); |
|||
|
|||
return casted; |
|||
} |
|||
|
|||
public virtual void Begin(DebugUI.Widget widget, DebugState state) |
|||
{ } |
|||
|
|||
public virtual bool OnGUI(DebugUI.Widget widget, DebugState state) |
|||
{ |
|||
return true; |
|||
} |
|||
|
|||
public virtual void End(DebugUI.Widget widget, DebugState state) |
|||
{ } |
|||
|
|||
protected void Apply(DebugUI.IValueField widget, DebugState state, object value) |
|||
{ |
|||
Undo.RegisterCompleteObjectUndo(state, "Debug Property Change"); |
|||
state.SetValue(value, widget); |
|||
widget.SetValue(value); |
|||
EditorUtility.SetDirty(state); |
|||
UnityEditorInternal.InternalEditorUtility.RepaintAllViews(); |
|||
} |
|||
|
|||
protected Rect PrepareControlRect(float height = -1) |
|||
{ |
|||
if (height < 0) |
|||
height = EditorGUIUtility.singleLineHeight; |
|||
var rect = GUILayoutUtility.GetRect(1f, 1f, height, height); |
|||
rect.width -= 2f; |
|||
rect.xMin += 2f; |
|||
EditorGUIUtility.labelWidth = rect.width / 2f; |
|||
return rect; |
|||
} |
|||
} |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: 3581d3ff7a65eee458feb865b7f29154 |
|||
MonoImporter: |
|||
externalObjects: {} |
|||
serializedVersion: 2 |
|||
defaultReferences: [] |
|||
executionOrder: 0 |
|||
icon: {instanceID: 0} |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
using System; |
|||
using System.Linq; |
|||
using UnityEditor; |
|||
using UnityEditor.Experimental.Rendering; |
|||
using UnityEditorInternal; |
|||
|
|||
namespace UnityEngine.Experimental.Rendering.UI |
|||
{ |
|||
[CustomEditor(typeof(DebugUIHandlerCanvas))] |
|||
public sealed class DebugUIHandlerCanvasEditor : Editor |
|||
{ |
|||
SerializedProperty m_PanelPrefab; |
|||
SerializedProperty m_Prefabs; |
|||
ReorderableList m_PrefabList; |
|||
|
|||
static string[] s_Types; // Assembly qualified names
|
|||
static string[] s_DisplayTypes; // Pretty names
|
|||
|
|||
static DebugUIHandlerCanvasEditor() |
|||
{ |
|||
s_Types = CoreUtils.GetAllAssemblyTypes() |
|||
.Where(t => t.IsSubclassOf(typeof(DebugUI.Widget)) && !t.IsAbstract) |
|||
.Select(t => t.AssemblyQualifiedName) |
|||
.ToArray(); |
|||
|
|||
s_DisplayTypes = new string[s_Types.Length]; |
|||
for (int i = 0; i < s_Types.Length; i++) |
|||
s_DisplayTypes[i] = Type.GetType(s_Types[i]).Name; |
|||
} |
|||
|
|||
void OnEnable() |
|||
{ |
|||
var o = new PropertyFetcher<DebugUIHandlerCanvas>(serializedObject); |
|||
m_PanelPrefab = o.Find(x => x.panelPrefab); |
|||
m_Prefabs = o.Find(x => x.prefabs); |
|||
|
|||
m_PrefabList = new ReorderableList(serializedObject, m_Prefabs, true, true, true, true) |
|||
{ |
|||
drawHeaderCallback = rect => EditorGUI.LabelField(rect, "Widget Prefabs"), |
|||
drawElementCallback = (rect, index, isActive, isFocused) => |
|||
{ |
|||
var element = m_PrefabList.serializedProperty.GetArrayElementAtIndex(index); |
|||
rect.y += 2f; |
|||
const float kTypeWidth = 100f; |
|||
|
|||
// Type selector
|
|||
var typeProp = element.FindPropertyRelative("type"); |
|||
int typeIndex = ArrayUtility.IndexOf(s_Types, typeProp.stringValue); |
|||
typeIndex = Mathf.Max(typeIndex, 0); |
|||
typeIndex = EditorGUI.Popup(new Rect(rect.x, rect.y, kTypeWidth, EditorGUIUtility.singleLineHeight), typeIndex, s_DisplayTypes); |
|||
typeProp.stringValue = s_Types[typeIndex]; |
|||
|
|||
// Prefab
|
|||
EditorGUI.PropertyField( |
|||
new Rect(rect.x + kTypeWidth + 2f, rect.y, rect.width - kTypeWidth - 2f, EditorGUIUtility.singleLineHeight), |
|||
element.FindPropertyRelative("prefab"), GUIContent.none); |
|||
}, |
|||
onSelectCallback = list => |
|||
{ |
|||
var prefab = list.serializedProperty.GetArrayElementAtIndex(list.index).FindPropertyRelative("prefab").objectReferenceValue as GameObject; |
|||
if (prefab) |
|||
EditorGUIUtility.PingObject(prefab.gameObject); |
|||
} |
|||
}; |
|||
} |
|||
|
|||
public override void OnInspectorGUI() |
|||
{ |
|||
serializedObject.Update(); |
|||
|
|||
EditorGUILayout.PropertyField(m_PanelPrefab); |
|||
EditorGUILayout.Space(); |
|||
m_PrefabList.DoLayoutList(); |
|||
|
|||
serializedObject.ApplyModifiedProperties(); |
|||
} |
|||
} |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: f1d41f85c15ac6048a850b51ff36c098 |
|||
MonoImporter: |
|||
externalObjects: {} |
|||
serializedVersion: 2 |
|||
defaultReferences: [] |
|||
executionOrder: 0 |
|||
icon: {instanceID: 0} |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Linq; |
|||
using UnityEditor.Callbacks; |
|||
using UnityEngine; |
|||
using UnityEngine.Experimental.Rendering; |
|||
|
|||
namespace UnityEditor.Experimental.Rendering |
|||
{ |
|||
#pragma warning disable 414
|
|||
|
|||
[Serializable] |
|||
sealed class WidgetStateDictionary : SerializedDictionary<string, DebugState> { } |
|||
|
|||
sealed class DebugWindowSettings : ScriptableObject |
|||
{ |
|||
// Keep these settings in a separate scriptable object so we can handle undo/redo on them
|
|||
// without the rest of the debug window interfering
|
|||
public int currentStateHash; |
|||
public int selectedPanel; |
|||
|
|||
void OnEnable() |
|||
{ |
|||
hideFlags = HideFlags.HideAndDontSave; |
|||
} |
|||
} |
|||
|
|||
public sealed class DebugWindow : EditorWindow |
|||
{ |
|||
static Styles s_Styles; |
|||
|
|||
[SerializeField] |
|||
WidgetStateDictionary m_WidgetStates; |
|||
|
|||
[SerializeField] |
|||
DebugWindowSettings m_Settings; |
|||
|
|||
[SerializeField] |
|||
int m_DebugTreeState; |
|||
|
|||
bool m_IsDirty; |
|||
|
|||
Vector2 m_PanelScroll; |
|||
Vector2 m_ContentScroll; |
|||
|
|||
static bool s_TypeMapDirty; |
|||
static Dictionary<Type, Type> s_WidgetStateMap; // DebugUI.Widget type -> DebugState type
|
|||
static Dictionary<Type, DebugUIDrawer> s_WidgetDrawerMap; // DebugUI.Widget type -> DebugUIDrawer
|
|||
|
|||
[DidReloadScripts] |
|||
static void OnEditorReload() |
|||
{ |
|||
s_TypeMapDirty = true; |
|||
} |
|||
|
|||
static void RebuildTypeMaps() |
|||
{ |
|||
var assemblyTypes = CoreUtils.GetAllAssemblyTypes(); |
|||
|
|||
// Map states to widget (a single state can map to several widget types if the value to
|
|||
// serialize is the same)
|
|||
var attrType = typeof(DebugStateAttribute); |
|||
var stateTypes = assemblyTypes |
|||
.Where( |
|||
t => t.IsSubclassOf(typeof(DebugState)) |
|||
&& t.IsDefined(attrType, false) |
|||
&& !t.IsAbstract |
|||
); |
|||
|
|||
s_WidgetStateMap = new Dictionary<Type, Type>(); |
|||
|
|||
foreach (var stateType in stateTypes) |
|||
{ |
|||
var attr = (DebugStateAttribute)stateType.GetCustomAttributes(attrType, false)[0]; |
|||
|
|||
foreach (var t in attr.types) |
|||
s_WidgetStateMap.Add(t, stateType); |
|||
} |
|||
|
|||
// Drawers
|
|||
attrType = typeof(DebugUIDrawerAttribute); |
|||
var types = assemblyTypes |
|||
.Where( |
|||
t => t.IsSubclassOf(typeof(DebugUIDrawer)) |
|||
&& t.IsDefined(attrType, false) |
|||
&& !t.IsAbstract |
|||
); |
|||
|
|||
s_WidgetDrawerMap = new Dictionary<Type, DebugUIDrawer>(); |
|||
|
|||
foreach (var t in types) |
|||
{ |
|||
var attr = (DebugUIDrawerAttribute)t.GetCustomAttributes(attrType, false)[0]; |
|||
var inst = (DebugUIDrawer)Activator.CreateInstance(t); |
|||
s_WidgetDrawerMap.Add(attr.type, inst); |
|||
} |
|||
|
|||
// Done
|
|||
s_TypeMapDirty = false; |
|||
} |
|||
|
|||
[MenuItem("Window/Render Pipeline/Debug Window", priority = CoreUtils.editMenuPriority2)] |
|||
static void Init() |
|||
{ |
|||
var window = GetWindow<DebugWindow>(); |
|||
window.titleContent = new GUIContent("Debugging"); |
|||
} |
|||
|
|||
void OnEnable() |
|||
{ |
|||
hideFlags = HideFlags.HideAndDontSave; |
|||
autoRepaintOnSceneChange = true; |
|||
|
|||
if (m_Settings == null) |
|||
m_Settings = CreateInstance<DebugWindowSettings>(); |
|||
|
|||
if (m_WidgetStates == null) |
|||
m_WidgetStates = new WidgetStateDictionary(); |
|||
|
|||
if (s_WidgetStateMap == null || s_WidgetDrawerMap == null || s_TypeMapDirty) |
|||
RebuildTypeMaps(); |
|||
|
|||
Undo.undoRedoPerformed += OnUndoRedoPerformed; |
|||
DebugManager.instance.onSetDirty += MarkDirty; |
|||
|
|||
// First init
|
|||
m_DebugTreeState = DebugManager.instance.GetState(); |
|||
UpdateWidgetStates(); |
|||
} |
|||
|
|||
// Note: this won't get called if the window is opened when the editor itself is closed
|
|||
void OnDestroy() |
|||
{ |
|||
DebugManager.instance.onSetDirty -= MarkDirty; |
|||
|
|||
if (m_WidgetStates != null) |
|||
{ |
|||
// Clear all the states from memory
|
|||
foreach (var state in m_WidgetStates) |
|||
{ |
|||
var s = state.Value; |
|||
Undo.ClearUndo(s); // Don't leave dangling states in the global undo/redo stack
|
|||
DestroyImmediate(s); |
|||
} |
|||
|
|||
m_WidgetStates.Clear(); |
|||
} |
|||
} |
|||
|
|||
void MarkDirty() |
|||
{ |
|||
m_IsDirty = true; |
|||
} |
|||
|
|||
// We use item states to keep a cached value of each serializable debug items in order to
|
|||
// handle domain reloads, play mode entering/exiting and undo/redo
|
|||
// Note: no removal of orphan states
|
|||
void UpdateWidgetStates() |
|||
{ |
|||
foreach (var panel in DebugManager.instance.panels) |
|||
UpdateWidgetStates(panel); |
|||
} |
|||
|
|||
void UpdateWidgetStates(DebugUI.IContainer container) |
|||
{ |
|||
// Skip runtime only containers, we won't draw them so no need to serialize them either
|
|||
var actualWidget = container as DebugUI.Widget; |
|||
if (actualWidget != null && actualWidget.isRuntimeOnly) |
|||
return; |
|||
|
|||
// Recursively update widget states
|
|||
foreach (var widget in container.children) |
|||
{ |
|||
// Skip non-serializable widgets but still traverse them in case one of their
|
|||
// children needs serialization support
|
|||
var valueField = widget as DebugUI.IValueField; |
|||
if (valueField != null) |
|||
{ |
|||
// Skip runtime & readonly only items
|
|||
if (widget.isRuntimeOnly) |
|||
return; |
|||
|
|||
var widgetType = widget.GetType(); |
|||
string guid = widget.queryPath; |
|||
Type stateType; |
|||
s_WidgetStateMap.TryGetValue(widgetType, out stateType); |
|||
|
|||
// Create missing states & recreate the ones that are null
|
|||
if (stateType != null) |
|||
{ |
|||
if (!m_WidgetStates.ContainsKey(guid) || m_WidgetStates[guid] == null) |
|||
{ |
|||
var inst = (DebugState)CreateInstance(stateType); |
|||
inst.queryPath = guid; |
|||
inst.SetValue(valueField.GetValue(), valueField); |
|||
m_WidgetStates[guid] = inst; |
|||
} |
|||
} |
|||
} |
|||
|
|||
// Recurse if the widget is a container
|
|||
var containerField = widget as DebugUI.IContainer; |
|||
if (containerField != null) |
|||
UpdateWidgetStates(containerField); |
|||
} |
|||
} |
|||
|
|||
public void ApplyStates() |
|||
{ |
|||
foreach (var state in m_WidgetStates) |
|||
{ |
|||
var widget = DebugManager.instance.GetItem(state.Key) as DebugUI.IValueField; |
|||
|
|||
if (widget == null) |
|||
continue; |
|||
|
|||
widget.SetValue(state.Value.GetValue()); |
|||
} |
|||
} |
|||
|
|||
void OnUndoRedoPerformed() |
|||
{ |
|||
int stateHash = ComputeStateHash(); |
|||
|
|||
// Something has been undone / redone, re-apply states to the debug tree
|
|||
if (stateHash != m_Settings.currentStateHash) |
|||
{ |
|||
ApplyStates(); |
|||
m_Settings.currentStateHash = stateHash; |
|||
} |
|||
|
|||
Repaint(); |
|||
} |
|||
|
|||
int ComputeStateHash() |
|||
{ |
|||
unchecked |
|||
{ |
|||
int hash = 13; |
|||
|
|||
foreach (var state in m_WidgetStates) |
|||
hash = hash * 23 + state.Value.GetHashCode(); |
|||
|
|||
return hash; |
|||
} |
|||
} |
|||
|
|||
void Update() |
|||
{ |
|||
int treeState = DebugManager.instance.GetState(); |
|||
|
|||
if (m_DebugTreeState != treeState || m_IsDirty) |
|||
{ |
|||
UpdateWidgetStates(); |
|||
ApplyStates(); |
|||
m_DebugTreeState = treeState; |
|||
m_IsDirty = false; |
|||
} |
|||
} |
|||
|
|||
void OnGUI() |
|||
{ |
|||
if (s_Styles == null) |
|||
s_Styles = new Styles(); |
|||
|
|||
var panels = DebugManager.instance.panels; |
|||
int itemCount = panels.Count(x => !x.isRuntimeOnly && x.children.Count(w => !w.isRuntimeOnly) > 0); |
|||
|
|||
if (itemCount == 0) |
|||
{ |
|||
EditorGUILayout.HelpBox("No debug item found.", MessageType.Info); |
|||
return; |
|||
} |
|||
|
|||
// Background color
|
|||
var wrect = position; |
|||
wrect.x = 0; |
|||
wrect.y = 0; |
|||
var oldColor = GUI.color; |
|||
GUI.color = s_Styles.skinBackgroundColor; |
|||
GUI.DrawTexture(wrect, EditorGUIUtility.whiteTexture); |
|||
GUI.color = oldColor; |
|||
|
|||
using (new EditorGUILayout.HorizontalScope()) |
|||
{ |
|||
// Side bar
|
|||
using (var scrollScope = new EditorGUILayout.ScrollViewScope(m_PanelScroll, s_Styles.sectionScrollView, GUILayout.Width(150f))) |
|||
{ |
|||
GUILayout.Space(40f); |
|||
|
|||
if (m_Settings.selectedPanel >= panels.Count) |
|||
m_Settings.selectedPanel = 0; |
|||
|
|||
// Validate container id
|
|||
while (panels[m_Settings.selectedPanel].isRuntimeOnly || panels[m_Settings.selectedPanel].children.Count(x => !x.isRuntimeOnly) == 0) |
|||
{ |
|||
m_Settings.selectedPanel++; |
|||
|
|||
if (m_Settings.selectedPanel >= panels.Count) |
|||
m_Settings.selectedPanel = 0; |
|||
} |
|||
|
|||
// Root children are containers
|
|||
for (int i = 0; i < panels.Count; i++) |
|||
{ |
|||
var panel = panels[i]; |
|||
|
|||
if (panel.isRuntimeOnly) |
|||
continue; |
|||
|
|||
if (panel.children.Count(x => !x.isRuntimeOnly) == 0) |
|||
continue; |
|||
|
|||
var elementRect = GUILayoutUtility.GetRect(CoreEditorUtils.GetContent(panel.displayName), s_Styles.sectionElement, GUILayout.ExpandWidth(true)); |
|||
|
|||
if (m_Settings.selectedPanel == i && Event.current.type == EventType.Repaint) |
|||
s_Styles.selected.Draw(elementRect, false, false, false, false); |
|||
|
|||
if (GUI.Toggle(elementRect, m_Settings.selectedPanel == i, panel.displayName, s_Styles.sectionElement)) |
|||
{ |
|||
Undo.RecordObject(m_Settings, "Debug Panel Selection"); |
|||
m_Settings.selectedPanel = i; |
|||
} |
|||
} |
|||
|
|||
m_PanelScroll = scrollScope.scrollPosition; |
|||
} |
|||
|
|||
GUILayout.Space(10f); |
|||
|
|||
// Main section - traverse current container
|
|||
using (var changedScope = new EditorGUI.ChangeCheckScope()) |
|||
{ |
|||
using (new EditorGUILayout.VerticalScope()) |
|||
{ |
|||
var selectedPanel = panels[m_Settings.selectedPanel]; |
|||
|
|||
GUILayout.Label(selectedPanel.displayName, s_Styles.sectionHeader); |
|||
GUILayout.Space(10f); |
|||
|
|||
using (var scrollScope = new EditorGUILayout.ScrollViewScope(m_ContentScroll)) |
|||
{ |
|||
TraverseContainerGUI(selectedPanel); |
|||
m_ContentScroll = scrollScope.scrollPosition; |
|||
} |
|||
} |
|||
|
|||
if (changedScope.changed) |
|||
m_Settings.currentStateHash = ComputeStateHash(); |
|||
} |
|||
} |
|||
} |
|||
|
|||
void OnWidgetGUI(DebugUI.Widget widget) |
|||
{ |
|||
if (widget.isRuntimeOnly) |
|||
return; |
|||
|
|||
DebugState state; // State will be null for stateless widget
|
|||
m_WidgetStates.TryGetValue(widget.queryPath, out state); |
|||
|
|||
DebugUIDrawer drawer; |
|||
|
|||
if (!s_WidgetDrawerMap.TryGetValue(widget.GetType(), out drawer)) |
|||
{ |
|||
EditorGUILayout.LabelField("Drawer not found (" + widget.GetType() + ")."); |
|||
} |
|||
else |
|||
{ |
|||
drawer.Begin(widget, state); |
|||
|
|||
if (drawer.OnGUI(widget, state)) |
|||
{ |
|||
var container = widget as DebugUI.IContainer; |
|||
|
|||
if (container != null) |
|||
TraverseContainerGUI(container); |
|||
} |
|||
|
|||
drawer.End(widget, state); |
|||
} |
|||
} |
|||
|
|||
void TraverseContainerGUI(DebugUI.IContainer container) |
|||
{ |
|||
// /!\ SHAAAAAAAME ALERT /!\
|
|||
// A container can change at runtime because of the way IMGUI works and how we handle
|
|||
// onValueChanged on widget so we have to take this into account while iterating
|
|||
try |
|||
{ |
|||
foreach (var widget in container.children) |
|||
OnWidgetGUI(widget); |
|||
} |
|||
catch (InvalidOperationException) |
|||
{ |
|||
Repaint(); |
|||
} |
|||
} |
|||
|
|||
public class Styles |
|||
{ |
|||
public static float s_DefaultLabelWidth = 0.5f; |
|||
|
|||
public readonly GUIStyle sectionScrollView = "PreferencesSectionBox"; |
|||
public readonly GUIStyle sectionElement = "PreferencesSection"; |
|||
public readonly GUIStyle selected = "OL SelectedRow"; |
|||
public readonly GUIStyle sectionHeader = new GUIStyle(EditorStyles.largeLabel); |
|||
public readonly Color skinBackgroundColor; |
|||
|
|||
public Styles() |
|||
{ |
|||
sectionScrollView = new GUIStyle(sectionScrollView); |
|||
sectionScrollView.overflow.bottom += 1; |
|||
|
|||
sectionHeader.fontStyle = FontStyle.Bold; |
|||
sectionHeader.fontSize = 18; |
|||
sectionHeader.margin.top = 10; |
|||
sectionHeader.margin.left += 1; |
|||
sectionHeader.normal.textColor = !EditorGUIUtility.isProSkin |
|||
? new Color(0.4f, 0.4f, 0.4f, 1.0f) |
|||
: new Color(0.7f, 0.7f, 0.7f, 1.0f); |
|||
|
|||
if (EditorGUIUtility.isProSkin) |
|||
{ |
|||
sectionHeader.normal.textColor = new Color(0.7f, 0.7f, 0.7f, 1.0f); |
|||
skinBackgroundColor = Color.gray * new Color(0.3f, 0.3f, 0.3f, 0.5f); |
|||
} |
|||
else |
|||
{ |
|||
sectionHeader.normal.textColor = new Color(0.4f, 0.4f, 0.4f, 1.0f); |
|||
skinBackgroundColor = Color.gray * new Color(1f, 1f, 1f, 0.32f); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
|
|||
#pragma warning restore 414
|
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: 41147144ff556e246b736135eb26f185 |
|||
MonoImporter: |
|||
externalObjects: {} |
|||
serializedVersion: 2 |
|||
defaultReferences: [] |
|||
executionOrder: 0 |
|||
icon: {instanceID: 0} |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
using UnityEngine.Experimental.Rendering.UI; |
|||
|
|||
namespace UnityEditor.Experimental.Rendering.UI |
|||
{ |
|||
[CustomEditor(typeof(UIFoldout), true)] |
|||
sealed class UIFoldoutEditor : Editor |
|||
{ |
|||
SerializedProperty m_IsOn; |
|||
SerializedProperty m_Content; |
|||
SerializedProperty m_ArrowClosed; |
|||
SerializedProperty m_ArrowOpened; |
|||
|
|||
void OnEnable() |
|||
{ |
|||
var o = new PropertyFetcher<UIFoldout>(serializedObject); |
|||
m_IsOn = o.Find("m_IsOn"); |
|||
m_Content = o.Find(x => x.content); |
|||
m_ArrowClosed = o.Find(x => x.arrowClosed); |
|||
m_ArrowOpened = o.Find(x => x.arrowOpened); |
|||
} |
|||
|
|||
public override void OnInspectorGUI() |
|||
{ |
|||
serializedObject.Update(); |
|||
|
|||
EditorGUILayout.PropertyField(m_IsOn); |
|||
EditorGUILayout.PropertyField(m_Content); |
|||
EditorGUILayout.PropertyField(m_ArrowClosed); |
|||
EditorGUILayout.PropertyField(m_ArrowOpened); |
|||
|
|||
serializedObject.ApplyModifiedProperties(); |
|||
} |
|||
} |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: e89075dc59755d8479f34df9e20926e1 |
|||
MonoImporter: |
|||
externalObjects: {} |
|||
serializedVersion: 2 |
|||
defaultReferences: [] |
|||
executionOrder: 0 |
|||
icon: {instanceID: 0} |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
using System; |
|||
using System.Collections; |
|||
using System.Collections.Generic; |
|||
|
|||
namespace UnityEngine.Experimental.Rendering |
|||
{ |
|||
public sealed class ListChangedEventArgs<T> : EventArgs |
|||
{ |
|||
public readonly int index; |
|||
public readonly T item; |
|||
|
|||
public ListChangedEventArgs(int index, T item) |
|||
{ |
|||
this.index = index; |
|||
this.item = item; |
|||
} |
|||
} |
|||
|
|||
public delegate void ListChangedEventHandler<T>(ObservableList<T> sender, ListChangedEventArgs<T> e); |
|||
|
|||
public class ObservableList<T> : IList<T> |
|||
{ |
|||
IList<T> m_List; |
|||
|
|||
public event ListChangedEventHandler<T> ItemAdded; |
|||
public event ListChangedEventHandler<T> ItemRemoved; |
|||
|
|||
public T this[int index] |
|||
{ |
|||
get { return m_List[index]; } |
|||
set |
|||
{ |
|||
OnEvent(ItemRemoved, index, m_List[index]); |
|||
m_List[index] = value; |
|||
OnEvent(ItemAdded, index, value); |
|||
} |
|||
} |
|||
|
|||
public int Count |
|||
{ |
|||
get { return m_List.Count; } |
|||
} |
|||
|
|||
public bool IsReadOnly |
|||
{ |
|||
get { return false; } |
|||
} |
|||
|
|||
public ObservableList() |
|||
: this(0) { } |
|||
|
|||
public ObservableList(int capacity) |
|||
{ |
|||
m_List = new List<T>(capacity); |
|||
} |
|||
|
|||
public ObservableList(IEnumerable<T> collection) |
|||
{ |
|||
m_List = new List<T>(collection); |
|||
} |
|||
|
|||
void OnEvent(ListChangedEventHandler<T> e, int index, T item) |
|||
{ |
|||
if (e != null) |
|||
e(this, new ListChangedEventArgs<T>(index, item)); |
|||
} |
|||
|
|||
public bool Contains(T item) |
|||
{ |
|||
return m_List.Contains(item); |
|||
} |
|||
|
|||
public int IndexOf(T item) |
|||
{ |
|||
return m_List.IndexOf(item); |
|||
} |
|||
|
|||
public void Add(T item) |
|||
{ |
|||
m_List.Add(item); |
|||
OnEvent(ItemAdded, m_List.IndexOf(item), item); |
|||
} |
|||
|
|||
public void Add(params T[] items) |
|||
{ |
|||
foreach (var i in items) |
|||
Add(i); |
|||
} |
|||
|
|||
public void Insert(int index, T item) |
|||
{ |
|||
m_List.Insert(index, item); |
|||
OnEvent(ItemAdded, index, item); |
|||
} |
|||
|
|||
public bool Remove(T item) |
|||
{ |
|||
int index = m_List.IndexOf(item); |
|||
bool ret = m_List.Remove(item); |
|||
if (ret) |
|||
OnEvent(ItemRemoved, index, item); |
|||
return ret; |
|||
} |
|||
|
|||
public int Remove(params T[] items) |
|||
{ |
|||
if (items == null) |
|||
return 0; |
|||
|
|||
int count = 0; |
|||
|
|||
foreach (var i in items) |
|||
count += Remove(i) ? 1 : 0; |
|||
|
|||
return count; |
|||
} |
|||
|
|||
public void RemoveAt(int index) |
|||
{ |
|||
var item = m_List[index]; |
|||
m_List.RemoveAt(index); |
|||
OnEvent(ItemRemoved, index, item); |
|||
} |
|||
|
|||
public void Clear() |
|||
{ |
|||
for (int i = 0; i < Count; i++) |
|||
RemoveAt(i); |
|||
} |
|||
|
|||
public void CopyTo(T[] array, int arrayIndex) |
|||
{ |
|||
m_List.CopyTo(array, arrayIndex); |
|||
} |
|||
|
|||
public IEnumerator<T> GetEnumerator() |
|||
{ |
|||
return m_List.GetEnumerator(); |
|||
} |
|||
|
|||
IEnumerator IEnumerable.GetEnumerator() |
|||
{ |
|||
return GetEnumerator(); |
|||
} |
|||
} |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: 1511526f1e7c8e94ea477c5b5c9dcc32 |
|||
MonoImporter: |
|||
externalObjects: {} |
|||
serializedVersion: 2 |
|||
defaultReferences: [] |
|||
executionOrder: 0 |
|||
icon: {instanceID: 0} |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
using System; |
|||
using System.Collections.Generic; |
|||
|
|||
namespace UnityEngine.Experimental.Rendering |
|||
{ |
|||
//
|
|||
// Unity can't serialize Dictionary so here's a custom wrapper that does. Note that you have to
|
|||
// extend it before it can be serialized as Unity won't serialized generic-based types either.
|
|||
//
|
|||
// Example:
|
|||
// public sealed class MyDictionary : SerializedDictionary<KeyType, ValueType> {}
|
|||
//
|
|||
[Serializable] |
|||
public class SerializedDictionary<K, V> : Dictionary<K, V>, ISerializationCallbackReceiver |
|||
{ |
|||
[SerializeField] |
|||
List<K> m_Keys = new List<K>(); |
|||
|
|||
[SerializeField] |
|||
List<V> m_Values = new List<V>(); |
|||
|
|||
public void OnBeforeSerialize() |
|||
{ |
|||
m_Keys.Clear(); |
|||
m_Values.Clear(); |
|||
|
|||
foreach (var kvp in this) |
|||
{ |
|||
m_Keys.Add(kvp.Key); |
|||
m_Values.Add(kvp.Value); |
|||
} |
|||
} |
|||
|
|||
public void OnAfterDeserialize() |
|||
{ |
|||
for (int i = 0; i < m_Keys.Count; i++) |
|||
Add(m_Keys[i], m_Values[i]); |
|||
|
|||
m_Keys.Clear(); |
|||
m_Values.Clear(); |
|||
} |
|||
} |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: b21ca88b322a62d4b9a511ddabc12251 |
|||
MonoImporter: |
|||
externalObjects: {} |
|||
serializedVersion: 2 |
|||
defaultReferences: [] |
|||
executionOrder: 0 |
|||
icon: {instanceID: 0} |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
fileFormatVersion: 2 |
|||
guid: a11be56b627f5034bbca389c76bd3964 |
|||
folderAsset: yes |
|||
DefaultImporter: |
|||
externalObjects: {} |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
|