//
|
// ShadowTextureRendererEditor.cs
|
//
|
// Dynamic Shadow Projector
|
//
|
// Copyright 2015 NYAHOON GAMES PTE. LTD. All Rights Reserved.
|
//
|
|
using UnityEngine;
|
using UnityEditor;
|
|
namespace DynamicShadowProjector.Editor {
|
[CustomEditor(typeof(ShadowTextureRenderer))]
|
public class ShadowTextureRendererEditor : EditorBase {
|
static bool s_showAdvancedOptions = false;
|
void OnEnable()
|
{
|
ShadowTextureRenderer shadowRenderer = target as ShadowTextureRenderer;
|
bool modified = false;
|
if (shadowRenderer.blurShader == null) {
|
shadowRenderer.blurShader = FindMaterial("DynamicShadowProjector/Blit/Blur");
|
ClearMaterialProperties(shadowRenderer.blurShader);
|
modified = true;
|
}
|
if (shadowRenderer.downsampleShader == null) {
|
shadowRenderer.downsampleShader = FindMaterial("DynamicShadowProjector/Blit/Downsample");
|
ClearMaterialProperties(shadowRenderer.downsampleShader);
|
modified = true;
|
}
|
if (shadowRenderer.copyMipmapShader == null) {
|
shadowRenderer.copyMipmapShader = FindMaterial("DynamicShadowProjector/Blit/CopyMipmap");
|
ClearMaterialProperties(shadowRenderer.copyMipmapShader);
|
modified = true;
|
}
|
if (shadowRenderer.eraseShadowShader == null) {
|
shadowRenderer.eraseShadowShader = FindMaterial("DynamicShadowProjector/Blit/EraseShadow");
|
ClearMaterialProperties(shadowRenderer.eraseShadowShader);
|
modified = true;
|
}
|
Projector projector = shadowRenderer.GetComponent<Projector>();
|
if (projector.material != null) {
|
RemoveUnusedMaterialProperties(projector.material);
|
}
|
if (modified) {
|
EditorUtility.SetDirty(shadowRenderer);
|
serializedObject.Update();
|
}
|
}
|
private SerializedObject m_cameraSerializedObject = null;
|
private Camera m_camera;
|
public override void OnInspectorGUI ()
|
{
|
EditorGUILayout.BeginHorizontal();
|
GUILayout.Label("Online Document");
|
if (GUILayout.Button("<color=blue>http://nyahoon.com/products/dynamic-shadow-projector/shadow-texture-renderer-component</color>", richTextStyle)) {
|
Application.OpenURL("http://nyahoon.com/products/dynamic-shadow-projector/shadow-texture-renderer-component");
|
}
|
EditorGUILayout.EndHorizontal();
|
bool isGUIEnabled = GUI.enabled;
|
EditorGUILayout.PropertyField(serializedObject.FindProperty("m_shadowColor"));
|
EditorGUILayout.IntPopup(serializedObject.FindProperty("m_textureWidth"), s_textureSizeDisplayOption, s_textureSizeOption);
|
EditorGUILayout.IntPopup(serializedObject.FindProperty("m_textureHeight"), s_textureSizeDisplayOption, s_textureSizeOption);
|
EditorGUILayout.PropertyField(serializedObject.FindProperty("m_multiSampling"));
|
EditorGUILayout.PropertyField(serializedObject.FindProperty("m_superSampling"));
|
SerializedProperty prop = serializedObject.FindProperty("m_blurLevel");
|
EditorGUILayout.IntPopup(prop, s_blurLevelDisplayOption, s_blurLevelOption);
|
++EditorGUI.indentLevel;
|
GUI.enabled = isGUIEnabled && 0 < prop.intValue;
|
ShadowTextureRenderer shadowRenderer = target as ShadowTextureRenderer;
|
EditorGUILayout.Slider(serializedObject.FindProperty("m_blurSize"), 1.0f, shadowRenderer.blurFilter == ShadowTextureRenderer.BlurFilter.Uniform ? 6.0f : 4.0f);
|
GUI.enabled = isGUIEnabled;
|
--EditorGUI.indentLevel;
|
prop = serializedObject.FindProperty("m_mipLevel");
|
EditorGUILayout.PropertyField(prop);
|
++EditorGUI.indentLevel;
|
GUI.enabled = isGUIEnabled && 0 < prop.intValue;
|
SerializedProperty fastBlur = serializedObject.FindProperty("m_singlePassMipmapBlur");
|
EditorGUILayout.PropertyField(fastBlur);
|
float maxBlurSize;
|
if (fastBlur.boolValue) {
|
maxBlurSize = 1.0f;
|
}
|
else {
|
maxBlurSize = shadowRenderer.blurFilter == ShadowTextureRenderer.BlurFilter.Uniform ? 3.0f : 2.0f;
|
}
|
EditorGUILayout.Slider(serializedObject.FindProperty("m_mipmapBlurSize"), 0.0f, maxBlurSize);
|
if (shadowRenderer.GetComponent<MipmappedShadowFallback>() == null) {
|
EditorGUILayout.BeginHorizontal();
|
GUILayout.FlexibleSpace();
|
if (GUILayout.Button("Add Fallback Component")) {
|
Undo.AddComponent<MipmappedShadowFallback>(shadowRenderer.gameObject);
|
}
|
EditorGUILayout.EndHorizontal();
|
GUI.enabled = isGUIEnabled;
|
--EditorGUI.indentLevel;
|
}
|
else if (prop.intValue == 0) {
|
GUI.enabled = isGUIEnabled;
|
--EditorGUI.indentLevel;
|
EditorGUILayout.BeginHorizontal();
|
GUILayout.TextArea("<color=red>Still has Mipmap Fallback Component!</color>", richTextStyle);
|
if (GUILayout.Button("Remove the Component")) {
|
Undo.DestroyObjectImmediate(shadowRenderer.GetComponent<MipmappedShadowFallback>());
|
}
|
EditorGUILayout.EndHorizontal();
|
}
|
else {
|
GUI.enabled = isGUIEnabled;
|
--EditorGUI.indentLevel;
|
}
|
prop = serializedObject.FindProperty("m_testViewClip");
|
EditorGUILayout.BeginHorizontal();
|
EditorGUILayout.LabelField("Don't update while out of view");
|
prop.boolValue = EditorGUILayout.Toggle(prop.boolValue);
|
EditorGUILayout.EndHorizontal();
|
++EditorGUI.indentLevel;
|
GUI.enabled = isGUIEnabled && prop.boolValue;
|
EditorGUILayout.PropertyField(serializedObject.FindProperty("m_camerasForViewClipTest"), true);
|
GUI.enabled = isGUIEnabled;
|
--EditorGUI.indentLevel;
|
|
s_showAdvancedOptions = GUILayout.Toggle(s_showAdvancedOptions, "Show Advanced Options");
|
if (s_showAdvancedOptions) {
|
++EditorGUI.indentLevel;
|
EditorGUILayout.PropertyField(serializedObject.FindProperty("m_blurFilter"));
|
prop = serializedObject.FindProperty("m_mipmapFalloff");
|
EditorGUILayout.PropertyField(prop);
|
if (prop.intValue == (int)ShadowTextureRenderer.MipmapFalloff.Custom) {
|
prop = serializedObject.FindProperty("m_customMipmapFalloff");
|
if (shadowRenderer.customMipmapFalloff != null && shadowRenderer.customMipmapFalloff.Length != prop.arraySize) {
|
serializedObject.Update();
|
prop = serializedObject.FindProperty("m_customMipmapFalloff");
|
}
|
EditorGUILayout.PropertyField(prop, true);
|
}
|
float near = EditorGUILayout.FloatField("Near Clip Plane", shadowRenderer.cameraNearClipPlane);
|
if (m_cameraSerializedObject == null) {
|
m_camera = shadowRenderer.GetComponent<Camera>();
|
m_cameraSerializedObject = new SerializedObject(shadowRenderer.GetComponent<Camera>());
|
}
|
if (near != shadowRenderer.cameraNearClipPlane) {
|
Undo.RecordObject(m_camera, "Inspector");
|
shadowRenderer.cameraNearClipPlane = near;
|
}
|
bool bShowCamera = (m_camera.hideFlags & HideFlags.HideInInspector) == 0;
|
bool newValue = EditorGUILayout.Toggle("Show Camera in Inspector", bShowCamera);
|
if (bShowCamera != newValue) {
|
if (newValue) {
|
m_camera.hideFlags &= ~HideFlags.HideInInspector;
|
}
|
else {
|
m_camera.hideFlags |= HideFlags.HideInInspector;
|
}
|
}
|
EditorGUILayout.PropertyField(serializedObject.FindProperty("m_blurShader"));
|
EditorGUILayout.PropertyField(serializedObject.FindProperty("m_downsampleShader"));
|
EditorGUILayout.PropertyField(serializedObject.FindProperty("m_copyMipmapShader"));
|
EditorGUILayout.PropertyField(serializedObject.FindProperty("m_preferredTextureFormats"), true);
|
--EditorGUI.indentLevel;
|
}
|
serializedObject.ApplyModifiedProperties();
|
}
|
private Material m_blitMaterial;
|
private Vector3 m_lastPosition;
|
private Quaternion m_lastRotation;
|
void OnSceneGUI()
|
{
|
ShadowTextureRenderer shadowRenderer = target as ShadowTextureRenderer;
|
if (shadowRenderer.shadowTexture == null || shadowRenderer.GetComponent<Projector>().material == null) {
|
return;
|
}
|
|
if (m_lastPosition != shadowRenderer.transform.position || m_lastRotation != shadowRenderer.transform.rotation) {
|
// This function call will have the following error on Unity 5.6.0:
|
// Rendering camera 'XXXX', but calling code does not set it up as current camera (current camera: 'Main Camera') UnityEngine.Camera:Render()
|
// But it seems like there are no way to avoid this error message.
|
shadowRenderer.ForceRenderTexture();
|
m_lastPosition = shadowRenderer.transform.position;
|
m_lastRotation = shadowRenderer.transform.rotation;
|
}
|
|
if (m_blitMaterial == null) {
|
m_blitMaterial = FindMaterial("DynamicShadowProjector/Blit/Blit");
|
}
|
int mipLevel = shadowRenderer.mipLevel + 1;
|
int w = shadowRenderer.textureWidth;
|
int h = shadowRenderer.textureHeight;
|
for (int i = 1; i < mipLevel; ++i) {
|
if ((w >> i) <= 4 || (h >> i) <=4) {
|
mipLevel = i;
|
break;
|
}
|
}
|
int displayWidth = 128;
|
float mipBias = Mathf.Log(displayWidth/w)/Mathf.Log(2.0f);
|
int displayHeight = h*displayWidth/w;
|
int marginSize = 4;
|
int windowWidth = mipLevel * (displayWidth + marginSize) + marginSize;
|
int windowHeight = displayHeight + 2*GUI.skin.window.border.bottom + marginSize;
|
int windowPosX = Screen.width - windowWidth - 10;
|
int windowPosY = Screen.height - windowHeight - GUI.skin.window.border.top - 10;
|
GUI.WindowFunction func = id => {
|
if (Event.current.type.Equals(EventType.Repaint)) {
|
int x = marginSize;
|
int y = GUI.skin.window.border.top;
|
for (int i = 0; i < mipLevel; ++i) {
|
m_blitMaterial.SetFloat("_MipLevel", i);
|
m_blitMaterial.SetFloat("_MipBias", mipBias + i);
|
Graphics.DrawTexture(new Rect(x, y, displayWidth, displayHeight), shadowRenderer.shadowTexture, m_blitMaterial);
|
x += displayWidth + marginSize;
|
}
|
}
|
};
|
GUI.Window(0, new Rect(windowPosX, windowPosY, windowWidth, windowHeight), func, "Shadow Texture");
|
}
|
}
|
}
|