mirror of
https://github.com/muskit/H3VR-TNH-Quality-of-Life-Improvements.git
synced 2026-06-03 04:34:26 -07:00
Initial commit
This commit is contained in:
@@ -0,0 +1,23 @@
|
||||
// Alloy Physical Shader Framework
|
||||
// Copyright 2013-2017 RUST LLC.
|
||||
// http://www.alloy.rustltd.com/
|
||||
|
||||
using UnityEngine;
|
||||
|
||||
public class MinValueAttribute : PropertyAttribute {
|
||||
public float Min;
|
||||
|
||||
public MinValueAttribute(float min) {
|
||||
Min = min;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public class MaxValueAttribute : PropertyAttribute {
|
||||
public float Max;
|
||||
|
||||
public MaxValueAttribute(float min) {
|
||||
Max = min;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 48d3cf2ec372bd34fa4b3bd9f05b6132
|
||||
timeCreated: 1445390687
|
||||
licenseType: Pro
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,27 @@
|
||||
// Alloy Physical Shader Framework
|
||||
// Copyright 2013-2017 RUST LLC.
|
||||
// http://www.alloy.rustltd.com/
|
||||
|
||||
using UnityEngine;
|
||||
|
||||
public static class AlloyUtils {
|
||||
public const string Name = "Alloy";
|
||||
public const string Version = "3.6.4";
|
||||
public const float SectionColorMax = 20.0f;
|
||||
|
||||
public const string Path = Name + "/";
|
||||
public const string MenuItem = "Window/" + Path;
|
||||
public const string ComponentMenu = Path + Name + " ";
|
||||
|
||||
public static string AssetsPath {
|
||||
get { return Application.dataPath + "/" + Path; }
|
||||
}
|
||||
|
||||
//public static float IntensityToLumens(float intensity) {
|
||||
// return Mathf.Floor(Mathf.GammaToLinearSpace(intensity) * 100.0f);
|
||||
//}
|
||||
|
||||
//public static float LumensToIntensity(float lumens) {
|
||||
// return Mathf.LinearToGammaSpace(lumens / 100.0f);
|
||||
//}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c9500e8a2783ced4aa7f8c3488e304b5
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
@@ -0,0 +1,6 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 608acff29777b4548909fea9555edd26
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
userData:
|
||||
assetBundleName:
|
||||
@@ -0,0 +1,178 @@
|
||||
// Alloy Physical Shader Framework
|
||||
// Copyright 2013-2017 RUST LLC.
|
||||
// http://www.alloy.rustltd.com/
|
||||
// We don't need this for MeatKit because it gets imported with the game assembly.
|
||||
/*
|
||||
#if UNITY_EDITOR
|
||||
using UnityEditor;
|
||||
#endif
|
||||
|
||||
using System;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Serialization;
|
||||
|
||||
[ExecuteInEditMode]
|
||||
[RequireComponent(typeof(Light))]
|
||||
[AddComponentMenu(AlloyUtils.ComponentMenu + "Area Light")]
|
||||
public class AlloyAreaLight : MonoBehaviour {
|
||||
// Minimum non-zero value for light size, so we can use sign for specular toggle.
|
||||
const float c_minimumLightSize = 0.00001f;
|
||||
|
||||
// Minimum light intensity to prevent divide by zero (because Epsilon causes infinity).
|
||||
const float c_minimumLightIntensity = 0.01f;
|
||||
|
||||
[HideInInspector]
|
||||
public Texture2D DefaultSpotLightCookie;
|
||||
|
||||
[FormerlySerializedAs("m_size")]
|
||||
[SerializeField]
|
||||
float m_radius;
|
||||
|
||||
[SerializeField]
|
||||
float m_length;
|
||||
|
||||
[SerializeField]
|
||||
bool m_hasSpecularHightlight = true;
|
||||
|
||||
Light m_light;
|
||||
Color m_lastColor;
|
||||
float m_lastIntensity;
|
||||
float m_lastRange;
|
||||
|
||||
Light Light {
|
||||
get {
|
||||
// Ensures that we have the light component, even if light is disabled.
|
||||
if (m_light == null)
|
||||
m_light = GetComponent<Light>();
|
||||
|
||||
return m_light;
|
||||
}
|
||||
}
|
||||
|
||||
public float Radius {
|
||||
get { return m_radius; }
|
||||
set {
|
||||
if (m_radius != value) {
|
||||
m_radius = value;
|
||||
UpdateBinding();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public float Length {
|
||||
get { return m_length; }
|
||||
set {
|
||||
if (m_length != value) {
|
||||
m_length = value;
|
||||
UpdateBinding();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public bool HasSpecularHighlight {
|
||||
get { return m_hasSpecularHightlight; }
|
||||
set {
|
||||
if (m_hasSpecularHightlight != value) {
|
||||
m_hasSpecularHightlight = value;
|
||||
UpdateBinding();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Reset() {
|
||||
m_hasSpecularHightlight = true;
|
||||
m_radius = 0.0f;
|
||||
m_length = 0.0f;
|
||||
|
||||
m_lastColor = Color.black;
|
||||
m_lastIntensity = 0.0f;
|
||||
m_lastRange = 0.0f;
|
||||
|
||||
UpdateBinding();
|
||||
}
|
||||
|
||||
// Must run after all other light scripts and animation clips.
|
||||
void LateUpdate() {
|
||||
var l = Light;
|
||||
|
||||
// Poll the Light component, since we can't extend it.
|
||||
if (l.color != m_lastColor
|
||||
|| l.intensity != m_lastIntensity
|
||||
|| l.range != m_lastRange) {
|
||||
UpdateBinding();
|
||||
}
|
||||
}
|
||||
|
||||
public void UpdateBinding() {
|
||||
var l = Light;
|
||||
var color = l.color;
|
||||
var intensity = l.intensity;
|
||||
var range = l.range;
|
||||
|
||||
#if UNITY_EDITOR
|
||||
EnsureCookie();
|
||||
#endif
|
||||
|
||||
if (l.type == LightType.Directional) {
|
||||
m_radius = Mathf.Clamp01(m_radius);
|
||||
color.a = 10.0f * m_radius; // Cancel 0.1 * n in the shader.
|
||||
}
|
||||
else {
|
||||
// Radius packed into fractional component of number.
|
||||
var maxRadius = range;
|
||||
m_radius = Mathf.Clamp(m_radius, 0.0f, maxRadius);
|
||||
color.a = Mathf.Min(0.999f, m_radius / maxRadius);
|
||||
|
||||
if (l.type == LightType.Point) {
|
||||
// Length packed into integer component of number.
|
||||
var maxLength = 2.0f * range;
|
||||
m_length = Mathf.Clamp(m_length, 0.0f, maxLength);
|
||||
color.a += Mathf.Ceil(1000.0f * Mathf.Min(1.0f, m_length / maxLength));
|
||||
}
|
||||
}
|
||||
|
||||
// Specular highlight toggle in sign component of number.
|
||||
color.a = Mathf.Max(c_minimumLightSize, color.a); // Must be non-zero!
|
||||
color.a *= (m_hasSpecularHightlight ? 1.0f : -1.0f);
|
||||
|
||||
// Cancel Unity's implicit intensity multiply.
|
||||
color.a /= Mathf.Max(intensity, c_minimumLightIntensity);
|
||||
l.color = color;
|
||||
|
||||
m_lastColor = color;
|
||||
m_lastIntensity = intensity;
|
||||
m_lastRange = range;
|
||||
}
|
||||
|
||||
#if UNITY_EDITOR
|
||||
public void EnsureCookie() {
|
||||
var l = Light;
|
||||
|
||||
if (l.type == LightType.Spot && l.cookie == null) {
|
||||
l.cookie = DefaultSpotLightCookie;
|
||||
EditorUtility.SetDirty(this);
|
||||
} else if (l.type == LightType.Point && l.cookie == DefaultSpotLightCookie) {
|
||||
l.cookie = null;
|
||||
EditorUtility.SetDirty(this);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
// DEPRECATED BEGIN
|
||||
[Obsolete("Please use Unity Light component's \"color\" field.")]
|
||||
public Color Color {
|
||||
get { return Light.color; }
|
||||
set { Light.color = value; }
|
||||
}
|
||||
|
||||
[Obsolete("Please use Unity Light component's \"intensity\" field.")]
|
||||
public float Intensity {
|
||||
get { return Light.intensity; }
|
||||
set { Light.intensity = value; }
|
||||
}
|
||||
|
||||
[Obsolete("No longer used. Please remove all references to it.")]
|
||||
public bool IsAnimated { get; set; }
|
||||
// DEPRECATED END
|
||||
}
|
||||
*/
|
||||
@@ -0,0 +1,14 @@
|
||||
fileFormatVersion: 2
|
||||
guid: e13ed666bcef6874386610d2ef878488
|
||||
timeCreated: 1468958632
|
||||
licenseType: Pro
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences:
|
||||
- DefaultSpotLightCookie: {fileID: 2800000, guid: d21bb2c11f0e5a2498a9ecc9cccfab62,
|
||||
type: 3}
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,9 @@
|
||||
fileFormatVersion: 2
|
||||
guid: bc738ca46cba47944874e267a234d9a9
|
||||
folderAsset: yes
|
||||
timeCreated: 1468957796
|
||||
licenseType: Pro
|
||||
DefaultImporter:
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
Binary file not shown.
@@ -0,0 +1,79 @@
|
||||
fileFormatVersion: 2
|
||||
guid: d21bb2c11f0e5a2498a9ecc9cccfab62
|
||||
timeCreated: 1442345799
|
||||
licenseType: Pro
|
||||
TextureImporter:
|
||||
fileIDToRecycleName: {}
|
||||
serializedVersion: 2
|
||||
mipmaps:
|
||||
mipMapMode: 0
|
||||
enableMipMap: 1
|
||||
linearTexture: 0
|
||||
correctGamma: 0
|
||||
fadeOut: 0
|
||||
borderMipMap: 1
|
||||
mipMapFadeDistanceStart: 1
|
||||
mipMapFadeDistanceEnd: 3
|
||||
bumpmap:
|
||||
convertToNormalMap: 0
|
||||
externalNormalMap: 0
|
||||
heightScale: 0.25
|
||||
normalMapFilter: 0
|
||||
isReadable: 0
|
||||
grayScaleToAlpha: 0
|
||||
generateCubemap: 0
|
||||
cubemapConvolution: 0
|
||||
cubemapConvolutionSteps: 8
|
||||
cubemapConvolutionExponent: 1.5
|
||||
seamlessCubemap: 0
|
||||
textureFormat: -1
|
||||
maxTextureSize: 1024
|
||||
textureSettings:
|
||||
filterMode: 1
|
||||
aniso: 0
|
||||
mipBias: 0
|
||||
wrapMode: 1
|
||||
nPOTScale: 1
|
||||
lightmap: 0
|
||||
rGBM: 0
|
||||
compressionQuality: 50
|
||||
allowsAlphaSplitting: 0
|
||||
spriteMode: 0
|
||||
spriteExtrude: 1
|
||||
spriteMeshType: 1
|
||||
alignment: 0
|
||||
spritePivot: {x: 0.5, y: 0.5}
|
||||
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
|
||||
spritePixelsToUnits: 100
|
||||
alphaIsTransparency: 0
|
||||
spriteTessellationDetail: -1
|
||||
textureType: 5
|
||||
buildTargetSettings:
|
||||
- buildTarget: iPhone
|
||||
maxTextureSize: 128
|
||||
textureFormat: 33
|
||||
compressionQuality: 50
|
||||
allowsAlphaSplitting: 0
|
||||
- buildTarget: Android
|
||||
maxTextureSize: 128
|
||||
textureFormat: 13
|
||||
compressionQuality: 50
|
||||
allowsAlphaSplitting: 0
|
||||
- buildTarget: BlackBerry
|
||||
maxTextureSize: 128
|
||||
textureFormat: 13
|
||||
compressionQuality: 50
|
||||
allowsAlphaSplitting: 0
|
||||
- buildTarget: WP8
|
||||
maxTextureSize: 128
|
||||
textureFormat: 12
|
||||
compressionQuality: 50
|
||||
allowsAlphaSplitting: 0
|
||||
spriteSheet:
|
||||
serializedVersion: 2
|
||||
sprites: []
|
||||
outline: []
|
||||
spritePackingTag:
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,6 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 0e3681edec2f2044bbbc59c604b43ec3
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
userData:
|
||||
assetBundleName:
|
||||
@@ -0,0 +1,190 @@
|
||||
// Alloy Physical Shader Framework
|
||||
// Copyright 2013-2017 RUST LLC.
|
||||
// http://www.alloy.rustltd.com/
|
||||
|
||||
using UnityEngine;
|
||||
using UnityEditor;
|
||||
|
||||
#if H3VR_IMPORTED
|
||||
[CustomEditor(typeof(AlloyAreaLight))]
|
||||
[CanEditMultipleObjects]
|
||||
public class AlloyAreaLightEditor : Editor {
|
||||
public override void OnInspectorGUI() {
|
||||
serializedObject.Update();
|
||||
|
||||
var hasSpecularHightlight = serializedObject.FindProperty("m_hasSpecularHightlight");
|
||||
var maxRange = float.MaxValue;
|
||||
var isSpecularAreaLight = false;
|
||||
var isPointLight = false;
|
||||
|
||||
// Light Type.
|
||||
foreach (AlloyAreaLight area in targets) {
|
||||
var light = area.GetComponent<Light>();
|
||||
|
||||
if (light.type == LightType.Directional) {
|
||||
maxRange = 1.0f;
|
||||
}
|
||||
else {
|
||||
maxRange = Mathf.Min(light.range, maxRange);
|
||||
}
|
||||
|
||||
isPointLight = light.type == LightType.Point;
|
||||
|
||||
if (isPointLight
|
||||
|| light.type == LightType.Spot
|
||||
|| light.type == LightType.Directional) {
|
||||
isSpecularAreaLight = true;
|
||||
}
|
||||
}
|
||||
|
||||
// Specular Highlight.
|
||||
if (isSpecularAreaLight) {
|
||||
hasSpecularHightlight.boolValue = EditorGUILayout.Toggle("Specular Highlight", hasSpecularHightlight.boolValue);
|
||||
isSpecularAreaLight = isSpecularAreaLight && hasSpecularHightlight.boolValue;
|
||||
}
|
||||
|
||||
// Radius.
|
||||
if (isSpecularAreaLight) {
|
||||
EditorGUILayout.Slider(serializedObject.FindProperty("m_radius"), 0.0f, maxRange);
|
||||
} else {
|
||||
var radius = serializedObject.FindProperty("m_radius");
|
||||
|
||||
if (radius.floatValue != 0.0f) {
|
||||
GUI.changed = true;
|
||||
radius.floatValue = 0.0f;
|
||||
}
|
||||
}
|
||||
|
||||
// Length.
|
||||
if (isSpecularAreaLight && isPointLight) {
|
||||
EditorGUILayout.Slider(serializedObject.FindProperty("m_length"), 0.0f, maxRange * 2.0f);
|
||||
} else {
|
||||
var length = serializedObject.FindProperty("m_length");
|
||||
|
||||
if (length.floatValue != 0.0f) {
|
||||
GUI.changed = true;
|
||||
length.floatValue = 0.0f;
|
||||
}
|
||||
}
|
||||
|
||||
serializedObject.ApplyModifiedProperties();
|
||||
|
||||
if (GUI.changed) {
|
||||
foreach (AlloyAreaLight area in targets) {
|
||||
area.UpdateBinding();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal static void DrawTwoShadedWireDisc(Vector3 position, Vector3 axis, float radius) {
|
||||
Color color1 = Handles.color;
|
||||
Color color2 = color1;
|
||||
|
||||
color1.a *= 0.2f;
|
||||
Handles.color = color1;
|
||||
Handles.DrawWireDisc(position, axis, radius);
|
||||
Handles.color = color2;
|
||||
}
|
||||
|
||||
internal static void DrawTwoShadedWireDisc(Vector3 position, Vector3 axis, Vector3 from, float degrees, float radius) {
|
||||
Handles.DrawWireArc(position, axis, from, degrees, radius);
|
||||
|
||||
Color cur = Handles.color;
|
||||
Color set = cur;
|
||||
|
||||
set.a *= 0.2f;
|
||||
Handles.color = set;
|
||||
Handles.DrawWireArc(position, axis, from, degrees - 360f, radius);
|
||||
Handles.color = cur;
|
||||
}
|
||||
|
||||
static Vector3[] s_directionArray = {
|
||||
Vector3.right,
|
||||
Vector3.up,
|
||||
Vector3.forward,
|
||||
-Vector3.right,
|
||||
-Vector3.up,
|
||||
-Vector3.forward
|
||||
};
|
||||
|
||||
static void DoRadiusHandle(Vector3 position, float radius, float length) {
|
||||
Vector3 dif = position - Camera.current.transform.position;
|
||||
float sqrMagnitude = dif.sqrMagnitude;
|
||||
float radiusSqr = radius * radius;
|
||||
float radiusDiv = radiusSqr * radiusSqr / sqrMagnitude;
|
||||
//float ratio = radiusDiv / radiusSqr;
|
||||
float total = Mathf.Sqrt(radiusSqr - radiusDiv);
|
||||
|
||||
Handles.DrawWireDisc(position - radiusSqr * dif / sqrMagnitude, dif, total);
|
||||
|
||||
for (int j = 0; j < 3; j++) {
|
||||
float angle = Vector3.Angle(dif, s_directionArray[j]);
|
||||
|
||||
angle = 90f - Mathf.Min(angle, 180f - angle);
|
||||
|
||||
float tanAngle = Mathf.Tan(angle * Mathf.Deg2Rad);
|
||||
float viewSize = Mathf.Sqrt(radiusDiv + tanAngle * tanAngle * radiusDiv) / radius;
|
||||
|
||||
if (viewSize < 1f) {
|
||||
float finalArcAngle = Mathf.Asin(viewSize) * Mathf.Rad2Deg;
|
||||
Vector3 vector2 = Vector3.Cross(s_directionArray[j], dif).normalized;
|
||||
vector2 = Quaternion.AngleAxis(finalArcAngle, s_directionArray[j]) * vector2;
|
||||
DrawTwoShadedWireDisc(position, s_directionArray[j], vector2, (90f - finalArcAngle) * 2f, radius);
|
||||
}
|
||||
else {
|
||||
DrawTwoShadedWireDisc(position, s_directionArray[j], radius);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
float DrawCapsuleGizmo(Transform transform, float radius, float length) {
|
||||
var fwd = Vector3.forward * radius;
|
||||
var side = Vector3.up * radius;
|
||||
var halfLength = 0.5f * length;
|
||||
|
||||
// Exclude light transform scale, and pre-rotate capsule to follow the Y-axis.
|
||||
Handles.matrix = Matrix4x4.TRS(transform.position, transform.rotation, Vector3.one)
|
||||
* Matrix4x4.TRS(Vector3.zero, Quaternion.Euler(0.0f, 0.0f, 90.0f), Vector3.one);
|
||||
|
||||
Handles.DrawWireArc(-halfLength * Vector3.right, Vector3.forward, Vector3.up, 180.0f, radius);
|
||||
Handles.DrawWireArc(-halfLength * Vector3.right, Vector3.up, -Vector3.forward, 180.0f, radius);
|
||||
|
||||
Handles.DrawWireArc(halfLength * Vector3.right, Vector3.forward, -Vector3.up, 180.0f, radius);
|
||||
Handles.DrawWireArc(halfLength * Vector3.right, Vector3.up, Vector3.forward, 180.0f, radius);
|
||||
|
||||
Handles.DrawWireDisc(-halfLength * Vector3.right, Vector3.right, radius);
|
||||
Handles.DrawWireDisc(halfLength * Vector3.right, Vector3.right, radius);
|
||||
|
||||
Handles.DrawLine(-halfLength * Vector3.right + fwd, halfLength * Vector3.right + fwd);
|
||||
Handles.DrawLine(-halfLength * Vector3.right - fwd, halfLength * Vector3.right - fwd);
|
||||
|
||||
Handles.DrawLine(-halfLength * Vector3.right + side, halfLength * Vector3.right + side);
|
||||
Handles.DrawLine(-halfLength * Vector3.right - side, halfLength * Vector3.right - side);
|
||||
|
||||
if (!Event.current.alt && !Event.current.shift) {
|
||||
radius = Handles.RadiusHandle(Quaternion.identity, -halfLength * Vector3.right, radius, true);
|
||||
radius = Handles.RadiusHandle(Quaternion.identity, halfLength * Vector3.right, radius, true);
|
||||
}
|
||||
|
||||
Handles.matrix = Matrix4x4.identity;
|
||||
|
||||
return radius;
|
||||
}
|
||||
|
||||
void OnSceneGUI() {
|
||||
var area = target as AlloyAreaLight;
|
||||
var light = area.GetComponent<Light>();
|
||||
|
||||
if (light.type == LightType.Point
|
||||
|| light.type == LightType.Spot) {
|
||||
area.Radius = DrawCapsuleGizmo(area.transform, area.Radius, area.Length);
|
||||
}
|
||||
|
||||
//DoRadiusHandle(area.transform.position, area.Size, 1.0f);
|
||||
|
||||
if (GUI.changed) {
|
||||
Undo.RecordObject(area, "Adjust area light");
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,9 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 895b6d1a02c68594f89e4586bdfff530
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
@@ -0,0 +1,51 @@
|
||||
// Alloy Physical Shader Framework
|
||||
// Copyright 2013-2017 RUST LLC.
|
||||
// http://www.alloy.rustltd.com/
|
||||
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
|
||||
public static class AlloyLightCreator {
|
||||
#if H3VR_IMPORTED
|
||||
const string c_lightMenuPath = "GameObject/Light/";
|
||||
const string c_undoMessage = "Created ";
|
||||
const string c_directionalLight = "Alloy Directional Light";
|
||||
const string c_pointLight = "Alloy Point Light";
|
||||
const string c_spotLight = "Alloy Spotlight";
|
||||
|
||||
[MenuItem(c_lightMenuPath + c_directionalLight)]
|
||||
static void CreateDirectionalLight() {
|
||||
BuildLight(c_directionalLight, LightType.Directional);
|
||||
}
|
||||
|
||||
[MenuItem(c_lightMenuPath + c_pointLight)]
|
||||
static void CreateSphereAreaLight() {
|
||||
BuildLight(c_pointLight, LightType.Point);
|
||||
}
|
||||
|
||||
[MenuItem(c_lightMenuPath + c_spotLight)]
|
||||
static void CreateSpotSphereAreaLight() {
|
||||
BuildLight(c_spotLight, LightType.Spot);
|
||||
}
|
||||
|
||||
static void BuildLight(string name, LightType type) {
|
||||
var go = new GameObject();
|
||||
var lastSceneView = SceneView.lastActiveSceneView;
|
||||
|
||||
Undo.RegisterCreatedObjectUndo(go, c_undoMessage + name);
|
||||
go.name = name;
|
||||
|
||||
var light = go.AddComponent<Light>();
|
||||
light.type = type;
|
||||
|
||||
go.AddComponent<AlloyAreaLight>();
|
||||
|
||||
if (lastSceneView != null)
|
||||
go.transform.position = lastSceneView.pivot;
|
||||
else
|
||||
go.transform.position = Vector3.zero;
|
||||
|
||||
Selection.activeGameObject = go;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f5d3ae613b034fe4599db89f5c75351a
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
@@ -0,0 +1,67 @@
|
||||
// Alloy Physical Shader Framework
|
||||
// Copyright 2013-2017 RUST LLC.
|
||||
// http://www.alloy.rustltd.com/
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using MeatKit;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
|
||||
|
||||
[CustomEditor(typeof(Light))]
|
||||
[CanEditMultipleObjects]
|
||||
public class AlloyLightEditor : Editor {
|
||||
#if H3VR_IMPORTED
|
||||
Editor m_editor;
|
||||
Action m_onSceneGUIReflected;
|
||||
|
||||
Type GetTypeGlobal(string typeName) {
|
||||
return AppDomain.CurrentDomain.GetAssemblies().SelectMany(a => a.GetTypesSafe()).FirstOrDefault(t => t.Name == typeName);
|
||||
}
|
||||
|
||||
void OnEnable() {
|
||||
m_editor = CreateEditor(targets, GetTypeGlobal("LightEditor"));
|
||||
Undo.undoRedoPerformed += RebindAreaLights;
|
||||
RebindAreaLights();
|
||||
m_onSceneGUIReflected = (Action)Delegate.CreateDelegate(typeof(Action), m_editor, "OnSceneGUI", false, true);
|
||||
}
|
||||
|
||||
void OnSceneGUI() {
|
||||
m_onSceneGUIReflected();
|
||||
}
|
||||
|
||||
void OnDisable() {
|
||||
Undo.undoRedoPerformed -= RebindAreaLights;
|
||||
|
||||
//Calls on destroy on light editor
|
||||
DestroyImmediate(m_editor);
|
||||
}
|
||||
|
||||
public override void OnInspectorGUI() {
|
||||
m_editor.OnInspectorGUI();
|
||||
bool anyMissing = targets.Any(l => ((Light)l).GetComponent<Light>().type != LightType.Area
|
||||
&& ((Light)l).GetComponent<AlloyAreaLight>() == null);
|
||||
|
||||
if (anyMissing) {
|
||||
if (GUILayout.Button("Convert to Alloy area light", EditorStyles.toolbarButton)) {
|
||||
foreach (Light light in targets) {
|
||||
Undo.AddComponent<AlloyAreaLight>(light.gameObject);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (GUI.changed) {
|
||||
RebindAreaLights();
|
||||
}
|
||||
}
|
||||
|
||||
void RebindAreaLights() {
|
||||
var lights = targets.Select(l => ((Light)l).GetComponent<AlloyAreaLight>()).Where(a => a != null);
|
||||
|
||||
foreach (AlloyAreaLight ar in lights) {
|
||||
ar.UpdateBinding();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f83832185bd1caa4d9aab41ddfbc423d
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
@@ -0,0 +1,6 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 301e9fbda97de0d41a1f555dc127b9c9
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
userData:
|
||||
assetBundleName:
|
||||
@@ -0,0 +1,61 @@
|
||||
// Alloy Physical Shader Framework
|
||||
// Copyright 2013-2017 RUST LLC.
|
||||
// http://www.alloy.rustltd.com/
|
||||
|
||||
using UnityEngine;
|
||||
using System.Collections.Generic;
|
||||
using UnityEditor;
|
||||
|
||||
public static class AlloyEditor {
|
||||
public static void DrawAddTabGUI(List<AlloyTabAdd> tabsToAdd) {
|
||||
if (tabsToAdd.Count <= 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
GUI.color = new Color(0.8f, 0.8f, 0.8f, 0.8f);
|
||||
GUILayout.Label("");
|
||||
var rect = GUILayoutUtility.GetLastRect();
|
||||
|
||||
rect.x -= 35.0f;
|
||||
rect.width += 10.0f;
|
||||
|
||||
GUI.color = Color.clear;
|
||||
bool add = GUI.Button(rect, new GUIContent(""), "Box");
|
||||
GUI.color = new Color(0.8f, 0.8f, 0.8f, 0.8f);
|
||||
Rect subRect = rect;
|
||||
|
||||
foreach (var tab in tabsToAdd) {
|
||||
GUI.color = tab.Color;
|
||||
GUI.Box(subRect, "", "ShurikenModuleTitle");
|
||||
|
||||
subRect.x += rect.width / tabsToAdd.Count;
|
||||
subRect.width -= rect.width / tabsToAdd.Count;
|
||||
}
|
||||
|
||||
GUI.color = new Color(0.8f, 0.8f, 0.8f, 0.8f);
|
||||
|
||||
var delRect = rect;
|
||||
delRect.xMin = rect.xMax;
|
||||
delRect.xMax += 40.0f;
|
||||
|
||||
if (GUI.Button(delRect, "", "ShurikenModuleTitle") || add) {
|
||||
var menu = new GenericMenu();
|
||||
|
||||
foreach (var tab in tabsToAdd) {
|
||||
menu.AddItem(new GUIContent(tab.Name), false, tab.Enable);
|
||||
}
|
||||
|
||||
menu.ShowAsContext();
|
||||
}
|
||||
|
||||
delRect.x += 10.0f;
|
||||
|
||||
GUI.Label(delRect, "+");
|
||||
rect.x += EditorGUIUtility.currentViewWidth / 2.0f - 30.0f;
|
||||
|
||||
// Ensures tab text is always white, even when using light skin in pro.
|
||||
GUI.color = EditorGUIUtility.isProSkin ? new Color(0.7f, 0.7f, 0.7f) : new Color(0.9f, 0.9f, 0.9f);
|
||||
GUI.Label(rect, "Add tab", EditorStyles.whiteLabel);
|
||||
GUI.color = Color.white;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: dd3f45d6cfc037e43baa01683c2ead46
|
||||
timeCreated: 1447518555
|
||||
licenseType: Pro
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,28 @@
|
||||
// Alloy Physical Shader Framework
|
||||
// Copyright 2013-2017 RUST LLC.
|
||||
// http://www.alloy.rustltd.com/
|
||||
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
|
||||
public static class AlloyMenuGroups {
|
||||
[MenuItem(AlloyUtils.MenuItem + "Documentation", false, 100)]
|
||||
static void Documentation() {
|
||||
Application.OpenURL("https://alloy.rustltd.com/documentation");
|
||||
}
|
||||
|
||||
[MenuItem(AlloyUtils.MenuItem + "Samples", false, 100)]
|
||||
static void Samples() {
|
||||
Application.OpenURL("https://www.assetstore.unity3d.com/en/#!/content/43687");
|
||||
}
|
||||
|
||||
[MenuItem(AlloyUtils.MenuItem + "Contact", false, 100)]
|
||||
static void Contact() {
|
||||
Application.OpenURL("https://alloy.rustltd.com/contact");
|
||||
}
|
||||
|
||||
[MenuItem(AlloyUtils.MenuItem + "About", false, 100)]
|
||||
static void About() {
|
||||
Application.OpenURL("https://alloy.rustltd.com/");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 85976895d5de5ee4f914e54f4aae9905
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
@@ -0,0 +1,289 @@
|
||||
// Alloy Physical Shader Framework
|
||||
// Copyright 2013-2017 RUST LLC.
|
||||
// http://www.alloy.rustltd.com/
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.IO;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
|
||||
public static class AlloyMigrationTools {
|
||||
#if H3VR_IMPORTED
|
||||
private const string keywordReportFilename = "/Alloy/Scripts/Material Report.txt";
|
||||
|
||||
[MenuItem(AlloyUtils.MenuItem + "Material Report", false, 11)]
|
||||
private static void MaterialReport() {
|
||||
var fileName = Application.dataPath + keywordReportFilename;
|
||||
var sr = File.CreateText(fileName);
|
||||
var materials = GetSceneMaterialsWithKeywords().OrderBy(m => m.name);
|
||||
var keywordList = materials
|
||||
.SelectMany(m => m.shaderKeywords)
|
||||
.Where(k => !string.IsNullOrEmpty(k))
|
||||
.Distinct()
|
||||
.OrderBy(k => k);
|
||||
var keywordCount = keywordList.Count();
|
||||
var materialShaderNames = new List<string>();
|
||||
|
||||
sr.WriteLine(" ");
|
||||
sr.WriteLine("-----------------------------------------------------------------------");
|
||||
sr.WriteLine(" Keywords: " + keywordCount);
|
||||
sr.WriteLine("-----------------------------------------------------------------------");
|
||||
|
||||
foreach (var keyword in keywordList) {
|
||||
sr.WriteLine("\"" + keyword + "\",");
|
||||
}
|
||||
|
||||
sr.WriteLine(" ");
|
||||
sr.WriteLine("-----------------------------------------------------------------------");
|
||||
sr.WriteLine(" Keywords -> Materials: " + keywordCount);
|
||||
sr.WriteLine("-----------------------------------------------------------------------");
|
||||
|
||||
foreach (var keyword in keywordList) {
|
||||
sr.WriteLine("\"" + keyword + "\",");
|
||||
|
||||
foreach (var material in materials) {
|
||||
var shaderKeywords = material.shaderKeywords;
|
||||
|
||||
if (shaderKeywords.Contains(keyword)) {
|
||||
sr.WriteLine(" " + material.name);
|
||||
}
|
||||
}
|
||||
|
||||
sr.WriteLine(" ");
|
||||
}
|
||||
|
||||
sr.WriteLine("-----------------------------------------------------------------------");
|
||||
sr.WriteLine(" Materials -> Keywords: " + materials.Count());
|
||||
sr.WriteLine("-----------------------------------------------------------------------");
|
||||
|
||||
foreach (var material in materials) {
|
||||
var shaderKeywords = material.shaderKeywords.OrderBy(k => k);
|
||||
|
||||
sr.WriteLine(material.name);
|
||||
|
||||
foreach (var keyword in shaderKeywords) {
|
||||
if (!string.IsNullOrEmpty(keyword)) {
|
||||
sr.WriteLine(" \"" + keyword + "\",");
|
||||
}
|
||||
}
|
||||
|
||||
sr.WriteLine(" ");
|
||||
materialShaderNames.Add(material.shader.name);
|
||||
}
|
||||
|
||||
var shaderNames = materialShaderNames.Distinct().OrderBy(s => s);
|
||||
|
||||
sr.WriteLine("-----------------------------------------------------------------------");
|
||||
sr.WriteLine(" Shaders -> Materials: " + shaderNames.Count());
|
||||
sr.WriteLine("-----------------------------------------------------------------------");
|
||||
|
||||
foreach (var shaderName in shaderNames) {
|
||||
var shaderMaterials = materials.Where(m => m.shader.name == shaderName).Select(m => m.name);
|
||||
|
||||
sr.WriteLine("\"" + shaderName + "\"");
|
||||
|
||||
foreach (var materialName in shaderMaterials) {
|
||||
if (!string.IsNullOrEmpty(materialName)) {
|
||||
sr.WriteLine(" " + materialName);
|
||||
}
|
||||
}
|
||||
|
||||
sr.WriteLine(" ");
|
||||
}
|
||||
|
||||
sr.Close();
|
||||
System.Diagnostics.Process.Start(fileName);
|
||||
}
|
||||
|
||||
// [MenuItem(AlloyUtils.MenuItem + "Material Migrator", false, 11)]
|
||||
// private static void MaterialMigrator() {
|
||||
// var window = ScriptableObject.CreateInstance<AlloyMaterialMigratorPopup>();
|
||||
// var dimensions = new Vector2(350, 100);
|
||||
//
|
||||
// window.position = new Rect(Screen.width / 2, Screen.height / 2, 0, 0);
|
||||
// window.minSize = dimensions;
|
||||
// window.maxSize = dimensions;
|
||||
// window.ShowUtility();
|
||||
// }
|
||||
|
||||
[MenuItem(AlloyUtils.MenuItem + "Light Converter", false, 11)]
|
||||
private static void LightConverter() {
|
||||
var lights = Resources.FindObjectsOfTypeAll<Light>();
|
||||
var lightsLength = lights.Length;
|
||||
|
||||
for (int i = 0; i < lightsLength; i++) {
|
||||
var light = lights[i];
|
||||
|
||||
EditorUtility.DisplayProgressBar(
|
||||
"Converting lights...",
|
||||
string.Format("Light {0} / {1}.", i + 1, lightsLength),
|
||||
i / (lightsLength - 1.0f));
|
||||
|
||||
// Skip Unity baked Area Lights & Prefabs.
|
||||
if (light.type != LightType.Area
|
||||
&& !EditorUtility.IsPersistent(light)) {
|
||||
var area = light.GetComponent<AlloyAreaLight>();
|
||||
|
||||
if (area == null) {
|
||||
Undo.RecordObject(light.gameObject, "Convert to Alloy area lights.");
|
||||
area = Undo.AddComponent<AlloyAreaLight>(light.gameObject);
|
||||
}
|
||||
|
||||
Undo.RecordObject(light, "Set default light cookie");
|
||||
area.UpdateBinding();
|
||||
}
|
||||
}
|
||||
|
||||
EditorUtility.ClearProgressBar();
|
||||
}
|
||||
|
||||
private static IEnumerable<Material> GetSceneMaterialsWithKeywords() {
|
||||
return Resources.FindObjectsOfTypeAll<Material>().Where(m => m.shaderKeywords.Length > 0);
|
||||
}
|
||||
}
|
||||
|
||||
public class AlloyMaterialMigratorPopup : EditorWindow {
|
||||
private const string messageFilename = "/Alloy/Scripts/Editor/MaterialMigratorWarning.txt";
|
||||
private static string[] keywordsToRemove = new string[] {
|
||||
"_AO2MAPUV_UV0",
|
||||
"_AO2MAPUV_UV1",
|
||||
"_BLENDMAPUV_UV0",
|
||||
"_BLENDMAPUV_UV1",
|
||||
"_BUMPMODE_BUMP",
|
||||
"_BUMPMODE_PARALLAX", // Set by stupid KeywordEnum.
|
||||
"_BUMPMODE_SPOM",
|
||||
"_CARFLAKEMAPUV_UV0",
|
||||
"_CARFLAKEMAPUV_UV1",
|
||||
"_DECAL_OFF",
|
||||
"_DECALMODE_NONE",
|
||||
"_DECALTEXUV_UV0",
|
||||
"_DECALTEXUV_UV1",
|
||||
"_DETAIL_ON", // Replaced with _DETAIL_MULX2
|
||||
"_DETAILALBEDOMAPUV_UV0",
|
||||
"_DETAILALBEDOMAPUV_UV1",
|
||||
"_DETAILMASKSSOURCE_TEXTURE", // From when I was trying that Masks channel picker idea. >_<
|
||||
"_DETAILMASKSOURCE_TEXTURE", // Discarded first attempt at name.
|
||||
"_DETAILMASKSOURCE_TEXTUREALPHA", // Set by stupid KeywordEnum.
|
||||
"_DETAILMASKSOURCE_VERTEXCOLORALPHA", // Replaced with _NORMALMAP
|
||||
"_DETAILMODE_MUL",
|
||||
"_DETAILMODE_MULX2",
|
||||
"_DIRECTIONALBLENDMODE_OBJECT", // Set by stupid KeywordEnum.
|
||||
"_DISSOLVETEXUV_UV0",
|
||||
"_DISSOLVETEXUV_UV1",
|
||||
"_EMISSION_ON",
|
||||
"_ENVIRONMENTMAPMODE_RSRM",
|
||||
"_ENVIRONMENTMAPMODE_SKYSHOP",
|
||||
"_ENVIRONMENTMAPMODE_SKYSHOPSH",
|
||||
"_INCANDESCENCEMAPUV_UV0",
|
||||
"_INCANDESCENCEMAPUV_UV1",
|
||||
"_INCANDESCENCEMAPUV2_UV0",
|
||||
"_INCANDESCENCEMAPUV2_UV1",
|
||||
"_MAINTEXTURESMODE_FULL",
|
||||
"_MAINTEXTURESMODE_LITE",
|
||||
"_MAINTEXTURESROUGHNESSSOURCE_BASECOLORALPHA", // Discarded first attempt at name.
|
||||
"_MAINTEXTURESROUGHNESSSOURCE_MATERIALALPHA", // Discarded first attempt at name.
|
||||
"_MAINROUGHNESSSOURCE_BASECOLORALPHA", // Replaced with _SMOOTHNESS_TEXTURE_ALBEDO_CHANNEL_A
|
||||
"_MAINROUGHNESSSOURCE_PACKEDMAPALPHA", // Set by stupid KeywordEnum.
|
||||
"_ORIENTEDROUGHNESSSOURCE_BASECOLORALPHA", // Replaced with _SPECGLOSSMAP
|
||||
"_ORIENTEDROUGHNESSSOURCE_PACKEDMAPALPHA", // Set by stupid KeywordEnum.
|
||||
"_ORIENTEDTEXTURESMODE_FULL",
|
||||
"_ORIENTEDTEXTURESMODE_LITE",
|
||||
"_ORIENTEDTEXTURESROUGHNESSSOURCE_BASECOLORALPHA", // Discarded first attempt at name.
|
||||
"_ORIENTEDTEXTURESROUGHNESSSOURCE_MATERIALALPHA", // Discarded first attempt at name.
|
||||
"_PARALLAX_ON", // Replaced with _PARALLAXMAP
|
||||
"_RIMTEXUV_UV0",
|
||||
"_RIMTEXUV_UV1",
|
||||
"_RIMTEXUV2_UV0",
|
||||
"_RIMTEXUV2_UV1",
|
||||
"_SECONDARYROUGHNESSSOURCE_BASECOLORALPHA", // Replaced with _METALLICGLOSSMAP
|
||||
"_SECONDARYROUGHNESSSOURCE_PACKEDMAPALPHA", // Set by stupid KeywordEnum.
|
||||
"_SECONDARYTEXTURESMODE_FULL",
|
||||
"_SECONDARYTEXTURESMODE_LITE",
|
||||
"_TESSELLATIONMODE_COMBINED", // Dropped this mode in favor of using two other modes keywords together.
|
||||
"_TRANSITIONTEXUV_UV0",
|
||||
"_TRANSITIONTEXUV_UV1",
|
||||
"_TRIPLANARMODE_OBJECT", // Set by stupid KeywordEnum.
|
||||
"_UVSEC_UV0", // Standard shader sets this.
|
||||
"_UVSEC_UV1", // Standard shader sets this.
|
||||
};
|
||||
|
||||
void OnGUI() {
|
||||
var message = File.ReadAllText(Application.dataPath + messageFilename);
|
||||
|
||||
titleContent = new GUIContent("Migrate Materials?");
|
||||
EditorGUILayout.LabelField(message, EditorStyles.wordWrappedLabel);
|
||||
GUILayout.Space(10);
|
||||
|
||||
EditorGUILayout.BeginHorizontal();
|
||||
GUILayout.FlexibleSpace();
|
||||
|
||||
if (GUILayout.Button("Confirm")) {
|
||||
Close();
|
||||
MigrateMaterials();
|
||||
}
|
||||
|
||||
if (GUILayout.Button("Cancel")) {
|
||||
Close();
|
||||
}
|
||||
|
||||
GUILayout.FlexibleSpace();
|
||||
EditorGUILayout.EndHorizontal();
|
||||
}
|
||||
|
||||
void MigrateMaterials() {
|
||||
try {
|
||||
var materialGuids = AssetDatabase.FindAssets("t:material");
|
||||
var length = materialGuids.Length;
|
||||
|
||||
for (int i = 0; i < length; i++) {
|
||||
var material = AssetDatabase.LoadAssetAtPath(AssetDatabase.GUIDToAssetPath(materialGuids[i]), typeof(Material)) as Material;
|
||||
var toRemove = material.shaderKeywords.Intersect(keywordsToRemove);
|
||||
var shaderName = material.shader.name;
|
||||
|
||||
EditorUtility.DisplayProgressBar(
|
||||
"Migrating Materials...",
|
||||
string.Format("({0} / {1}) {2}", i, length, material.name),
|
||||
i / (float)(length - 1));
|
||||
|
||||
if (shaderName.Contains("Alloy")) {
|
||||
if (material.HasProperty("_HasBumpMap")
|
||||
&& Mathf.Approximately(material.GetFloat("_HasBumpMap"), 1.0f)) {
|
||||
material.EnableKeyword("EFFECT_BUMP");
|
||||
}
|
||||
|
||||
foreach (var keyword in toRemove) {
|
||||
if (!string.IsNullOrEmpty(keyword)) {
|
||||
material.DisableKeyword(keyword);
|
||||
|
||||
// Migrate to Unity keywords.
|
||||
switch (keyword) {
|
||||
case "_DETAIL_ON":
|
||||
material.EnableKeyword("_DETAIL_MULX2");
|
||||
break;
|
||||
case "_DETAILMASKSOURCE_VERTEXCOLORALPHA":
|
||||
material.EnableKeyword("_NORMALMAP");
|
||||
break;
|
||||
case "_MAINROUGHNESSSOURCE_BASECOLORALPHA":
|
||||
material.EnableKeyword("_SMOOTHNESS_TEXTURE_ALBEDO_CHANNEL_A");
|
||||
break;
|
||||
case "_PARALLAX_ON":
|
||||
material.EnableKeyword("_PARALLAXMAP");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
EditorUtility.SetDirty(material);
|
||||
AssetDatabase.SaveAssets();
|
||||
material = null;
|
||||
EditorUtility.UnloadUnusedAssetsImmediate();
|
||||
}
|
||||
}
|
||||
}
|
||||
finally {
|
||||
EditorUtility.ClearProgressBar();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 222acbd1878d5b3459b1f2946805fba9
|
||||
timeCreated: 1425000426
|
||||
licenseType: Pro
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,51 @@
|
||||
// Alloy Physical Shader Framework
|
||||
// Copyright 2013-2017 RUST LLC.
|
||||
// http://www.alloy.rustltd.com/
|
||||
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
|
||||
|
||||
[CustomPropertyDrawer(typeof(MinValueAttribute))]
|
||||
public class MinValueDrawer : PropertyDrawer {
|
||||
// Draw the property inside the given rect
|
||||
public override void OnGUI(Rect position, SerializedProperty property, GUIContent label) {
|
||||
// Using BeginProperty / EndProperty on the parent property means that
|
||||
// prefab override logic works on the entire property.
|
||||
EditorGUI.BeginProperty(position, label, property);
|
||||
|
||||
// Draw label
|
||||
EditorGUI.BeginChangeCheck();
|
||||
|
||||
float newVal = EditorGUI.FloatField(position, label, property.floatValue);
|
||||
|
||||
if (EditorGUI.EndChangeCheck()) {
|
||||
newVal = Mathf.Max((attribute as MinValueAttribute).Min, newVal);
|
||||
property.floatValue = newVal;
|
||||
}
|
||||
|
||||
EditorGUI.EndProperty();
|
||||
}
|
||||
}
|
||||
|
||||
[CustomPropertyDrawer(typeof(MaxValueAttribute))]
|
||||
public class MaxValueDrawer : PropertyDrawer {
|
||||
// Draw the property inside the given rect
|
||||
public override void OnGUI(Rect position, SerializedProperty property, GUIContent label) {
|
||||
// Using BeginProperty / EndProperty on the parent property means that
|
||||
// prefab override logic works on the entire property.
|
||||
EditorGUI.BeginProperty(position, label, property);
|
||||
|
||||
// Draw label
|
||||
|
||||
EditorGUI.BeginChangeCheck();
|
||||
|
||||
float newVal = EditorGUI.FloatField(position, label, property.floatValue);
|
||||
|
||||
if (EditorGUI.EndChangeCheck()) {
|
||||
newVal = Mathf.Min((attribute as MaxValueAttribute).Max, newVal);
|
||||
property.floatValue = newVal;
|
||||
}
|
||||
EditorGUI.EndProperty();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: cd608910999af3a4e960e52f543102ed
|
||||
timeCreated: 1445390480
|
||||
licenseType: Pro
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,54 @@
|
||||
// Alloy Physical Shader Framework
|
||||
// Copyright 2013-2017 RUST LLC.
|
||||
// http://www.alloy.rustltd.com/
|
||||
|
||||
using System.IO;
|
||||
|
||||
using UnityEngine;
|
||||
using UnityEditor;
|
||||
|
||||
[InitializeOnLoad]
|
||||
static class AlloyRequiredActions {
|
||||
static AlloyRequiredActions() {
|
||||
// Check if popup hasn't appeared for this version.
|
||||
if (File.Exists(AlloyRequiredActionsPopup.MessageFilePath)
|
||||
&& EditorPrefs.GetString(AlloyRequiredActionsPopup.SettingsKey) != AlloyUtils.Version) {
|
||||
var window = ScriptableObject.CreateInstance<AlloyRequiredActionsPopup>();
|
||||
var dimensions = new Vector2(350, 200);
|
||||
|
||||
window.position = new Rect(Screen.width / 2, Screen.height / 2, 0, 0);
|
||||
window.minSize = dimensions;
|
||||
window.maxSize = dimensions;
|
||||
window.ShowUtility();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class AlloyRequiredActionsPopup : EditorWindow {
|
||||
public const string SettingsKey = "AlloyRequiredActionsPopupShown";
|
||||
|
||||
public static string MessageFilePath {
|
||||
get { return AlloyUtils.AssetsPath + "REQUIRED ACTIONS.txt"; }
|
||||
}
|
||||
|
||||
void OnGUI() {
|
||||
var message = File.ReadAllText(MessageFilePath);
|
||||
|
||||
titleContent = new GUIContent(string.Format("Required Actions for Alloy {0}...", AlloyUtils.Version));
|
||||
EditorGUILayout.LabelField(message, EditorStyles.wordWrappedLabel);
|
||||
GUILayout.Space(10);
|
||||
|
||||
EditorGUILayout.BeginHorizontal();
|
||||
GUILayout.FlexibleSpace();
|
||||
|
||||
if (GUILayout.Button("Okay")) {
|
||||
Close();
|
||||
}
|
||||
|
||||
GUILayout.FlexibleSpace();
|
||||
EditorGUILayout.EndHorizontal();
|
||||
|
||||
// Make sure it doesn't reappear again for this version.
|
||||
EditorPrefs.SetString(SettingsKey, AlloyUtils.Version);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c605d19298efffc45afeb01a1a5086fa
|
||||
timeCreated: 1473702994
|
||||
licenseType: Pro
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,3 @@
|
||||
We STRONGLY recommend that you save and back up your work before proceeding.
|
||||
|
||||
Do you wish to continue?
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: e579897034a773341b981f6cb2ab54c6
|
||||
timeCreated: 1474115145
|
||||
licenseType: Pro
|
||||
TextScriptImporter:
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,9 @@
|
||||
fileFormatVersion: 2
|
||||
guid: d774905ce3293694e97161cbf47d6542
|
||||
folderAsset: yes
|
||||
timeCreated: 1439503600
|
||||
licenseType: Pro
|
||||
DefaultImporter:
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,288 @@
|
||||
// Alloy Physical Shader Framework
|
||||
// Copyright 2013-2017 RUST LLC.
|
||||
// http://www.alloy.rustltd.com/
|
||||
|
||||
using System;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Rendering;
|
||||
|
||||
#if UNITY_EDITOR
|
||||
using UnityEditor;
|
||||
#endif
|
||||
|
||||
[ExecuteInEditMode]
|
||||
[ImageEffectAllowedInSceneView]
|
||||
[RequireComponent(typeof (Camera))]
|
||||
[AddComponentMenu(AlloyUtils.ComponentMenu + "Effects Manager")]
|
||||
public class AlloyEffectsManager : MonoBehaviour {
|
||||
|
||||
// Arbitrary range multiplier.
|
||||
private const float c_blurWdith = 0.15f;
|
||||
private const float c_blurDepthDifferenceMultiplier = 100.0f;
|
||||
private const string c_copyTransmissionBufferName = "AlloyCopyTransmission";
|
||||
private const string c_blurNormalsBufferName = "AlloyBlurNormals";
|
||||
private const CameraEvent c_copyTransmissionEvent = CameraEvent.AfterGBuffer;
|
||||
private const CameraEvent c_blurNormalsEvent = CameraEvent.BeforeLighting;
|
||||
|
||||
[Serializable]
|
||||
public struct SkinSettingsData {
|
||||
public bool Enabled;
|
||||
public Texture2D Lut;
|
||||
|
||||
[Range(0.0f, 1.0f)]
|
||||
public float Weight;
|
||||
|
||||
[Range(0.01f, 1.0f)]
|
||||
public float MaskCutoff;
|
||||
|
||||
[Range(0.0f, 1.0f)]
|
||||
public float Bias;
|
||||
|
||||
[Range(0.0f, 1.0f)]
|
||||
public float Scale;
|
||||
|
||||
[Range(0.0f, 1.0f)]
|
||||
public float BumpBlur;
|
||||
|
||||
public Vector3 Absorption;
|
||||
public Vector3 AoColorBleed;
|
||||
}
|
||||
|
||||
[Serializable]
|
||||
public struct TransmissionSettingsData {
|
||||
public bool Enabled;
|
||||
|
||||
[Range(0.0f, 1.0f)]
|
||||
public float Weight;
|
||||
|
||||
[Range(0.0f, 1.0f)]
|
||||
public float ShadowWeight;
|
||||
|
||||
[Range(0.0f, 1.0f)]
|
||||
[Tooltip("Amount that the transmission is distorted by surface normals.")]
|
||||
public float BumpDistortion;
|
||||
|
||||
[MinValue(1.0f)]
|
||||
public float Falloff;
|
||||
}
|
||||
|
||||
public SkinSettingsData SkinSettings = new SkinSettingsData() {
|
||||
Enabled = true,
|
||||
Weight = 1.0f,
|
||||
MaskCutoff = 0.1f,
|
||||
Bias = 0.0f,
|
||||
Scale = 1.0f,
|
||||
BumpBlur = 0.7f,
|
||||
Absorption = new Vector3(-8.0f, -40.0f, -64.0f),
|
||||
AoColorBleed = new Vector3(0.4f, 0.15f, 0.13f),
|
||||
};
|
||||
|
||||
public TransmissionSettingsData TransmissionSettings = new TransmissionSettingsData {
|
||||
Enabled = true,
|
||||
Weight = 1.0f,
|
||||
ShadowWeight = 0.5f,
|
||||
BumpDistortion = 0.05f,
|
||||
Falloff = 1.0f
|
||||
};
|
||||
|
||||
// LUT
|
||||
[HideInInspector] public Texture2D SkinLut;
|
||||
|
||||
// Shaders
|
||||
[HideInInspector] public Shader TransmissionBlitShader;
|
||||
[HideInInspector] public Shader BlurNormalsShader;
|
||||
|
||||
// Private
|
||||
private Material m_deferredTransmissionBlitMaterial;
|
||||
private Material m_deferredBlurredNormalsMaterial;
|
||||
|
||||
private Camera m_camera;
|
||||
private bool m_isTransmissionEnabled;
|
||||
private bool m_isScatteringEnabled;
|
||||
|
||||
private CommandBuffer m_copyTransmission;
|
||||
private CommandBuffer m_renderBlurredNormals;
|
||||
|
||||
#if UNITY_EDITOR
|
||||
private int lastWidth = 0;
|
||||
private int lastHeight = 0;
|
||||
#endif
|
||||
|
||||
private void Awake() {
|
||||
m_camera = GetComponent<Camera>();
|
||||
}
|
||||
|
||||
private void Reset() {
|
||||
ResetCommandBuffers();
|
||||
}
|
||||
|
||||
#if UNITY_EDITOR
|
||||
private void Update() {
|
||||
if (lastWidth != m_camera.pixelWidth
|
||||
|| lastHeight != m_camera.pixelHeight) {
|
||||
ResetCommandBuffers();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
private void OnEnable() {
|
||||
ResetCommandBuffers();
|
||||
}
|
||||
|
||||
private void OnDisable() {
|
||||
DestroyCommandBuffers();
|
||||
}
|
||||
|
||||
private void OnDestroy() {
|
||||
DestroyCommandBuffers();
|
||||
}
|
||||
|
||||
public void Refresh() {
|
||||
bool scatteringEnabled = SkinSettings.Enabled;
|
||||
bool transmissionEnabled = TransmissionSettings.Enabled || scatteringEnabled;
|
||||
|
||||
if (m_isTransmissionEnabled == transmissionEnabled
|
||||
&& m_isScatteringEnabled == scatteringEnabled) {
|
||||
RefreshProperties();
|
||||
}
|
||||
else {
|
||||
ResetCommandBuffers();
|
||||
}
|
||||
}
|
||||
|
||||
// Per camera properties.
|
||||
private void RefreshProperties() {
|
||||
if (m_isTransmissionEnabled || m_isScatteringEnabled) {
|
||||
float transmissionWeight = m_isTransmissionEnabled ? Mathf.GammaToLinearSpace(TransmissionSettings.Weight) : 0.0f;
|
||||
|
||||
Shader.SetGlobalVector("_DeferredTransmissionParams",
|
||||
new Vector4(transmissionWeight, TransmissionSettings.Falloff, TransmissionSettings.BumpDistortion, TransmissionSettings.ShadowWeight));
|
||||
|
||||
if (m_isScatteringEnabled) {
|
||||
// Blur shaders.
|
||||
float distanceToProjectionWindow = 1.0f / Mathf.Tan(0.5f * Mathf.Deg2Rad * m_camera.fieldOfView);
|
||||
float blurStepScale = c_blurWdith * distanceToProjectionWindow;
|
||||
float blurDepthDifferenceScale = c_blurDepthDifferenceMultiplier * distanceToProjectionWindow;
|
||||
|
||||
Shader.SetGlobalVector("_DeferredBlurredNormalsParams", new Vector2(blurStepScale, blurDepthDifferenceScale));
|
||||
|
||||
// Material shaders.
|
||||
var absorption = SkinSettings.Absorption;
|
||||
var aoColorBleed = SkinSettings.AoColorBleed;
|
||||
|
||||
Shader.SetGlobalTexture("_DeferredSkinLut", SkinSettings.Lut);
|
||||
Shader.SetGlobalVector("_DeferredSkinParams", new Vector3(SkinSettings.Weight, 1.0f / SkinSettings.MaskCutoff, SkinSettings.BumpBlur));
|
||||
Shader.SetGlobalVector("_DeferredSkinTransmissionAbsorption", new Vector4(absorption.x, absorption.y, absorption.z, SkinSettings.Bias));
|
||||
Shader.SetGlobalVector("_DeferredSkinColorBleedAoWeights", new Vector4(aoColorBleed.x, aoColorBleed.y, aoColorBleed.z, SkinSettings.Scale));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void ResetCommandBuffers() {
|
||||
m_isScatteringEnabled = SkinSettings.Enabled;
|
||||
m_isTransmissionEnabled = TransmissionSettings.Enabled || m_isScatteringEnabled;
|
||||
|
||||
if (SkinSettings.Lut == null) {
|
||||
SkinSettings.Lut = SkinLut;
|
||||
|
||||
#if UNITY_EDITOR
|
||||
EditorUtility.SetDirty(this);
|
||||
#endif
|
||||
}
|
||||
|
||||
DestroyCommandBuffers();
|
||||
|
||||
if ((m_isTransmissionEnabled || m_isScatteringEnabled)
|
||||
&& m_camera != null
|
||||
&& TransmissionBlitShader != null) {
|
||||
int outputRT = Shader.PropertyToID("_DeferredPlusBuffer");
|
||||
|
||||
#if UNITY_EDITOR
|
||||
// Reference for when screen size changes.
|
||||
lastWidth = m_camera.pixelWidth;
|
||||
lastHeight = m_camera.pixelHeight;
|
||||
#endif
|
||||
|
||||
m_deferredTransmissionBlitMaterial = new Material(TransmissionBlitShader);
|
||||
m_deferredTransmissionBlitMaterial.hideFlags = HideFlags.HideAndDontSave;
|
||||
|
||||
// Copy Gbuffer emission buffer so we can get at the alpha channel for transmission.
|
||||
m_copyTransmission = new CommandBuffer();
|
||||
m_copyTransmission.name = c_copyTransmissionBufferName;
|
||||
|
||||
if (!m_isScatteringEnabled) {
|
||||
// Copy transmission from emission buffer alpha.
|
||||
m_copyTransmission.GetTemporaryRT(outputRT, -1, -1, 0, FilterMode.Point, RenderTextureFormat.ARGB32, RenderTextureReadWrite.Linear);
|
||||
m_copyTransmission.Blit(BuiltinRenderTextureType.CameraTarget, outputRT, m_deferredTransmissionBlitMaterial);
|
||||
m_copyTransmission.ReleaseTemporaryRT(outputRT);
|
||||
}
|
||||
else if (BlurNormalsShader != null) {
|
||||
int halfWidth = m_camera.pixelWidth / 2;
|
||||
int halfHeight = m_camera.pixelHeight / 2;
|
||||
int pingRT = Shader.PropertyToID("_DeferredBlurredNormalPingBuffer");
|
||||
int pongRT = Shader.PropertyToID("_DeferredBlurredNormalPongBuffer");
|
||||
|
||||
// Bind emission buffer to be copied in blurred normal upsample pass.
|
||||
m_copyTransmission.SetGlobalTexture("_DeferredTransmissionBuffer", BuiltinRenderTextureType.CameraTarget);
|
||||
|
||||
// Blur normals and copy transmission.
|
||||
m_deferredBlurredNormalsMaterial = new Material(BlurNormalsShader);
|
||||
m_deferredBlurredNormalsMaterial.hideFlags = HideFlags.HideAndDontSave;
|
||||
|
||||
m_renderBlurredNormals = new CommandBuffer();
|
||||
m_renderBlurredNormals.name = c_blurNormalsBufferName;
|
||||
|
||||
// RGBA8 target has sufficient precision for normals that are smooth and diffuse-only.
|
||||
m_renderBlurredNormals.GetTemporaryRT(outputRT, -1, -1, 0, FilterMode.Point, RenderTextureFormat.ARGB32, RenderTextureReadWrite.Linear);
|
||||
m_renderBlurredNormals.GetTemporaryRT(pingRT, halfWidth, halfHeight, 0, FilterMode.Point, RenderTextureFormat.ARGBHalf, RenderTextureReadWrite.Linear);
|
||||
m_renderBlurredNormals.GetTemporaryRT(pongRT, halfWidth, halfHeight, 0, FilterMode.Point, RenderTextureFormat.ARGBHalf, RenderTextureReadWrite.Linear);
|
||||
|
||||
// Downsample, Blur X, Blur Y, Upsample.
|
||||
m_renderBlurredNormals.Blit(BuiltinRenderTextureType.GBuffer2, pingRT, m_deferredBlurredNormalsMaterial, 0);
|
||||
m_renderBlurredNormals.Blit(pingRT, pongRT, m_deferredBlurredNormalsMaterial, 1);
|
||||
m_renderBlurredNormals.Blit(pongRT, pingRT, m_deferredBlurredNormalsMaterial, 2);
|
||||
m_renderBlurredNormals.Blit(pingRT, outputRT, m_deferredBlurredNormalsMaterial, 3);
|
||||
|
||||
// Cleanup.
|
||||
m_renderBlurredNormals.ReleaseTemporaryRT(outputRT);
|
||||
m_renderBlurredNormals.ReleaseTemporaryRT(pingRT);
|
||||
m_renderBlurredNormals.ReleaseTemporaryRT(pongRT);
|
||||
|
||||
// Need depth texture for depth-aware upsample.
|
||||
m_camera.depthTextureMode |= DepthTextureMode.Depth;
|
||||
m_camera.AddCommandBuffer(c_blurNormalsEvent, m_renderBlurredNormals);
|
||||
}
|
||||
|
||||
m_camera.AddCommandBuffer(c_copyTransmissionEvent, m_copyTransmission);
|
||||
}
|
||||
|
||||
RefreshProperties();
|
||||
|
||||
#if UNITY_EDITOR
|
||||
EditorUtility.SetDirty(m_camera);
|
||||
#endif
|
||||
}
|
||||
|
||||
private void DestroyCommandBuffers() {
|
||||
if (m_copyTransmission != null) {
|
||||
m_camera.RemoveCommandBuffer(c_copyTransmissionEvent, m_copyTransmission);
|
||||
}
|
||||
|
||||
if (m_renderBlurredNormals != null) {
|
||||
m_camera.RemoveCommandBuffer(c_blurNormalsEvent, m_renderBlurredNormals);
|
||||
}
|
||||
|
||||
if (m_deferredTransmissionBlitMaterial != null) {
|
||||
DestroyImmediate(m_deferredTransmissionBlitMaterial);
|
||||
}
|
||||
|
||||
if (m_deferredBlurredNormalsMaterial != null) {
|
||||
DestroyImmediate(m_deferredBlurredNormalsMaterial);
|
||||
}
|
||||
|
||||
m_copyTransmission = null;
|
||||
m_renderBlurredNormals = null;
|
||||
m_deferredTransmissionBlitMaterial = null;
|
||||
m_deferredBlurredNormalsMaterial = null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
fileFormatVersion: 2
|
||||
guid: bf5b97b13ec5bae41ac96a39caf39874
|
||||
timeCreated: 1487764061
|
||||
licenseType: Pro
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences:
|
||||
- SkinLut: {fileID: 2800000, guid: d13510bb2be49aa40a66a0101efb6a36, type: 3}
|
||||
- TransmissionBlitShader: {fileID: 4800000, guid: 4bbeef29a84b4ed498f2d4a7d9fcefc4,
|
||||
type: 3}
|
||||
- BlurNormalsShader: {fileID: 4800000, guid: 5b34ef975c671984fb9c93adc7042982, type: 3}
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,9 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c7a3813b9ad39d847b4acc42619b3256
|
||||
folderAsset: yes
|
||||
timeCreated: 1445386286
|
||||
licenseType: Pro
|
||||
DefaultImporter:
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,39 @@
|
||||
// Alloy Physical Shader Framework
|
||||
// Copyright 2013-2017 RUST LLC.
|
||||
// http://www.alloy.rustltd.com/
|
||||
using System;
|
||||
using System.Linq;
|
||||
using MeatKit;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
|
||||
[CustomEditor(typeof(Camera))]
|
||||
[CanEditMultipleObjects]
|
||||
public class AlloyCameraEditor : Editor {
|
||||
Editor m_editor;
|
||||
|
||||
Type GetTypeGlobal(string typeName) {
|
||||
return AppDomain.CurrentDomain.GetAssemblies().SelectMany(a => a.GetTypesSafe()).FirstOrDefault(t => t.Name == typeName);
|
||||
}
|
||||
|
||||
void OnEnable() {
|
||||
m_editor = CreateEditor(targets, GetTypeGlobal("CameraEditor"));
|
||||
}
|
||||
|
||||
void OnDisable() {
|
||||
DestroyImmediate(m_editor);
|
||||
}
|
||||
|
||||
public override void OnInspectorGUI() {
|
||||
m_editor.OnInspectorGUI();
|
||||
bool anyMissing = targets.Any(c => ((Camera)c).GetComponent<AlloyEffectsManager>() == null);
|
||||
|
||||
if (anyMissing) {
|
||||
if (GUILayout.Button("Convert to Alloy Effects Manager", EditorStyles.toolbarButton)) {
|
||||
foreach (Camera camera in targets) {
|
||||
Undo.AddComponent<AlloyEffectsManager>(camera.gameObject);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: dc5a924e062584c4b994b26019b1b30c
|
||||
timeCreated: 1491670701
|
||||
licenseType: Pro
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,142 @@
|
||||
// Alloy Physical Shader Framework
|
||||
// Copyright 2013-2017 RUST LLC.
|
||||
// http://www.alloy.rustltd.com/
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Alloy;
|
||||
using UnityEditor;
|
||||
using UnityEditor.AnimatedValues;
|
||||
using UnityEngine;
|
||||
|
||||
[CustomEditor(typeof(AlloyEffectsManager))]
|
||||
public class AlloyEffectsManagerEditor : Editor {
|
||||
private const string c_skinTabName = "SkinTab";
|
||||
private const string c_transmissionTabName = "TransmissionTab";
|
||||
private static Color s_scatterColor = new Color(0.49f, 0.36f, 0.16f);
|
||||
private static Color s_transmissionColor = new Color(0.49f, 0.46f, 0.16f);
|
||||
|
||||
private AlloyTabGroup m_tabGroup;
|
||||
private AnimBool m_skinGroup;
|
||||
private AnimBool m_transmissionGroup;
|
||||
private List<AlloyTabAdd> m_tabAdd = new List<AlloyTabAdd>();
|
||||
private GenericMenu m_menu;
|
||||
|
||||
private void OnEnable() {
|
||||
m_tabGroup = AlloyTabGroup.GetTabGroup();
|
||||
m_skinGroup = new AnimBool(m_tabGroup.IsOpen(c_skinTabName));
|
||||
m_transmissionGroup = new AnimBool(m_tabGroup.IsOpen(c_transmissionTabName));
|
||||
}
|
||||
|
||||
public override void OnInspectorGUI() {
|
||||
serializedObject.Update();
|
||||
m_tabAdd.Clear();
|
||||
|
||||
var skinEnabled = serializedObject.FindProperty("SkinSettings.Enabled");
|
||||
|
||||
if (skinEnabled.boolValue && !skinEnabled.hasMultipleDifferentValues) {
|
||||
bool removed;
|
||||
m_skinGroup.target = m_tabGroup.TabArea("Skin Scattering", s_scatterColor, true, out removed,
|
||||
c_skinTabName);
|
||||
|
||||
if (EditorGUILayout.BeginFadeGroup(m_skinGroup.faded)) {
|
||||
var prop = serializedObject.FindProperty("SkinSettings");
|
||||
prop.Next(true); //skip flag
|
||||
prop.Next(true); //skip enabled
|
||||
|
||||
DrawRemainingProp(prop);
|
||||
}
|
||||
|
||||
EditorGUILayout.EndFadeGroup();
|
||||
|
||||
if (removed) {
|
||||
skinEnabled.boolValue = false;
|
||||
}
|
||||
}
|
||||
else {
|
||||
m_tabAdd.Add(new AlloyTabAdd {
|
||||
Color = s_scatterColor,
|
||||
Name = "Skin Scattering",
|
||||
Enable = EnableSkin
|
||||
});
|
||||
}
|
||||
|
||||
var transEnabled = serializedObject.FindProperty("TransmissionSettings.Enabled");
|
||||
|
||||
if (transEnabled.boolValue && !transEnabled.hasMultipleDifferentValues) {
|
||||
bool removed;
|
||||
m_transmissionGroup.target = m_tabGroup.TabArea("Transmission", s_transmissionColor, true, out removed,
|
||||
c_transmissionTabName);
|
||||
|
||||
if (EditorGUILayout.BeginFadeGroup(m_transmissionGroup.faded)) {
|
||||
var prop = serializedObject.FindProperty("TransmissionSettings");
|
||||
prop.Next(true); //skip flag
|
||||
prop.Next(true);//skip enabled
|
||||
DrawRemainingProp(prop);
|
||||
}
|
||||
|
||||
EditorGUILayout.EndFadeGroup();
|
||||
|
||||
if (removed) {
|
||||
transEnabled.boolValue = false;
|
||||
}
|
||||
}
|
||||
else {
|
||||
m_tabAdd.Add(new AlloyTabAdd {
|
||||
Color = s_transmissionColor,
|
||||
Name = "Transmission",
|
||||
Enable = EnableTransmission
|
||||
});
|
||||
}
|
||||
|
||||
if (m_skinGroup.isAnimating || m_transmissionGroup.isAnimating) {
|
||||
Repaint();
|
||||
}
|
||||
|
||||
AlloyEditor.DrawAddTabGUI(m_tabAdd);
|
||||
serializedObject.ApplyModifiedProperties();
|
||||
|
||||
if (GUI.changed) {
|
||||
var deferredRendererPlus = serializedObject.targetObject as AlloyEffectsManager;
|
||||
|
||||
if (deferredRendererPlus != null) {
|
||||
deferredRendererPlus.Refresh();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void EnableTransmission() {
|
||||
foreach (AlloyEffectsManager rend in targets) {
|
||||
rend.TransmissionSettings.Enabled = true;
|
||||
EditorUtility.SetDirty(rend);
|
||||
rend.Refresh();
|
||||
}
|
||||
|
||||
m_transmissionGroup.value = false;
|
||||
m_transmissionGroup.target = true;
|
||||
m_tabGroup.SetOpen(c_transmissionTabName, true);
|
||||
}
|
||||
|
||||
private void EnableSkin() {
|
||||
foreach (AlloyEffectsManager rend in targets) {
|
||||
rend.SkinSettings.Enabled = true;
|
||||
EditorUtility.SetDirty(rend);
|
||||
rend.Refresh();
|
||||
}
|
||||
|
||||
m_skinGroup.value = false;
|
||||
m_skinGroup.target = true;
|
||||
m_tabGroup.SetOpen(c_skinTabName, true);
|
||||
}
|
||||
|
||||
private static void DrawRemainingProp(SerializedProperty prop) {
|
||||
int depth = prop.depth;
|
||||
|
||||
while (true) {
|
||||
bool child = EditorGUILayout.PropertyField(prop, true);
|
||||
|
||||
if (!prop.Next(child) || prop.depth < depth)
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 4d4b26109848fff4daa6b5974417de47
|
||||
timeCreated: 1445386295
|
||||
licenseType: Pro
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,9 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 979804faf9172f54dbdbf0974928665d
|
||||
folderAsset: yes
|
||||
timeCreated: 1439605207
|
||||
licenseType: Pro
|
||||
DefaultImporter:
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,232 @@
|
||||
// Alloy Physical Shader Framework
|
||||
// Copyright 2013-2017 RUST LLC.
|
||||
// http://www.alloy.rustltd.com/
|
||||
|
||||
Shader "Hidden/Alloy/Blur Normals" {
|
||||
Properties {
|
||||
_MainTex ("Render Input", 2D) = "white" {}
|
||||
}
|
||||
SubShader {
|
||||
ZTest Always Cull Off ZWrite Off Fog { Mode Off }
|
||||
|
||||
CGINCLUDE
|
||||
#pragma target 3.0
|
||||
#pragma exclude_renderers gles
|
||||
|
||||
#include "Assets/Alloy/Shaders/Framework/Utility.cginc"
|
||||
|
||||
#include "HLSLSupport.cginc"
|
||||
#include "UnityCG.cginc"
|
||||
#include "UnityDeferredLibrary.cginc"
|
||||
|
||||
// Screen-space diffusion
|
||||
// cf http://www.iryoku.com/screen-space-subsurface-scattering
|
||||
// cf http://uaasoftware.com/xi/PDSS/diffuseShader.fx
|
||||
|
||||
// blurWidth = 0.15
|
||||
// blurDepthDifferenceMultiplier = 100
|
||||
// distanceToProjectionWindow = 1 / tan(radians(FoV) / 2);
|
||||
// blurStepScale = blurWidth * distanceToProjectionWindow
|
||||
// blurDepthDifferenceScale = blurDepthDifferenceMultiplier * distanceToProjectionWindow
|
||||
|
||||
/// Number of downsampling texture taps.
|
||||
#define A_NUM_DOWNSAMPLE_TAPS 4
|
||||
|
||||
/// Downsampling texture coordinate offset directions.
|
||||
static const float2 A_DOWNSAMPLE_OFFSETS[A_NUM_DOWNSAMPLE_TAPS] = {
|
||||
float2(0.0f, 0.0f),
|
||||
float2(1.0f, 0.0f),
|
||||
float2(0.0f, 1.0f),
|
||||
float2(1.0f, 1.0f)
|
||||
};
|
||||
|
||||
/// Number of blur texture taps.
|
||||
#define A_NUM_BLUR_TAPS 7
|
||||
|
||||
/// Gaussian Distribution blur texture coordinate offsets.
|
||||
static const float A_BLUR_OFFSETS[A_NUM_BLUR_TAPS] = {
|
||||
0.0f, -3.0f, -2.0f, -1.0f, 1.0f, 2.0f, 3.0f
|
||||
};
|
||||
|
||||
/// Gaussian Distribution blur sample weights.
|
||||
static const half A_BLUR_WEIGHTS[A_NUM_BLUR_TAPS] = {
|
||||
0.199471h, 0.0647588h, 0.120985h, 0.176033h, 0.176033h, 0.120985h, 0.0647588h
|
||||
};
|
||||
|
||||
/// Number of upsampling texture taps.
|
||||
#define A_NUM_UPSAMPLE_TAPS 4
|
||||
|
||||
/// Upsampling texture coordinate offset directions.
|
||||
static const float2 A_UPSAMPLE_OFFSETS[A_NUM_UPSAMPLE_TAPS] = {
|
||||
float2(0.0f, 1.0f),
|
||||
float2(1.0f, 0.0f),
|
||||
float2(-1.0f, 0.0f),
|
||||
float2(0.0f, -1.0f)
|
||||
};
|
||||
|
||||
/// (X: blurStepScale, Y: blurDepthDifferenceScale).
|
||||
float2 _DeferredBlurredNormalsParams;
|
||||
|
||||
// G-Buffer LAB (transmission in alpha).
|
||||
sampler2D _DeferredTransmissionBuffer;
|
||||
|
||||
/// Pass source texture.
|
||||
sampler2D _MainTex;
|
||||
|
||||
/// Pass source texture (X: Tiling X, Y: Tiling Y, Z: Offset X, W: Offset Y).
|
||||
float4 _MainTex_ST;
|
||||
|
||||
/// Pass source texture (X: 1 / width, Y: 1 / height, Z: width, W: height).
|
||||
float4 _MainTex_TexelSize;
|
||||
|
||||
/// Normal buffer.
|
||||
sampler2D _CameraGBufferTexture2;
|
||||
|
||||
/// Interpolates offet normals to center normals at edge discontinuities.
|
||||
/// @param normalDepth Offset sample (XYZ: Normals, W: Depth).
|
||||
/// @param normalDepthM Center sample (XYZ: Normals, W: Depth).
|
||||
/// @return Edge-corrected normal.
|
||||
half3 aEdgeCorrectNormal(
|
||||
half4 normalDepth,
|
||||
half4 normalDepthM)
|
||||
{
|
||||
// Cheaper than a 5-way blend, which requires inverts and an accumulator.
|
||||
half alpha = saturate(_DeferredBlurredNormalsParams.y * abs(normalDepth.w - normalDepthM.w));
|
||||
return lerp(normalDepth.xyz, normalDepthM.xyz, alpha);
|
||||
}
|
||||
|
||||
/// Downsamples the G-Buffer normals and depth to 1/2 resolution.
|
||||
/// @param IN Vertex input.
|
||||
/// @return Downsampled image (XYZ: Normals, W: Nearest Depth).
|
||||
half4 aDownsample(
|
||||
v2f_img IN)
|
||||
{
|
||||
half depth = 1.0h;
|
||||
half3 normal = 0.0h;
|
||||
|
||||
UNITY_UNROLL
|
||||
for (int i = 1; i < A_NUM_DOWNSAMPLE_TAPS; i++) {
|
||||
float2 coord = UnityStereoScreenSpaceUVAdjust(A_DOWNSAMPLE_OFFSETS[i] * _MainTex_TexelSize.xy + IN.uv, _MainTex_ST);
|
||||
float4 sampleUv = float4(coord, 0.0f, 0.0f);
|
||||
|
||||
// Pre-combine sample weight with normal scale-bias unpack.
|
||||
// 0.25 * (normal * 2 - 1) = normal * 0.5 - 0.25
|
||||
normal += tex2Dlod(_MainTex, sampleUv).xyz * 0.5h - 0.25h;
|
||||
|
||||
// Use projection depth directly to avoid linearizing cost per sample.
|
||||
depth = min(depth, SAMPLE_DEPTH_TEXTURE_LOD(_CameraDepthTexture, sampleUv));
|
||||
}
|
||||
|
||||
// Export unpacked normals and linear depth for subsequent passes.
|
||||
return half4(normal, LinearEyeDepth(depth));
|
||||
}
|
||||
|
||||
/// Blur the source image along the specified axis.
|
||||
/// @param IN Vertex input.
|
||||
/// @param axis Axis on which to blur.
|
||||
/// @return (XYZ: Blurred Normals, W: Sharp Depth).
|
||||
half4 aBlurAxis(
|
||||
v2f_img IN,
|
||||
float2 axis)
|
||||
{
|
||||
// Gaussian Blur.
|
||||
half4 normalDepthM = tex2Dlod(_MainTex, float4(UnityStereoScreenSpaceUVAdjust(IN.uv, _MainTex_ST), 0.0f, 0.0f));
|
||||
float scale = _DeferredBlurredNormalsParams.x / normalDepthM.w;
|
||||
float2 finalStep = scale * axis * _MainTex_TexelSize.xy;
|
||||
half3 output = A_BLUR_WEIGHTS[0] * normalDepthM.xyz;
|
||||
|
||||
UNITY_UNROLL
|
||||
for (int i = 1; i < A_NUM_BLUR_TAPS; i++) {
|
||||
float2 coord = UnityStereoScreenSpaceUVAdjust(A_BLUR_OFFSETS[i] * finalStep + IN.uv, _MainTex_ST);
|
||||
half4 normalDepth = tex2Dlod(_MainTex, float4(coord, 0.0f, 0.0f));
|
||||
|
||||
// Lerp back to middle sample when blur sample crosses an edge.
|
||||
output += A_BLUR_WEIGHTS[i] * aEdgeCorrectNormal(normalDepth, normalDepthM);
|
||||
}
|
||||
|
||||
// Transfer original depth for subsequent passes.
|
||||
return half4(output, normalDepthM.w);
|
||||
}
|
||||
|
||||
/// Upsamples the blurred normals.
|
||||
/// @param IN Vertex input.
|
||||
/// @return Upsampled, packed blurred normals.
|
||||
half4 aUpsample(
|
||||
v2f_img IN)
|
||||
{
|
||||
// Cross Bilateral Upsample filter.
|
||||
half4 normalDepthM;
|
||||
half4 output = 0.0h;
|
||||
float4 sampleUv = float4(UnityStereoScreenSpaceUVAdjust(IN.uv, _MainTex_ST), 0.0f, 0.0f);
|
||||
|
||||
normalDepthM.xyz = tex2Dlod(_CameraGBufferTexture2, sampleUv).xyz * 2.0f - 1.0f;
|
||||
normalDepthM.w = LinearEyeDepth(SAMPLE_DEPTH_TEXTURE_LOD(_CameraDepthTexture, sampleUv));
|
||||
|
||||
UNITY_UNROLL
|
||||
for (int i = 0; i < A_NUM_UPSAMPLE_TAPS; i++) {
|
||||
float2 coord = UnityStereoScreenSpaceUVAdjust(A_UPSAMPLE_OFFSETS[i] * _MainTex_TexelSize.xy + IN.uv, _MainTex_ST);
|
||||
half4 normalDepth = tex2Dlod(_MainTex, float4(coord, 0.0f, 0.0f));
|
||||
|
||||
output.xyz += 0.25h * aEdgeCorrectNormal(normalDepth, normalDepthM);
|
||||
}
|
||||
|
||||
// Pack normals and transmission for RGBA8 storage.
|
||||
output.xyz = normalize(output.xyz) * 0.5h + 0.5h;
|
||||
output.w = tex2Dlod(_DeferredTransmissionBuffer, sampleUv).a;
|
||||
return output;
|
||||
}
|
||||
ENDCG
|
||||
|
||||
Pass {
|
||||
CGPROGRAM
|
||||
#pragma target 3.0
|
||||
#pragma exclude_renderers gles
|
||||
#pragma vertex vert_img
|
||||
#pragma fragment frag
|
||||
|
||||
half4 frag(v2f_img IN) : SV_Target {
|
||||
return aDownsample(IN);
|
||||
}
|
||||
ENDCG
|
||||
}
|
||||
|
||||
Pass {
|
||||
CGPROGRAM
|
||||
#pragma target 3.0
|
||||
#pragma exclude_renderers gles
|
||||
#pragma vertex vert_img
|
||||
#pragma fragment frag
|
||||
|
||||
half4 frag(v2f_img IN) : SV_Target {
|
||||
return aBlurAxis(IN, float2(1.0f, 0.0f));
|
||||
}
|
||||
ENDCG
|
||||
}
|
||||
|
||||
Pass {
|
||||
CGPROGRAM
|
||||
#pragma target 3.0
|
||||
#pragma exclude_renderers gles
|
||||
#pragma vertex vert_img
|
||||
#pragma fragment frag
|
||||
|
||||
half4 frag(v2f_img IN) : SV_Target {
|
||||
return aBlurAxis(IN, float2(0.0f, 1.0f));
|
||||
}
|
||||
ENDCG
|
||||
}
|
||||
|
||||
Pass {
|
||||
CGPROGRAM
|
||||
#pragma target 3.0
|
||||
#pragma exclude_renderers gles
|
||||
#pragma vertex vert_img
|
||||
#pragma fragment frag
|
||||
|
||||
half4 frag(v2f_img IN) : SV_Target {
|
||||
return aUpsample(IN);
|
||||
}
|
||||
ENDCG
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 5b34ef975c671984fb9c93adc7042982
|
||||
timeCreated: 1439655606
|
||||
licenseType: Pro
|
||||
ShaderImporter:
|
||||
defaultTextures: []
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,33 @@
|
||||
// Alloy Physical Shader Framework
|
||||
// Copyright 2013-2017 RUST LLC.
|
||||
// http://www.alloy.rustltd.com/
|
||||
|
||||
Shader "Hidden/Alloy/Transmission Blit" {
|
||||
Properties {
|
||||
_MainTex ("Render Input", 2D) = "white" {}
|
||||
}
|
||||
SubShader {
|
||||
ZTest Always
|
||||
Cull Off
|
||||
ZWrite Off
|
||||
Fog { Mode Off }
|
||||
|
||||
Pass {
|
||||
CGPROGRAM
|
||||
#pragma target 3.0
|
||||
#pragma exclude_renderers gles
|
||||
#pragma vertex vert_img
|
||||
#pragma fragment frag
|
||||
|
||||
#include "UnityCG.cginc"
|
||||
|
||||
sampler2D _MainTex;
|
||||
float4 _MainTex_ST;
|
||||
|
||||
float4 frag(v2f_img IN) : SV_Target {
|
||||
return tex2Dlod(_MainTex, float4(UnityStereoScreenSpaceUVAdjust(IN.uv, _MainTex_ST), 0.0f, 0.0f));
|
||||
}
|
||||
ENDCG
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 4bbeef29a84b4ed498f2d4a7d9fcefc4
|
||||
timeCreated: 1439605218
|
||||
licenseType: Pro
|
||||
ShaderImporter:
|
||||
defaultTextures: []
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,6 @@
|
||||
fileFormatVersion: 2
|
||||
guid: a09bc1e2550271c4b80f0d54972ba858
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
userData:
|
||||
assetBundleName:
|
||||
@@ -0,0 +1,5 @@
|
||||
fileFormatVersion: 2
|
||||
guid: cdcd98ae1d577384abf903171eb390e1
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
userData:
|
||||
@@ -0,0 +1,214 @@
|
||||
// Alloy Physical Shader Framework
|
||||
// Copyright 2013-2017 RUST LLC.
|
||||
// http://www.alloy.rustltd.com/
|
||||
|
||||
using UnityEngine;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Alloy;
|
||||
using UnityEditor;
|
||||
using PropType = UnityEditor.MaterialProperty.PropType;
|
||||
|
||||
static class AlloySceneDrawer {
|
||||
static Dictionary<AlloyInspectorBase, MaterialEditor> s_inspectorKeeper = new Dictionary<AlloyInspectorBase, MaterialEditor>();
|
||||
static List<AlloyInspectorBase> s_removekeys = new List<AlloyInspectorBase>();
|
||||
|
||||
static AlloySceneDrawer() {
|
||||
EditorApplication.update += Update;
|
||||
}
|
||||
|
||||
static void Update() {
|
||||
var keys = s_inspectorKeeper.Keys;
|
||||
s_removekeys.Clear();
|
||||
|
||||
foreach (var key in keys) {
|
||||
if (s_inspectorKeeper[key] != null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
key.OnAlloyShaderDisable();
|
||||
s_removekeys.Add(key);
|
||||
}
|
||||
|
||||
foreach (var key in s_removekeys) {
|
||||
s_inspectorKeeper.Remove(key);
|
||||
}
|
||||
}
|
||||
|
||||
public static void Register(AlloyInspectorBase inspector, MaterialEditor keeper) {
|
||||
if (!s_inspectorKeeper.ContainsKey(inspector)) {
|
||||
s_inspectorKeeper.Add(inspector, keeper);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class AlloyInspectorBase : ShaderGUI {
|
||||
public MaterialEditor MatEditor;
|
||||
protected AlloyTabGroup TabGroup;
|
||||
|
||||
public Object[] Targets { get { return MatEditor.targets; } }
|
||||
public Material Target { get { return (Material) MatEditor.target; } }
|
||||
|
||||
bool m_inited;
|
||||
bool m_isValid = true;
|
||||
|
||||
protected int MatInst {
|
||||
get {
|
||||
if (Selection.objects.Length == 1 && Selection.activeGameObject != null) {
|
||||
var sharedMaterials = Selection.activeGameObject.GetComponent<Renderer>().sharedMaterials;
|
||||
|
||||
if (sharedMaterials != null) {
|
||||
return ArrayUtility.IndexOf(sharedMaterials, Target);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
void OnEnable(MaterialProperty[] properties) {
|
||||
if (HasMutlipleShaders()) {
|
||||
return;
|
||||
}
|
||||
|
||||
TabGroup = AlloyTabGroup.GetTabGroup();
|
||||
|
||||
if (Targets.Length > 1) {
|
||||
if (MaterialsAreMismatched()) {
|
||||
foreach (var target in Targets) {
|
||||
var so = new SerializedObject(target);
|
||||
so.Update();
|
||||
|
||||
|
||||
var textures = so.FindProperty("m_SavedProperties.m_TexEnvs");
|
||||
ClearMaterialArray(PropType.Texture, textures, properties);
|
||||
|
||||
var floats = so.FindProperty("m_SavedProperties.m_Floats");
|
||||
ClearMaterialArray(PropType.Float, floats, properties);
|
||||
|
||||
var colors = so.FindProperty("m_SavedProperties.m_Colors");
|
||||
ClearMaterialArray(PropType.Color, colors, properties);
|
||||
so.ApplyModifiedProperties();
|
||||
so.Dispose();
|
||||
}
|
||||
|
||||
m_isValid = false;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
SceneView.onSceneGUIDelegate += OnAlloySceneGUI;
|
||||
OnAlloyShaderEnable();
|
||||
}
|
||||
|
||||
bool HasMutlipleShaders() {
|
||||
if (MatEditor.targets.Length > 1) {
|
||||
|
||||
return Targets.Any(o => {
|
||||
var objMat = o as Material;
|
||||
return objMat != null && (Target != null && objMat.shader != Target.shader);
|
||||
});
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
protected virtual void OnAlloyShaderGUI(MaterialProperty[] properties) {
|
||||
}
|
||||
|
||||
protected virtual void OnAlloyShaderEnable() {
|
||||
}
|
||||
|
||||
public virtual void OnAlloySceneGUI(SceneView sceneView) {
|
||||
}
|
||||
|
||||
|
||||
void ClearMaterialArray(PropType type, SerializedProperty props, MaterialProperty[] properties) {
|
||||
for (int i = 0; i < props.arraySize; ++i) {
|
||||
var prop = props.GetArrayElementAtIndex(i);
|
||||
var nameProp = prop.FindPropertyRelative("first");
|
||||
string propName = nameProp.stringValue;
|
||||
|
||||
MaterialProperty matProp = FindProperty(propName, properties, false);
|
||||
|
||||
if (matProp == null || matProp.type != type) {
|
||||
props.DeleteArrayElementAtIndex(i);
|
||||
--i;
|
||||
}
|
||||
}
|
||||
|
||||
MatEditor.OnEnable();
|
||||
}
|
||||
|
||||
bool MaterialsAreMismatched() {
|
||||
var textures = MatEditor.serializedObject.FindProperty("m_SavedProperties.m_TexEnvs");
|
||||
if (PropsInArrayMismatched(textures)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
var floats = MatEditor.serializedObject.FindProperty("m_SavedProperties.m_Floats");
|
||||
if (PropsInArrayMismatched(floats)) {
|
||||
return true;
|
||||
}
|
||||
var colors = MatEditor.serializedObject.FindProperty("m_SavedProperties.m_Colors");
|
||||
if (PropsInArrayMismatched(colors)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool PropsInArrayMismatched(SerializedProperty props) {
|
||||
string original = props.propertyPath;
|
||||
props.Next(true);
|
||||
props.Next(true);
|
||||
props.Next(true);
|
||||
|
||||
//some weird unity behaviour where it collapses the array
|
||||
if (!props.propertyPath.Contains(original)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
do {
|
||||
var nameProp = props.FindPropertyRelative("first");
|
||||
|
||||
if (nameProp.hasMultipleDifferentValues) {
|
||||
return true;
|
||||
}
|
||||
} while (props.NextVisible(false) && props.propertyPath.Contains(original));
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public override void OnGUI(MaterialEditor materialEditor, MaterialProperty[] properties) {
|
||||
MatEditor = materialEditor;
|
||||
m_isValid = true;
|
||||
|
||||
if (!m_inited) {
|
||||
AlloySceneDrawer.Register(this, MatEditor);
|
||||
OnEnable(properties);
|
||||
}
|
||||
|
||||
if (!m_isValid) {
|
||||
EditorGUILayout.LabelField("There's a problem with the inspector. Reselect the material to fix");
|
||||
EditorApplication.delayCall += () => MatEditor.Repaint();
|
||||
return;
|
||||
}
|
||||
|
||||
if (HasMutlipleShaders()) {
|
||||
EditorGUILayout.HelpBox("Can't edit materials with different shaders!", MessageType.Warning);
|
||||
return;
|
||||
}
|
||||
|
||||
GUILayout.Space(10.0f);
|
||||
if (MatEditor.isVisible) {
|
||||
OnAlloyShaderGUI(properties);
|
||||
}
|
||||
|
||||
m_inited = true;
|
||||
}
|
||||
|
||||
public virtual void OnAlloyShaderDisable() {
|
||||
SceneView.onSceneGUIDelegate -= OnAlloySceneGUI;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b14f7264c7490be4e9efc64c33c313aa
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
@@ -0,0 +1,162 @@
|
||||
// Alloy Physical Shader Framework
|
||||
// Copyright 2013-2017 RUST LLC.
|
||||
// http://www.alloy.rustltd.com/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using UnityEditor;
|
||||
|
||||
namespace Alloy
|
||||
{
|
||||
[Serializable]
|
||||
public class AlloyTabGroup : ScriptableObject
|
||||
{
|
||||
[SerializeField] private List<bool> m_open;
|
||||
[SerializeField] private List<string> m_names;
|
||||
private Action<Rect> m_defaultTabFunction = (r) => GUI.Label(r, "-", EditorStyles.whiteLabel);
|
||||
|
||||
|
||||
|
||||
public static AlloyTabGroup GetTabGroup() {
|
||||
var o = Resources.FindObjectsOfTypeAll<AlloyTabGroup>();
|
||||
AlloyTabGroup tab;
|
||||
|
||||
if (o.Length != 0) {
|
||||
tab = o[0];
|
||||
} else {
|
||||
tab = CreateInstance<AlloyTabGroup>();
|
||||
tab.hideFlags = HideFlags.HideAndDontSave;
|
||||
tab.name = "AlloyTabGroup";
|
||||
}
|
||||
|
||||
return tab;
|
||||
}
|
||||
|
||||
private void OnEnable() {
|
||||
if (m_open != null && m_names != null) return;
|
||||
|
||||
m_open = new List<bool>();
|
||||
m_names = new List<string>();
|
||||
}
|
||||
|
||||
private int DeclOpen(string nameDecl) {
|
||||
string actual = nameDecl + GUI.depth;
|
||||
|
||||
if (!m_names.Contains(actual)) {
|
||||
m_open.Add(false);
|
||||
m_names.Add(actual);
|
||||
}
|
||||
|
||||
return m_names.IndexOf(actual);
|
||||
}
|
||||
|
||||
public bool TabArea(string areaName, Color color, bool hasOptionalGui, out bool removed, string saveAs = "") {
|
||||
return TabArea(areaName, color, hasOptionalGui, m_defaultTabFunction, out removed, saveAs);
|
||||
}
|
||||
|
||||
public bool TabArea(string areaName, Color color, bool hasOptionalGui, Action<Rect> optionalGUI, out bool removed, string saveAs = "")
|
||||
{
|
||||
if (saveAs == "") {
|
||||
saveAs = areaName;
|
||||
}
|
||||
|
||||
Color oldGuiColor = GUI.color;
|
||||
Color oldBackgroundColor = GUI.backgroundColor;
|
||||
|
||||
GUI.color = Color.Lerp(color, Color.white, 0.8f);
|
||||
GUI.backgroundColor = color;
|
||||
|
||||
bool ret = TabArea(areaName, hasOptionalGui, optionalGUI, out removed, saveAs);
|
||||
GUI.color = oldGuiColor;
|
||||
GUI.backgroundColor = oldBackgroundColor;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
public bool TabArea(string areaName, bool hasOptionalGui, out bool removed, string saveAs = "") {
|
||||
return TabArea(areaName, hasOptionalGui, m_defaultTabFunction, out removed, saveAs);
|
||||
}
|
||||
|
||||
public bool TabArea(string areaName, bool hasOptionalGui, Action<Rect> optionalGUI, out bool removed, string saveAs = "")
|
||||
{
|
||||
if (saveAs == "") {
|
||||
saveAs = areaName;
|
||||
}
|
||||
|
||||
int i = DeclOpen(saveAs);
|
||||
var tabTextColor = EditorGUIUtility.isProSkin ? new Color(0.7f, 0.7f, 0.7f) : new Color(0.9f, 0.9f, 0.9f);
|
||||
var oldCol = GUI.color;
|
||||
GUI.color = oldCol * (m_open[i] ? Color.white : new Color(0.8f, 0.8f, 0.8f));
|
||||
|
||||
GUILayout.Label("");
|
||||
|
||||
var rect = GUILayoutUtility.GetLastRect();
|
||||
rect.x -= 35.0f;
|
||||
rect.width += hasOptionalGui ? 10.0f : 50.0f;
|
||||
|
||||
m_open[i] = GUI.Toggle(rect, m_open[i], new GUIContent(""), "ShurikenModuleTitle");
|
||||
removed = false;
|
||||
|
||||
if (hasOptionalGui)
|
||||
{
|
||||
var delRect = rect;
|
||||
delRect.xMin = rect.xMax;
|
||||
delRect.xMax += 40.0f;
|
||||
|
||||
GUI.color = oldCol * (m_open[i] ? new Color(0.7f, 0.7f, 0.7f) : new Color(0.5f, 0.5f, 0.5f));
|
||||
|
||||
if (GUI.Button(delRect, "", "ShurikenModuleTitle")) {
|
||||
removed = true;
|
||||
}
|
||||
|
||||
GUI.color = tabTextColor;
|
||||
GUI.backgroundColor = Color.white;
|
||||
delRect.x += 10.0f;
|
||||
optionalGUI(delRect);
|
||||
}
|
||||
|
||||
rect.x += 35.0f;
|
||||
GUI.color = tabTextColor;
|
||||
GUI.Label(rect, areaName, EditorStyles.whiteLabel);
|
||||
GUI.color = oldCol;
|
||||
|
||||
if (GUI.changed) {
|
||||
EditorUtility.SetDirty(this);
|
||||
}
|
||||
|
||||
return m_open[i];
|
||||
}
|
||||
|
||||
public bool Foldout(string areaName, string saveName, params GUILayoutOption[] options) {
|
||||
int i = DeclOpen(saveName);
|
||||
|
||||
EditorGUILayout.BeginHorizontal();
|
||||
m_open[i] = EditorGUILayout.Toggle(new GUIContent(""), m_open[i], "foldout", options);
|
||||
|
||||
if (areaName != "")
|
||||
EditorGUILayout.LabelField(new GUIContent(areaName), GUILayout.ExpandWidth(false), GUILayout.Width(180.0f));
|
||||
EditorGUILayout.EndHorizontal();
|
||||
|
||||
if (GUI.changed)
|
||||
EditorUtility.SetDirty(this);
|
||||
|
||||
return m_open[i];
|
||||
}
|
||||
|
||||
public bool IsOpen(string areaName) {
|
||||
int i = DeclOpen(areaName);
|
||||
return m_open[i];
|
||||
}
|
||||
|
||||
public void SetOpen(string areaName, bool open) {
|
||||
int i = DeclOpen(areaName);
|
||||
m_open[i] = open;
|
||||
}
|
||||
|
||||
public void Close(string areaName) {
|
||||
int i = DeclOpen(areaName);
|
||||
m_open[i] = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 700e2ca720a367c41877be522b433566
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
@@ -0,0 +1,6 @@
|
||||
fileFormatVersion: 2
|
||||
guid: dadbee4584b61ec4792a816f7dfe5061
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
userData:
|
||||
assetBundleName:
|
||||
@@ -0,0 +1,167 @@
|
||||
// Alloy Physical Shader Framework
|
||||
// Copyright 2013-2017 RUST LLC.
|
||||
// http://www.alloy.rustltd.com/
|
||||
|
||||
using UnityEngine;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using UnityEditor;
|
||||
using UnityEditor.AnimatedValues;
|
||||
|
||||
[CanEditMultipleObjects]
|
||||
public class AlloyFieldBasedEditor : AlloyInspectorBase {
|
||||
Dictionary<string, AnimBool> m_openCloseAnim = new Dictionary<string, AnimBool>();
|
||||
AlloyFieldDrawer[] m_fieldDrawers;
|
||||
|
||||
string[] m_allTabs;
|
||||
|
||||
public bool TabIsEnabled(MaterialProperty prop) {
|
||||
return !prop.hasMixedValue && prop.floatValue > 0.5f;
|
||||
}
|
||||
|
||||
public void EnableTab(string tab, MaterialProperty prop, int matInst) {
|
||||
m_openCloseAnim[prop.name].value = false;
|
||||
TabGroup.SetOpen(tab + matInst, true);
|
||||
|
||||
prop.floatValue = 1.0f;
|
||||
MaterialEditor.ApplyMaterialPropertyDrawers(Targets);
|
||||
RepaintScene();
|
||||
}
|
||||
|
||||
public void DisableTab(string tab, MaterialProperty prop, int matInst) {
|
||||
prop.floatValue = 0.0f;
|
||||
MaterialEditor.ApplyMaterialPropertyDrawers(Targets);
|
||||
RepaintScene();
|
||||
|
||||
m_openCloseAnim[prop.name].target = false;
|
||||
TabGroup.SetOpen(tab + matInst, false);
|
||||
}
|
||||
|
||||
protected override void OnAlloyShaderEnable() {
|
||||
Undo.undoRedoPerformed += OnUndo;
|
||||
}
|
||||
|
||||
public override void OnAlloyShaderDisable() {
|
||||
base.OnAlloyShaderDisable();
|
||||
|
||||
if (m_fieldDrawers != null) {
|
||||
foreach (var drawer in m_fieldDrawers) {
|
||||
if (drawer != null) {
|
||||
drawer.OnDisable();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void OnUndo() {
|
||||
MatEditor.Repaint();
|
||||
}
|
||||
|
||||
static HashSet<string> s_knownNulls = new HashSet<string>();
|
||||
|
||||
protected override void OnAlloyShaderGUI(MaterialProperty[] properties) {
|
||||
//Refresh drawer structure if needed
|
||||
bool structuralChange = false;
|
||||
if (m_fieldDrawers == null || m_fieldDrawers.Length != properties.Length) {
|
||||
m_fieldDrawers = new AlloyFieldDrawer[properties.Length];
|
||||
structuralChange = true;
|
||||
}
|
||||
|
||||
for (int i = 0; i < properties.Length; ++i) {
|
||||
string propName = properties[i].name;
|
||||
|
||||
if (m_fieldDrawers[i] == null && !s_knownNulls.Contains(propName) || m_fieldDrawers[i] != null && m_fieldDrawers[i].Property.name != propName) {
|
||||
m_fieldDrawers[i] = AlloyFieldDrawerFactory.GetFieldDrawer(this, properties[i]);
|
||||
|
||||
if (m_fieldDrawers[i] == null) {
|
||||
s_knownNulls.Add(propName);
|
||||
}
|
||||
else {
|
||||
structuralChange = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//If changed, update the animation stuff
|
||||
if (structuralChange) {
|
||||
m_openCloseAnim.Clear();
|
||||
var allTabs = new List<string>();
|
||||
|
||||
for (var i = 0; i < m_fieldDrawers.Length; i++) {
|
||||
var drawer = m_fieldDrawers[i];
|
||||
|
||||
if (!(drawer is AlloyTabDrawer)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
bool isOpenCur = TabGroup.IsOpen(drawer.DisplayName + MatInst);
|
||||
|
||||
var anim = new AnimBool(isOpenCur) {speed = 6.0f, value = isOpenCur};
|
||||
m_openCloseAnim.Add(properties[i].name, anim);
|
||||
allTabs.Add(drawer.DisplayName);
|
||||
}
|
||||
|
||||
m_allTabs = allTabs.ToArray();
|
||||
}
|
||||
|
||||
|
||||
//Formulate arguments to pass to drawing
|
||||
var args = new AlloyFieldDrawerArgs {
|
||||
Editor = this,
|
||||
Materials = Targets.Cast<Material>().ToArray(),
|
||||
Properties = properties,
|
||||
PropertiesSkip = new List<string>(),
|
||||
MatInst = MatInst,
|
||||
TabGroup = TabGroup,
|
||||
AllTabNames = m_allTabs,
|
||||
OpenCloseAnim = m_openCloseAnim
|
||||
};
|
||||
|
||||
|
||||
for (var i = 0; i < m_fieldDrawers.Length; i++) {
|
||||
var drawer = m_fieldDrawers[i];
|
||||
|
||||
if (drawer == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
drawer.Index = i;
|
||||
drawer.Property = properties[i];
|
||||
|
||||
if (drawer.ShouldDraw(args)) {
|
||||
drawer.Draw(args);
|
||||
}
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(args.CurrentTab)) {
|
||||
EditorGUILayout.EndFadeGroup();
|
||||
}
|
||||
|
||||
GUILayout.Space(10.0f);
|
||||
|
||||
AlloyEditor.DrawAddTabGUI(args.TabsToAdd);
|
||||
|
||||
//If animating -> Repaint
|
||||
foreach (var animBool in m_openCloseAnim) {
|
||||
if (animBool.Value.isAnimating) {
|
||||
MatEditor.Repaint();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override void OnAlloySceneGUI(SceneView sceneView) {
|
||||
foreach (var drawer in m_fieldDrawers) {
|
||||
if (drawer != null) {
|
||||
drawer.OnSceneGUI(Targets.Cast<Material>().ToArray());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void RepaintScene() {
|
||||
var lastSceneView = SceneView.lastActiveSceneView;
|
||||
|
||||
if (lastSceneView != null)
|
||||
lastSceneView.Repaint();
|
||||
}
|
||||
}
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
fileFormatVersion: 2
|
||||
guid: a42f0f341bef6df4c8093abde9d7e4f3
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
@@ -0,0 +1,327 @@
|
||||
// Alloy Physical Shader Framework
|
||||
// Copyright 2013-2017 RUST LLC.
|
||||
// http://www.alloy.rustltd.com/
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using UnityEngine;
|
||||
|
||||
public abstract class AlloyToken
|
||||
{
|
||||
public string Token;
|
||||
|
||||
protected AlloyToken(string field, AlloyFieldLexer currentLexer) {
|
||||
Token = field;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public class AlloyCollectionToken : AlloyToken
|
||||
{
|
||||
public List<AlloyToken> SubTokens;
|
||||
|
||||
public const char CollectionOpen = '{';
|
||||
public const char CollectionClose = '}';
|
||||
|
||||
public AlloyCollectionToken(string field, AlloyFieldLexer currentLexer)
|
||||
: base(field, currentLexer) {
|
||||
|
||||
|
||||
SubTokens = currentLexer.GenerateTokens(field);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public class AlloyArgumentToken : AlloyToken
|
||||
{
|
||||
public const char ArgumentChar = ':';
|
||||
|
||||
public string ArgumentName;
|
||||
public AlloyToken ArgumentToken;
|
||||
|
||||
public AlloyArgumentToken(string field, AlloyFieldLexer currentLexer)
|
||||
: base(field, currentLexer) {
|
||||
int index = field.IndexOf(':');
|
||||
ArgumentName = field.Substring(0, index);
|
||||
string valueStr = field.Substring(index + 1);
|
||||
|
||||
|
||||
int outInd;
|
||||
ArgumentToken = currentLexer.GenerateToken(valueStr, 0, out outInd);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public class AlloyValueToken : AlloyToken
|
||||
{
|
||||
private const string c_true = "True";
|
||||
private const string c_false = "False";
|
||||
|
||||
public enum ValueTypeEnum
|
||||
{
|
||||
Bool,
|
||||
Float,
|
||||
String
|
||||
}
|
||||
|
||||
|
||||
public ValueTypeEnum ValueType { get; private set; }
|
||||
private bool m_boolValue;
|
||||
private float m_floatValue;
|
||||
private string m_stringValue;
|
||||
|
||||
|
||||
public bool BoolValue {
|
||||
get {
|
||||
ExpectType(ValueTypeEnum.Bool);
|
||||
return m_boolValue;
|
||||
}
|
||||
}
|
||||
|
||||
public float FloatValue {
|
||||
get {
|
||||
ExpectType(ValueTypeEnum.Float);
|
||||
return m_floatValue;
|
||||
}
|
||||
}
|
||||
|
||||
public string StringValue {
|
||||
get {
|
||||
ExpectType(ValueTypeEnum.String);
|
||||
return m_stringValue;
|
||||
}
|
||||
}
|
||||
|
||||
private void ExpectType(ValueTypeEnum type) {
|
||||
if (ValueType != type) {
|
||||
Debug.LogError("Cant read " + type + " value from token!");
|
||||
}
|
||||
}
|
||||
|
||||
public AlloyValueToken(string field, AlloyFieldLexer currentLexer)
|
||||
: base(field, currentLexer) {
|
||||
|
||||
if (field == c_true) {
|
||||
ValueType = ValueTypeEnum.Bool;
|
||||
m_boolValue = true;
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
if (field == c_false) {
|
||||
ValueType = ValueTypeEnum.Bool;
|
||||
m_boolValue = false;
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
||||
float val;
|
||||
if (float.TryParse(field, out val)) {
|
||||
ValueType = ValueTypeEnum.Float;
|
||||
m_floatValue = val;
|
||||
return;
|
||||
}
|
||||
|
||||
ValueType = ValueTypeEnum.String;
|
||||
m_stringValue = field;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//The language defines a few concepts
|
||||
|
||||
//A pure token will be intepreted as a value
|
||||
//MyString -> string value MyString
|
||||
//True -> bool True
|
||||
//1.03 -> float 1.03
|
||||
|
||||
|
||||
//A collection token defines a set of tokens
|
||||
//{1.03f True True {}}
|
||||
|
||||
//A argument token defines a name and an associated token
|
||||
//CollectionArgument:{True, False}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
public class AlloyFieldLexer
|
||||
{
|
||||
private AlloyToken[] m_tokens;
|
||||
private static char[] s_specialChars = { '.', ':', '_'};
|
||||
|
||||
|
||||
public List<AlloyToken> GenerateTokens(string parseString) {
|
||||
|
||||
|
||||
var ret = new List<AlloyToken>();
|
||||
int index = 0;
|
||||
|
||||
while (index != -1) {
|
||||
var token = GenerateToken(parseString, index, out index);
|
||||
|
||||
if (token == null) {
|
||||
break;
|
||||
}
|
||||
|
||||
ret.Add(token);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
public AlloyToken GenerateToken(string parseString, int startIndex, out int index) {
|
||||
parseString = PreprocessString(parseString);
|
||||
|
||||
for (int i = startIndex; i < parseString.Length; ++i) {
|
||||
char c = parseString[i];
|
||||
|
||||
if (c == ' ') {
|
||||
continue;
|
||||
}
|
||||
|
||||
string token;
|
||||
|
||||
switch (c) {
|
||||
case AlloyCollectionToken.CollectionOpen:
|
||||
token = ReadStackedUntil(parseString, i, AlloyCollectionToken.CollectionOpen, AlloyCollectionToken.CollectionClose);
|
||||
index = i + token.Length + 1;
|
||||
return new AlloyCollectionToken(token, this);
|
||||
}
|
||||
|
||||
bool charOpen = c == '\'';
|
||||
|
||||
if (char.IsLetterOrDigit(c) || charOpen || s_specialChars.Contains(c)) {
|
||||
bool argument;
|
||||
token = ReadWord(parseString, i, out argument);
|
||||
index = i + token.Length + 1;
|
||||
|
||||
if (charOpen) {
|
||||
++index;
|
||||
}
|
||||
|
||||
if (argument) {
|
||||
return new AlloyArgumentToken(token, this);
|
||||
}
|
||||
|
||||
return new AlloyValueToken(token, this);
|
||||
}
|
||||
}
|
||||
|
||||
index = -1;
|
||||
return null;
|
||||
}
|
||||
|
||||
private string PreprocessString(string parseString) {
|
||||
return parseString.Replace(',', ' ');
|
||||
}
|
||||
|
||||
protected string ReadStackedUntil(string parseString, int index, char openC, char closeC) {
|
||||
bool found = false;
|
||||
int stack = 0;
|
||||
int readIndex;
|
||||
|
||||
for (readIndex = index; readIndex < parseString.Length; ++readIndex) {
|
||||
char c = parseString[readIndex];
|
||||
|
||||
if (c == openC) {
|
||||
++stack;
|
||||
}
|
||||
else if (c == closeC) {
|
||||
--stack;
|
||||
}
|
||||
|
||||
|
||||
if (stack == 0) {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!found) {
|
||||
Debug.LogError("Parsing fail. Could not find closing char" + closeC);
|
||||
Debug.Log(parseString);
|
||||
return null;
|
||||
}
|
||||
|
||||
return parseString.Substring(index + 1, readIndex - index);
|
||||
}
|
||||
|
||||
private string ReadWord(string parseString, int index, out bool isArgument) {
|
||||
int readIndex = index;
|
||||
bool found = false;
|
||||
int stack = 0;
|
||||
|
||||
bool inString = parseString[index] == '\'';
|
||||
|
||||
if (inString) {
|
||||
++index;
|
||||
}
|
||||
|
||||
isArgument = false;
|
||||
|
||||
|
||||
for (int i = index; i < parseString.Length; ++i) {
|
||||
char curChar = parseString[i];
|
||||
|
||||
readIndex = i;
|
||||
|
||||
|
||||
if (curChar == ':') {
|
||||
isArgument = true;
|
||||
}
|
||||
|
||||
if (!inString) {
|
||||
if (char.IsLetterOrDigit(curChar) || s_specialChars.Contains(curChar)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (curChar == AlloyCollectionToken.CollectionOpen) {
|
||||
++stack;
|
||||
continue;
|
||||
}
|
||||
|
||||
if ((curChar == AlloyCollectionToken.CollectionClose) && stack != 0) {
|
||||
--stack;
|
||||
|
||||
if (stack == 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (stack != 0) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (curChar != '\'') {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
|
||||
if (!found) {
|
||||
readIndex++;
|
||||
}
|
||||
|
||||
string ret = parseString.Substring(index, readIndex - index);
|
||||
|
||||
|
||||
//TODO: Handle argument:'StringToken'
|
||||
/*
|
||||
if (found) {
|
||||
|
||||
//if (readIndex < parseString.Length - 1 && parseString[readIndex + 1] == ':') {
|
||||
//ret += ReadWord(parseString, readIndex + 2);
|
||||
//}
|
||||
}
|
||||
*/
|
||||
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 52de48504b3bb25439b7013a009de5e9
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
@@ -0,0 +1,156 @@
|
||||
// Alloy Physical Shader Framework
|
||||
// Copyright 2013-2017 RUST LLC.
|
||||
// http://www.alloy.rustltd.com/
|
||||
|
||||
using UnityEditor.AnimatedValues;
|
||||
using UnityEngine;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Alloy;
|
||||
using UnityEditor;
|
||||
|
||||
|
||||
//Generates drawers for a certain field
|
||||
public abstract class AlloyFieldParser {
|
||||
protected List<AlloyToken> Tokens;
|
||||
|
||||
public bool HasSettings;
|
||||
public string DisplayName;
|
||||
|
||||
protected MaterialProperty MaterialProperty;
|
||||
protected AlloyArgumentToken[] Arguments;
|
||||
|
||||
protected AlloyFieldParser(MaterialProperty prop) {
|
||||
var lexer = new AlloyFieldLexer();
|
||||
Tokens = lexer.GenerateTokens(prop.displayName);
|
||||
|
||||
if (Tokens.Count == 0) {
|
||||
Debug.LogError("No tokens found!");
|
||||
return;
|
||||
}
|
||||
|
||||
MaterialProperty = prop;
|
||||
DisplayName = Tokens[0].Token;
|
||||
|
||||
if (Tokens.Count <= 1) {
|
||||
return;
|
||||
}
|
||||
|
||||
var settingsToken = Tokens[1] as AlloyCollectionToken;
|
||||
if (settingsToken == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
HasSettings = true;
|
||||
Arguments = settingsToken.SubTokens.OfType<AlloyArgumentToken>().ToArray();
|
||||
}
|
||||
|
||||
public AlloyFieldDrawer GetDrawer(AlloyInspectorBase editor) {
|
||||
if (!HasSettings) {
|
||||
return null;
|
||||
}
|
||||
|
||||
var drawer = GenerateDrawer(editor);
|
||||
if (drawer != null) {
|
||||
drawer.DisplayName = DisplayName;
|
||||
}
|
||||
|
||||
return drawer;
|
||||
}
|
||||
|
||||
protected abstract AlloyFieldDrawer GenerateDrawer(AlloyInspectorBase editor);
|
||||
}
|
||||
|
||||
public class AlloyFieldDrawerArgs {
|
||||
public AlloyFieldBasedEditor Editor;
|
||||
public AlloyTabGroup TabGroup;
|
||||
public Material[] Materials;
|
||||
public MaterialProperty[] Properties;
|
||||
public List<string> PropertiesSkip = new List<string>();
|
||||
public string CurrentTab;
|
||||
public int MatInst;
|
||||
public bool DoDraw = true;
|
||||
public List<AlloyTabAdd> TabsToAdd = new List<AlloyTabAdd>();
|
||||
public string[] AllTabNames;
|
||||
public Dictionary<string, AnimBool> OpenCloseAnim;
|
||||
|
||||
public MaterialProperty GetMaterialProperty(string velName) {
|
||||
return Properties.FirstOrDefault(p => p.name == velName);
|
||||
}
|
||||
}
|
||||
|
||||
public class AlloyTabAdd {
|
||||
public string Name;
|
||||
public Color Color;
|
||||
|
||||
public GenericMenu.MenuFunction Enable;
|
||||
}
|
||||
|
||||
public abstract class AlloyFieldDrawer {
|
||||
public MaterialProperty Property;
|
||||
public int Index;
|
||||
|
||||
public string DisplayName;
|
||||
public abstract void Draw(AlloyFieldDrawerArgs args);
|
||||
|
||||
protected MaterialEditor MatEditor;
|
||||
|
||||
protected void BeginMaterialProperty(MaterialProperty property) {
|
||||
MatEditor.BeginAnimatedCheck(Property);
|
||||
EditorGUI.BeginChangeCheck();
|
||||
EditorGUI.showMixedValue = Property.hasMixedValue;
|
||||
}
|
||||
|
||||
protected bool EndMaterialProperty() {
|
||||
bool change = EditorGUI.EndChangeCheck();
|
||||
MatEditor.EndAnimatedCheck();
|
||||
EditorGUI.showMixedValue = false;
|
||||
return change;
|
||||
}
|
||||
|
||||
public AlloyFieldDrawer(AlloyInspectorBase editor, MaterialProperty property) {
|
||||
Property = property;
|
||||
MatEditor = editor.MatEditor;
|
||||
}
|
||||
|
||||
protected void FloatFieldMin(string displayName, float min) {
|
||||
BeginMaterialProperty(Property);
|
||||
float newVal = EditorGUILayout.FloatField(displayName, Property.floatValue);
|
||||
|
||||
if (EndMaterialProperty()) {
|
||||
Property.floatValue = Mathf.Max(newVal, min);
|
||||
}
|
||||
}
|
||||
|
||||
protected void FloatFieldMax(string displayName, float max) {
|
||||
BeginMaterialProperty(Property);
|
||||
float newVal = EditorGUILayout.FloatField(displayName, Property.floatValue);
|
||||
|
||||
if (EndMaterialProperty()) {
|
||||
Property.floatValue = Mathf.Min(newVal, max);
|
||||
}
|
||||
}
|
||||
|
||||
protected void FloatFieldSlider(string displayName, float min, float max) {
|
||||
BeginMaterialProperty(Property);
|
||||
float newVal = EditorGUILayout.Slider(displayName, Property.floatValue, min, max, GUILayout.MinWidth(20.0f));
|
||||
|
||||
if (EndMaterialProperty()) {
|
||||
Property.floatValue = Mathf.Clamp(newVal, min, max);
|
||||
}
|
||||
}
|
||||
|
||||
public void PropField(string displayName) {
|
||||
MatEditor.ShaderProperty(Property, displayName);
|
||||
}
|
||||
|
||||
public virtual bool ShouldDraw(AlloyFieldDrawerArgs args) {
|
||||
return args.DoDraw && !args.PropertiesSkip.Contains(Property.name);
|
||||
}
|
||||
|
||||
public virtual void OnSceneGUI(Material[] materials) {
|
||||
}
|
||||
|
||||
public virtual void OnDisable() {
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 23f0b2f9bd608954ca3ef47baea748b7
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
@@ -0,0 +1,9 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c8a42743b4a4aee4d901f3b88bbf641f
|
||||
folderAsset: yes
|
||||
timeCreated: 1430261445
|
||||
licenseType: Pro
|
||||
DefaultImporter:
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
+46
@@ -0,0 +1,46 @@
|
||||
// Alloy Physical Shader Framework
|
||||
// Copyright 2013-2017 RUST LLC.
|
||||
// http://www.alloy.rustltd.com/
|
||||
|
||||
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
|
||||
public static class AlloyFieldDrawerFactory {
|
||||
private static AlloyFieldParser GetFieldParser(MaterialProperty prop) {
|
||||
|
||||
switch (prop.type) {
|
||||
case MaterialProperty.PropType.Texture:
|
||||
if (prop.textureDimension == UnityEngine.Rendering.TextureDimension.Cube) {
|
||||
return new AlloyCubeParser(prop);
|
||||
}
|
||||
|
||||
return new AlloyTextureParser(prop);
|
||||
|
||||
case MaterialProperty.PropType.Range:
|
||||
case MaterialProperty.PropType.Float:
|
||||
return new AlloyFloatParser(prop);
|
||||
|
||||
case MaterialProperty.PropType.Color:
|
||||
return new AlloyColorParser(prop);
|
||||
|
||||
case MaterialProperty.PropType.Vector:
|
||||
return new AlloyVectorParser(prop);
|
||||
|
||||
default:
|
||||
Debug.LogError("No appopriate parser found to generate a drawer");
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public static AlloyFieldDrawer GetFieldDrawer(AlloyInspectorBase editor, MaterialProperty prop) {
|
||||
AlloyFieldParser parser = GetFieldParser(prop);
|
||||
|
||||
if (parser != null) {
|
||||
return parser.GetDrawer(editor);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 92100f25eeaa5f14c882772983cb2592
|
||||
timeCreated: 1430261698
|
||||
licenseType: Pro
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
+189
@@ -0,0 +1,189 @@
|
||||
// Alloy Physical Shader Framework
|
||||
// Copyright 2013-2017 RUST LLC.
|
||||
// http://www.alloy.rustltd.com/
|
||||
|
||||
using System.Linq;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
|
||||
public class AlloyDefaultDrawer : AlloyFieldDrawer
|
||||
{
|
||||
public override void Draw(AlloyFieldDrawerArgs args) {
|
||||
PropField(DisplayName);
|
||||
}
|
||||
|
||||
public AlloyDefaultDrawer(AlloyInspectorBase editor, MaterialProperty property) : base(editor, property) {
|
||||
}
|
||||
}
|
||||
|
||||
public class AlloyLightmapEmissionDrawer : AlloyFieldDrawer {
|
||||
public override void Draw(AlloyFieldDrawerArgs args) {
|
||||
args.Editor.MatEditor.LightmapEmissionProperty();
|
||||
|
||||
foreach (var material in args.Materials) {
|
||||
// Setup lightmap emissive flags
|
||||
MaterialGlobalIlluminationFlags flags = material.globalIlluminationFlags;
|
||||
if ((flags & (MaterialGlobalIlluminationFlags.BakedEmissive | MaterialGlobalIlluminationFlags.RealtimeEmissive)) != 0) {
|
||||
flags &= ~MaterialGlobalIlluminationFlags.EmissiveIsBlack;
|
||||
|
||||
|
||||
material.globalIlluminationFlags = flags;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public AlloyLightmapEmissionDrawer(AlloyInspectorBase editor, MaterialProperty property) : base(editor, property) {
|
||||
}
|
||||
}
|
||||
|
||||
public class AlloyRenderQueueDrawer : AlloyFieldDrawer {
|
||||
public override void Draw(AlloyFieldDrawerArgs args) {
|
||||
args.Editor.MatEditor.RenderQueueField();
|
||||
}
|
||||
|
||||
public AlloyRenderQueueDrawer(AlloyInspectorBase editor, MaterialProperty property) : base(editor, property) {
|
||||
}
|
||||
}
|
||||
|
||||
public class AlloyEnableInstancingDrawer : AlloyFieldDrawer {
|
||||
public override void Draw(AlloyFieldDrawerArgs args) {
|
||||
args.Editor.MatEditor.EnableInstancingField();
|
||||
}
|
||||
|
||||
public AlloyEnableInstancingDrawer(AlloyInspectorBase editor, MaterialProperty property) : base(editor, property) {
|
||||
}
|
||||
}
|
||||
|
||||
public class AlloyRenderingModeDrawer : AlloyBlendModeDropdownDrawer {
|
||||
private enum RenderingMode {
|
||||
Opaque,
|
||||
Cutout,
|
||||
Fade,
|
||||
Transparent
|
||||
}
|
||||
|
||||
private static readonly BlendModeOptionConfig[] s_renderingModes = {
|
||||
new BlendModeOptionConfig() {
|
||||
Type = (int)RenderingMode.Opaque,
|
||||
OverrideTag = "",
|
||||
SrcBlend = UnityEngine.Rendering.BlendMode.One,
|
||||
DstBlend = UnityEngine.Rendering.BlendMode.Zero,
|
||||
ZWrite = 1,
|
||||
Keyword = "",
|
||||
RenderQueue = -1
|
||||
},
|
||||
new BlendModeOptionConfig() {
|
||||
Type = (int)RenderingMode.Cutout,
|
||||
OverrideTag = "TransparentCutout",
|
||||
SrcBlend = UnityEngine.Rendering.BlendMode.One,
|
||||
DstBlend = UnityEngine.Rendering.BlendMode.Zero,
|
||||
ZWrite = 1,
|
||||
Keyword = "_ALPHATEST_ON",
|
||||
RenderQueue = (int)UnityEngine.Rendering.RenderQueue.AlphaTest,
|
||||
},
|
||||
new BlendModeOptionConfig() {
|
||||
Type = (int)RenderingMode.Fade,
|
||||
OverrideTag = "Transparent",
|
||||
SrcBlend = UnityEngine.Rendering.BlendMode.SrcAlpha,
|
||||
DstBlend = UnityEngine.Rendering.BlendMode.OneMinusSrcAlpha,
|
||||
ZWrite = 0,
|
||||
Keyword = "_ALPHABLEND_ON",
|
||||
RenderQueue = (int)UnityEngine.Rendering.RenderQueue.Transparent
|
||||
},
|
||||
new BlendModeOptionConfig() {
|
||||
Type = (int)RenderingMode.Transparent,
|
||||
OverrideTag = "Transparent",
|
||||
SrcBlend = UnityEngine.Rendering.BlendMode.One,
|
||||
DstBlend = UnityEngine.Rendering.BlendMode.OneMinusSrcAlpha,
|
||||
ZWrite = 0,
|
||||
Keyword = "_ALPHAPREMULTIPLY_ON",
|
||||
RenderQueue = (int)UnityEngine.Rendering.RenderQueue.Transparent
|
||||
},
|
||||
};
|
||||
|
||||
public AlloyRenderingModeDrawer(AlloyInspectorBase editor, MaterialProperty property)
|
||||
: base(editor, property, s_renderingModes) {
|
||||
}
|
||||
}
|
||||
|
||||
public class AlloySpeedTreeGeometryTypeDrawer : AlloyBlendModeDropdownDrawer {
|
||||
private enum SpeedTreeGeometryType {
|
||||
Branch,
|
||||
BranchDetail,
|
||||
Frond,
|
||||
Leaf,
|
||||
Mesh,
|
||||
}
|
||||
|
||||
private static readonly BlendModeOptionConfig[] s_geometryTypes = {
|
||||
new BlendModeOptionConfig() {
|
||||
Type = (int)SpeedTreeGeometryType.Branch,
|
||||
OverrideTag = "",
|
||||
SrcBlend = UnityEngine.Rendering.BlendMode.One,
|
||||
DstBlend = UnityEngine.Rendering.BlendMode.Zero,
|
||||
ZWrite = 1,
|
||||
Keyword = "GEOM_TYPE_BRANCH",
|
||||
RenderQueue = -1
|
||||
},
|
||||
new BlendModeOptionConfig() {
|
||||
Type = (int)SpeedTreeGeometryType.BranchDetail,
|
||||
OverrideTag = "",
|
||||
SrcBlend = UnityEngine.Rendering.BlendMode.One,
|
||||
DstBlend = UnityEngine.Rendering.BlendMode.Zero,
|
||||
ZWrite = 1,
|
||||
Keyword = "GEOM_TYPE_BRANCH_DETAIL",
|
||||
RenderQueue = -1
|
||||
},
|
||||
new BlendModeOptionConfig() {
|
||||
Type = (int)SpeedTreeGeometryType.Frond,
|
||||
OverrideTag = "TransparentCutout",
|
||||
SrcBlend = UnityEngine.Rendering.BlendMode.One,
|
||||
DstBlend = UnityEngine.Rendering.BlendMode.Zero,
|
||||
ZWrite = 1,
|
||||
Keyword = "GEOM_TYPE_FROND",
|
||||
RenderQueue = (int)UnityEngine.Rendering.RenderQueue.AlphaTest
|
||||
},
|
||||
new BlendModeOptionConfig() {
|
||||
Type = (int)SpeedTreeGeometryType.Leaf,
|
||||
OverrideTag = "TransparentCutout",
|
||||
SrcBlend = UnityEngine.Rendering.BlendMode.One,
|
||||
DstBlend = UnityEngine.Rendering.BlendMode.Zero,
|
||||
ZWrite = 1,
|
||||
Keyword = "GEOM_TYPE_LEAF",
|
||||
RenderQueue = (int)UnityEngine.Rendering.RenderQueue.AlphaTest
|
||||
},
|
||||
new BlendModeOptionConfig() {
|
||||
Type = (int)SpeedTreeGeometryType.Mesh,
|
||||
OverrideTag = "",
|
||||
SrcBlend = UnityEngine.Rendering.BlendMode.One,
|
||||
DstBlend = UnityEngine.Rendering.BlendMode.Zero,
|
||||
ZWrite = 1,
|
||||
Keyword = "GEOM_TYPE_MESH",
|
||||
RenderQueue = -1
|
||||
},
|
||||
};
|
||||
|
||||
public AlloySpeedTreeGeometryTypeDrawer(AlloyInspectorBase editor, MaterialProperty property)
|
||||
: base(editor, property, s_geometryTypes)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
public class AlloyColorParser : AlloyFieldParser{
|
||||
protected override AlloyFieldDrawer GenerateDrawer(AlloyInspectorBase editor) {
|
||||
var ret = new AlloyColorDrawer(editor, MaterialProperty);
|
||||
return ret;
|
||||
}
|
||||
|
||||
public AlloyColorParser(MaterialProperty field) : base(field) {
|
||||
}
|
||||
}
|
||||
|
||||
public class AlloyColorDrawer : AlloyFieldDrawer {
|
||||
public override void Draw(AlloyFieldDrawerArgs args) {
|
||||
PropField(DisplayName);
|
||||
}
|
||||
|
||||
public AlloyColorDrawer(AlloyInspectorBase editor, MaterialProperty property) : base(editor, property) {
|
||||
}
|
||||
}
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
fileFormatVersion: 2
|
||||
guid: ce2d4023424d8b24e830bed4c9fb55f5
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
+511
@@ -0,0 +1,511 @@
|
||||
// Alloy Physical Shader Framework
|
||||
// Copyright 2013-2017 RUST LLC.
|
||||
// http://www.alloy.rustltd.com/
|
||||
|
||||
using System;
|
||||
using System.Text.RegularExpressions;
|
||||
using UnityEngine;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using UnityEditor;
|
||||
|
||||
public class AlloyDropdownOption {
|
||||
public string Name;
|
||||
public string[] HideFields;
|
||||
}
|
||||
|
||||
public class AlloyFloatParser : AlloyFieldParser {
|
||||
private readonly Color32 c_defaultSectionColor = new Color32(97, 97, 97, 255);
|
||||
|
||||
protected override AlloyFieldDrawer GenerateDrawer(AlloyInspectorBase editor) {
|
||||
AlloyFieldDrawer retDrawer = null;
|
||||
|
||||
foreach (var token in Arguments) {
|
||||
var argName = token.ArgumentName;
|
||||
var argToken = token.ArgumentToken;
|
||||
|
||||
switch (argName) {
|
||||
case "Min":
|
||||
AlloyFloatDrawer minDrawer = null;
|
||||
var minValToken = argToken as AlloyValueToken;
|
||||
|
||||
if (retDrawer != null)
|
||||
minDrawer = retDrawer as AlloyFloatDrawer;
|
||||
|
||||
if (minDrawer == null)
|
||||
minDrawer = new AlloyFloatDrawer(editor, MaterialProperty);
|
||||
|
||||
minDrawer.HasMin = true;
|
||||
minDrawer.MinValue = minValToken.FloatValue;
|
||||
retDrawer = minDrawer;
|
||||
break;
|
||||
|
||||
case "Max":
|
||||
AlloyFloatDrawer maxDrawer = null;
|
||||
var maxValToken = argToken as AlloyValueToken;
|
||||
|
||||
if (retDrawer != null)
|
||||
maxDrawer = retDrawer as AlloyFloatDrawer;
|
||||
|
||||
if (maxDrawer == null)
|
||||
maxDrawer = new AlloyFloatDrawer(editor, MaterialProperty);
|
||||
|
||||
maxDrawer.HasMax = true;
|
||||
maxDrawer.MaxValue = maxValToken.FloatValue;
|
||||
retDrawer = maxDrawer;
|
||||
break;
|
||||
|
||||
case "Section":
|
||||
retDrawer = new AlloySectionDrawer(editor, MaterialProperty);
|
||||
SetSectionOption(retDrawer, argToken);
|
||||
break;
|
||||
|
||||
case "Feature":
|
||||
retDrawer = new AlloyFeatureDrawer(editor, MaterialProperty);
|
||||
SetSectionOption(retDrawer, argToken);
|
||||
break;
|
||||
|
||||
case "Toggle":
|
||||
retDrawer = new AlloyToggleDrawer(editor, MaterialProperty);
|
||||
SetToggleOption(retDrawer, argToken);
|
||||
break;
|
||||
|
||||
case "SpeedTreeGeometryType":
|
||||
retDrawer = new AlloySpeedTreeGeometryTypeDrawer(editor, MaterialProperty);
|
||||
SetDropdownOption(retDrawer, argToken);
|
||||
break;
|
||||
|
||||
case "RenderingMode":
|
||||
retDrawer = new AlloyRenderingModeDrawer(editor, MaterialProperty);
|
||||
SetDropdownOption(retDrawer, argToken);
|
||||
break;
|
||||
|
||||
case "Dropdown":
|
||||
retDrawer = new AlloyDropdownDrawer(editor, MaterialProperty);
|
||||
SetDropdownOption(retDrawer, argToken);
|
||||
break;
|
||||
|
||||
case "LightmapEmissionProperty":
|
||||
retDrawer = new AlloyLightmapEmissionDrawer(editor, MaterialProperty);
|
||||
break;
|
||||
|
||||
case "RenderQueue":
|
||||
retDrawer = new AlloyRenderQueueDrawer(editor, MaterialProperty);
|
||||
break;
|
||||
|
||||
case "EnableInstancing":
|
||||
retDrawer = new AlloyEnableInstancingDrawer(editor, MaterialProperty);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (retDrawer == null)
|
||||
retDrawer = new AlloyFloatDrawer(editor, MaterialProperty);
|
||||
|
||||
return retDrawer;
|
||||
}
|
||||
|
||||
private static void SetDropdownOption(AlloyFieldDrawer retDrawer, AlloyToken argToken) {
|
||||
var drawer = retDrawer as AlloyDropdownDrawer;
|
||||
|
||||
if (drawer == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
var options = argToken as AlloyCollectionToken;
|
||||
|
||||
if (options == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
var dropOptions = new List<AlloyDropdownOption>();
|
||||
|
||||
for (int i = 0; i < options.SubTokens.Count; i++) {
|
||||
AlloyArgumentToken arg = (AlloyArgumentToken)options.SubTokens[i];
|
||||
var collection = arg.ArgumentToken as AlloyCollectionToken;
|
||||
|
||||
if (collection == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
// Split PascalCase name into words separated by spaces while skipping acronyms.
|
||||
var dropOption = new AlloyDropdownOption {
|
||||
Name = Regex.Replace(arg.ArgumentName, @"(?<=[A-Za-z])(?=[A-Z][a-z])|(?<=[a-z0-9])(?=[0-9]?[A-Z])", " "),
|
||||
HideFields = collection.SubTokens.Select(alloyToken => alloyToken.Token).ToArray()
|
||||
};
|
||||
dropOptions.Add(dropOption);
|
||||
}
|
||||
|
||||
drawer.DropOptions = dropOptions.ToArray();
|
||||
}
|
||||
|
||||
private static void SetToggleOption(AlloyFieldDrawer retDrawer, AlloyToken argToken) {
|
||||
var drawer = retDrawer as AlloyToggleDrawer;
|
||||
|
||||
if (drawer == null) {
|
||||
return;
|
||||
}
|
||||
var collectionToken = argToken as AlloyCollectionToken;
|
||||
|
||||
if (collectionToken == null) {
|
||||
return;
|
||||
}
|
||||
foreach (var token in collectionToken.SubTokens) {
|
||||
var arg = token as AlloyArgumentToken;
|
||||
|
||||
if (arg != null && arg.ArgumentName == "On") {
|
||||
var onToken = arg.ArgumentToken as AlloyCollectionToken;
|
||||
|
||||
if (onToken != null) {
|
||||
drawer.OnHideFields = onToken.SubTokens.Select(colToken => colToken.Token).ToArray();
|
||||
}
|
||||
}
|
||||
else if (arg != null && arg.ArgumentName == "Off") {
|
||||
var offToken = arg.ArgumentToken as AlloyCollectionToken;
|
||||
|
||||
if (offToken != null) {
|
||||
drawer.OffHideFields = offToken.SubTokens.Select(colToken => colToken.Token).ToArray();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void SetMinOption(AlloyFieldDrawer retDrawer, AlloyToken argToken) {
|
||||
var floatDrawer = retDrawer as AlloyFloatDrawer;
|
||||
var minValToken = argToken as AlloyValueToken;
|
||||
|
||||
if (floatDrawer != null) {
|
||||
floatDrawer.HasMin = true;
|
||||
|
||||
if (minValToken != null) {
|
||||
floatDrawer.MinValue = minValToken.FloatValue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SetSectionOption(AlloyFieldDrawer retDrawer, AlloyToken argToken) {
|
||||
var sectionDrawer = retDrawer as AlloyTabDrawer;
|
||||
|
||||
if (sectionDrawer != null) {
|
||||
var collectionToken = argToken as AlloyCollectionToken;
|
||||
|
||||
if (collectionToken == null) {
|
||||
sectionDrawer.Color = c_defaultSectionColor;
|
||||
}
|
||||
else {
|
||||
foreach (var token in collectionToken.SubTokens) {
|
||||
var arg = token as AlloyArgumentToken;
|
||||
|
||||
if (arg != null && arg.ArgumentName == "Color") {
|
||||
var value = arg.ArgumentToken as AlloyValueToken;
|
||||
|
||||
// Calculate color from section index and HSV scale factor.
|
||||
if (value != null) {
|
||||
var hueIndex = value.FloatValue;
|
||||
|
||||
if (hueIndex > -0.1f)
|
||||
sectionDrawer.Color = Color.HSVToRGB((hueIndex / AlloyUtils.SectionColorMax) * 0.6f, 0.75f, 0.5f);
|
||||
}
|
||||
else {
|
||||
// Manually specify color.
|
||||
var colCollection = arg.ArgumentToken as AlloyCollectionToken;
|
||||
|
||||
if (colCollection != null) {
|
||||
var r = colCollection.SubTokens[0] as AlloyValueToken;
|
||||
var g = colCollection.SubTokens[1] as AlloyValueToken;
|
||||
var b = colCollection.SubTokens[2] as AlloyValueToken;
|
||||
|
||||
if (r != null && g != null && b != null) {
|
||||
sectionDrawer.Color = new Color32((byte)r.FloatValue, (byte)g.FloatValue, (byte)b.FloatValue, 255);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (arg != null && arg.ArgumentName == "Hide") {
|
||||
var featureDrawer = sectionDrawer as AlloyFeatureDrawer;
|
||||
var offToken = arg.ArgumentToken as AlloyCollectionToken;
|
||||
|
||||
if (offToken != null) {
|
||||
featureDrawer.HideFields = offToken.SubTokens.Select(colToken => colToken.Token).ToArray();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public AlloyFloatParser(MaterialProperty field)
|
||||
: base(field) {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public abstract class AlloyTabDrawer : AlloyFieldDrawer
|
||||
{
|
||||
public Color Color;
|
||||
Func<bool, Action<Rect>> m_foldoutAction;
|
||||
|
||||
protected void SetAllTabsOpenedTo(bool open, AlloyFieldDrawerArgs args) {
|
||||
foreach (var tab in args.AllTabNames) {
|
||||
args.TabGroup.SetOpen(tab + args.MatInst, open);
|
||||
}
|
||||
}
|
||||
|
||||
public override bool ShouldDraw(AlloyFieldDrawerArgs args) {
|
||||
return !args.PropertiesSkip.Contains(Property.name);
|
||||
}
|
||||
|
||||
protected void DrawNow(AlloyFieldDrawerArgs args, bool optional) {
|
||||
var firstDrawer = Index == 0;
|
||||
var firstTab = string.IsNullOrEmpty(args.CurrentTab);
|
||||
|
||||
if (firstDrawer) {
|
||||
GUILayout.Space(-10.0f);
|
||||
}
|
||||
else if (firstTab) {
|
||||
GUILayout.Space(5.0f);
|
||||
}
|
||||
else {
|
||||
if (args.DoDraw) {
|
||||
GUILayout.Space(8.0f);
|
||||
}
|
||||
|
||||
EditorGUILayout.EndFadeGroup();
|
||||
}
|
||||
|
||||
if (!optional || args.Editor.TabIsEnabled(Property)) {
|
||||
bool open;
|
||||
|
||||
if (firstTab && !optional) {
|
||||
bool openAll = args.AllTabNames.All(tab => args.TabGroup.IsOpen(tab + args.MatInst));
|
||||
bool closeOpen;
|
||||
bool all = openAll;
|
||||
|
||||
open = args.TabGroup.TabArea(DisplayName, Color, true, m_foldoutAction(all), out closeOpen, DisplayName + args.MatInst);
|
||||
|
||||
if (closeOpen) {
|
||||
openAll = !openAll;
|
||||
SetAllTabsOpenedTo(openAll, args);
|
||||
}
|
||||
}
|
||||
else {
|
||||
bool removed;
|
||||
open = args.TabGroup.TabArea(DisplayName, Color, optional, out removed, DisplayName + args.MatInst);
|
||||
|
||||
if (removed) {
|
||||
args.Editor.DisableTab(DisplayName, Property, args.MatInst);
|
||||
}
|
||||
}
|
||||
|
||||
var anim = args.OpenCloseAnim[Property.name];
|
||||
anim.target = open;
|
||||
|
||||
args.CurrentTab = Property.name;
|
||||
args.DoDraw = EditorGUILayout.BeginFadeGroup(anim.faded);
|
||||
}
|
||||
else {
|
||||
args.DoDraw = false;
|
||||
|
||||
args.TabsToAdd.Add(new AlloyTabAdd { Color = Color, Name = DisplayName, Enable = () => args.Editor.EnableTab(DisplayName, Property, args.MatInst) });
|
||||
}
|
||||
}
|
||||
|
||||
protected AlloyTabDrawer(AlloyInspectorBase editor, MaterialProperty property)
|
||||
: base(editor, property) {
|
||||
m_foldoutAction = all => r => GUI.Label(r, all ? "v" : ">", EditorStyles.whiteLabel);
|
||||
}
|
||||
}
|
||||
|
||||
public class AlloySectionDrawer : AlloyTabDrawer {
|
||||
public override void Draw(AlloyFieldDrawerArgs args) {
|
||||
DrawNow(args, false);
|
||||
}
|
||||
|
||||
public AlloySectionDrawer(AlloyInspectorBase editor, MaterialProperty property) : base(editor, property) {
|
||||
}
|
||||
}
|
||||
|
||||
public class AlloyFeatureDrawer : AlloyTabDrawer {
|
||||
public string[] HideFields;
|
||||
|
||||
public override bool ShouldDraw(AlloyFieldDrawerArgs args) {
|
||||
return true;
|
||||
}
|
||||
|
||||
public override void Draw(AlloyFieldDrawerArgs args) {
|
||||
bool current = Property.floatValue > 0.5f;
|
||||
|
||||
DrawNow(args, true);
|
||||
|
||||
if (!current) {
|
||||
if (HideFields != null) {
|
||||
args.PropertiesSkip.AddRange(HideFields);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public AlloyFeatureDrawer(AlloyInspectorBase editor, MaterialProperty property) : base(editor, property) {
|
||||
}
|
||||
}
|
||||
|
||||
public class AlloyFloatDrawer : AlloyFieldDrawer
|
||||
{
|
||||
public bool HasMin;
|
||||
public float MinValue;
|
||||
|
||||
public bool HasMax;
|
||||
public float MaxValue;
|
||||
|
||||
int m_selectedIndex;
|
||||
|
||||
public override void Draw(AlloyFieldDrawerArgs args) {
|
||||
if (HasMin || HasMax) {
|
||||
if (HasMin && HasMax) {
|
||||
FloatFieldSlider(DisplayName, MinValue, MaxValue);
|
||||
}
|
||||
else if (HasMin) {
|
||||
FloatFieldMin(DisplayName, MinValue);
|
||||
}
|
||||
else {
|
||||
FloatFieldMax(DisplayName, MaxValue);
|
||||
}
|
||||
}
|
||||
else {
|
||||
PropField(DisplayName);
|
||||
}
|
||||
}
|
||||
|
||||
public AlloyFloatDrawer(AlloyInspectorBase editor, MaterialProperty property) : base(editor, property) {
|
||||
}
|
||||
}
|
||||
|
||||
public class AlloyDropdownDrawer : AlloyFieldDrawer {
|
||||
public AlloyDropdownOption[] DropOptions;
|
||||
|
||||
protected virtual bool OnSetOption(int newOption, AlloyFieldDrawerArgs args) {
|
||||
return false;
|
||||
}
|
||||
|
||||
public override void Draw(AlloyFieldDrawerArgs args) {
|
||||
int current = (int)Property.floatValue;
|
||||
var label = new GUIContent(DisplayName);
|
||||
|
||||
BeginMaterialProperty(Property);
|
||||
|
||||
int newVal = EditorGUILayout.Popup(label, current, DropOptions.Select(option => new GUIContent(option.Name)).ToArray());
|
||||
EditorGUI.showMixedValue = false;
|
||||
|
||||
if (!OnSetOption(newVal, args) && EditorGUI.EndChangeCheck()) {
|
||||
Property.floatValue = newVal;
|
||||
MaterialEditor.ApplyMaterialPropertyDrawers(args.Materials);
|
||||
}
|
||||
|
||||
MatEditor.EndAnimatedCheck();
|
||||
args.PropertiesSkip.AddRange(DropOptions[current].HideFields);
|
||||
}
|
||||
|
||||
public AlloyDropdownDrawer(AlloyInspectorBase editor, MaterialProperty property) : base(editor, property) {
|
||||
}
|
||||
}
|
||||
|
||||
public abstract class AlloyBlendModeDropdownDrawer : AlloyDropdownDrawer {
|
||||
public struct BlendModeOptionConfig {
|
||||
public int Type;
|
||||
public string OverrideTag;
|
||||
public UnityEngine.Rendering.BlendMode SrcBlend;
|
||||
public UnityEngine.Rendering.BlendMode DstBlend;
|
||||
public int ZWrite;
|
||||
public string Keyword;
|
||||
public int RenderQueue;
|
||||
}
|
||||
|
||||
protected BlendModeOptionConfig[] BlendModeOptionConfigs = null;
|
||||
|
||||
public AlloyBlendModeDropdownDrawer(AlloyInspectorBase editor, MaterialProperty property, BlendModeOptionConfig[] blendModeOptionConfigs) : base(editor, property) {
|
||||
BlendModeOptionConfigs = blendModeOptionConfigs;
|
||||
|
||||
// Get default from keyword.
|
||||
var keywords = editor.Target.shaderKeywords;
|
||||
property.floatValue = 0.0f;
|
||||
|
||||
foreach (var setting in BlendModeOptionConfigs) {
|
||||
if (keywords.Contains(setting.Keyword)) {
|
||||
property.floatValue = setting.Type;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected override bool OnSetOption(int newOption, AlloyFieldDrawerArgs args) {
|
||||
base.OnSetOption(newOption, args);
|
||||
|
||||
foreach (var material in args.Materials) {
|
||||
if (Property.floatValue != newOption) {
|
||||
foreach (var setting in BlendModeOptionConfigs) {
|
||||
var keyword = setting.Keyword;
|
||||
|
||||
if (newOption != setting.Type) {
|
||||
material.DisableKeyword(keyword);
|
||||
}
|
||||
else {
|
||||
material.SetOverrideTag("RenderType", setting.OverrideTag);
|
||||
material.SetInt("_SrcBlend", (int)setting.SrcBlend);
|
||||
material.SetInt("_DstBlend", (int)setting.DstBlend);
|
||||
material.SetInt("_ZWrite", setting.ZWrite);
|
||||
material.EnableKeyword(keyword);
|
||||
material.renderQueue = setting.RenderQueue;
|
||||
}
|
||||
}
|
||||
|
||||
material.SetInt(Property.name, newOption);
|
||||
EditorUtility.SetDirty(material);
|
||||
}
|
||||
}
|
||||
|
||||
Undo.RecordObjects(args.Materials, "set " + Property.name);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
public class AlloyToggleDrawer : AlloyFieldDrawer {
|
||||
public string[] OnHideFields;
|
||||
public string[] OffHideFields;
|
||||
|
||||
public override void Draw(AlloyFieldDrawerArgs args) {
|
||||
bool current = Property.floatValue > 0.5f;
|
||||
var label = new GUIContent(DisplayName);
|
||||
|
||||
|
||||
//EditorGUI.BeginProperty(new Rect(), label, Serialized);
|
||||
|
||||
EditorGUI.showMixedValue = Property.hasMixedValue;
|
||||
|
||||
EditorGUI.BeginChangeCheck();
|
||||
current = EditorGUILayout.Toggle(label, current);
|
||||
|
||||
if (EditorGUI.EndChangeCheck()) {
|
||||
Property.floatValue = current ? 1.0f : 0.0f;
|
||||
MaterialEditor.ApplyMaterialPropertyDrawers(args.Materials);
|
||||
}
|
||||
|
||||
//EditorGUI.EndProperty();
|
||||
|
||||
EditorGUI.showMixedValue = false;
|
||||
|
||||
|
||||
if (!current) {
|
||||
if (OffHideFields != null) {
|
||||
args.PropertiesSkip.AddRange(OffHideFields);
|
||||
}
|
||||
} else {
|
||||
if (OnHideFields != null) {
|
||||
args.PropertiesSkip.AddRange(OnHideFields);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public AlloyToggleDrawer(AlloyInspectorBase editor, MaterialProperty property) : base(editor, property) {
|
||||
}
|
||||
}
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 70c021998d433f440868615e1d5d09e2
|
||||
timeCreated: 1430261565
|
||||
licenseType: Pro
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
+400
@@ -0,0 +1,400 @@
|
||||
// Alloy Physical Shader Framework
|
||||
// Copyright 2013-2017 RUST LLC.
|
||||
// http://www.alloy.rustltd.com/
|
||||
|
||||
using Alloy;
|
||||
using UnityEditor;
|
||||
using UnityEditor.AnimatedValues;
|
||||
using UnityEngine;
|
||||
|
||||
public class AlloyTextureFieldDrawer : AlloyFieldDrawer {
|
||||
public enum TextureVisualizeMode {
|
||||
None,
|
||||
RGB,
|
||||
R,
|
||||
G,
|
||||
B,
|
||||
A,
|
||||
NRM
|
||||
}
|
||||
|
||||
public string ParentTexture {
|
||||
get { return m_parentTexture; }
|
||||
set {
|
||||
m_parentTexture = value;
|
||||
m_hasParentTexture = !string.IsNullOrEmpty(value);
|
||||
}
|
||||
}
|
||||
|
||||
public TextureVisualizeMode[] DisplayModes;
|
||||
public bool Controls = true;
|
||||
|
||||
protected int TexInst;
|
||||
|
||||
string m_parentTexture = string.Empty;
|
||||
bool m_hasParentTexture;
|
||||
|
||||
protected AlloyTabGroup TabGroup;
|
||||
|
||||
AnimBool m_tabOpen = new AnimBool(false);
|
||||
bool m_firstDraw = true;
|
||||
int m_vizIndex;
|
||||
|
||||
Material m_visualizeMat;
|
||||
Renderer m_oldSelect;
|
||||
|
||||
static GUIContent[] s_uvModes = {new GUIContent("UV0"), new GUIContent("UV1")};
|
||||
static GUILayoutOption[] s_texLayout = new GUILayoutOption[2];
|
||||
|
||||
Material VisualizeMaterial {
|
||||
get {
|
||||
if (m_visualizeMat == null) {
|
||||
m_visualizeMat = new Material(Shader.Find("Hidden/Alloy Visualize")) {hideFlags = HideFlags.HideAndDontSave};
|
||||
}
|
||||
|
||||
return m_visualizeMat;
|
||||
}
|
||||
}
|
||||
|
||||
protected virtual string TextureProp { get { return "m_Texture"; } }
|
||||
|
||||
TextureVisualizeMode Mode {
|
||||
get { return m_vizIndex == 0 ? TextureVisualizeMode.None : DisplayModes[m_vizIndex - 1]; }
|
||||
}
|
||||
|
||||
protected string SaveName { get { return Property.name + TexInst; } }
|
||||
protected bool IsOpen { get { return TabGroup.IsOpen(SaveName); } }
|
||||
|
||||
//Passed in by the base editor
|
||||
public AlloyTextureFieldDrawer(AlloyInspectorBase editor, MaterialProperty property)
|
||||
: base(editor, property) {
|
||||
TabGroup = AlloyTabGroup.GetTabGroup();
|
||||
|
||||
m_tabOpen.value = TabGroup.IsOpen(SaveName);
|
||||
m_tabOpen.speed = 4.0f;
|
||||
}
|
||||
|
||||
|
||||
void AdvanceMode() {
|
||||
m_vizIndex = (m_vizIndex + 1) % (DisplayModes.Length + 1);
|
||||
}
|
||||
|
||||
string GetVisualizeButtonText() {
|
||||
return Mode == TextureVisualizeMode.None ? "Visualize" : Mode.ToString();
|
||||
}
|
||||
|
||||
void TextureField(float size, MaterialProperty prop, AlloyFieldDrawerArgs args) {
|
||||
var rawRef = prop.textureValue;
|
||||
|
||||
if (rawRef == null
|
||||
&& !prop.hasMixedValue
|
||||
&& (!IsOpen || m_hasParentTexture)) {
|
||||
|
||||
s_texLayout[0] = GUILayout.Width(100.0f);
|
||||
s_texLayout[1] = GUILayout.Height(16.0f);
|
||||
}
|
||||
else {
|
||||
s_texLayout[0] = GUILayout.Width(size - 20.0f);
|
||||
s_texLayout[1] = GUILayout.Height((size - 20.0f) * 0.9f);
|
||||
}
|
||||
|
||||
BeginMaterialProperty(Property);
|
||||
|
||||
var tex = EditorGUILayout.ObjectField(rawRef, typeof(Texture), false, s_texLayout) as Texture;
|
||||
|
||||
if (EndMaterialProperty()) {
|
||||
prop.textureValue = tex;
|
||||
}
|
||||
}
|
||||
|
||||
bool DrawWarningString(MaterialProperty texture) {
|
||||
//normal map warning
|
||||
if (DisplayModes == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (ArrayUtility.Contains(DisplayModes, TextureVisualizeMode.NRM)) {
|
||||
if (texture.hasMixedValue || texture.textureValue == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
string path = AssetDatabase.GetAssetPath(texture.textureValue);
|
||||
|
||||
if (!string.IsNullOrEmpty(path)) {
|
||||
var imp = AssetImporter.GetAtPath(path);
|
||||
var importer = imp as TextureImporter;
|
||||
|
||||
// If the texture isn't a Normal Map, offer to convert it.
|
||||
if (importer != null && importer.textureType != TextureImporterType.NormalMap) {
|
||||
GUILayout.BeginHorizontal();
|
||||
EditorGUILayout.HelpBox("Texture not marked as normal map", MessageType.Warning, true);
|
||||
|
||||
var rect = GUILayoutUtility.GetLastRect();
|
||||
|
||||
rect.xMin += rect.width / 2;
|
||||
|
||||
GUILayout.BeginVertical();
|
||||
|
||||
GUILayout.Space(14.0f);
|
||||
|
||||
if (GUILayout.Button("Fix now", EditorStyles.toolbarButton, GUILayout.Width(60.0f))) {
|
||||
importer.textureType = TextureImporterType.NormalMap;
|
||||
AssetDatabase.ImportAsset(path);
|
||||
}
|
||||
|
||||
GUILayout.EndVertical();
|
||||
|
||||
GUILayout.EndHorizontal();
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void DrawVisualizeButton() {
|
||||
if (DisplayModes != null && DisplayModes.Length > 0
|
||||
&& Selection.activeGameObject && Selection.objects.Length == 1) {
|
||||
if (GUILayout.Button(GetVisualizeButtonText(), EditorStyles.toolbarButton, GUILayout.Width(70.0f))) {
|
||||
AdvanceMode();
|
||||
EditorApplication.delayCall += SceneView.RepaintAll;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override void OnDisable() {
|
||||
if (Mode != TextureVisualizeMode.None) {
|
||||
if (m_oldSelect != null) {
|
||||
EditorUtility.SetSelectedRenderState(m_oldSelect, EditorSelectedRenderState.Highlight);
|
||||
}
|
||||
|
||||
m_vizIndex = 0;
|
||||
}
|
||||
}
|
||||
|
||||
public override void OnSceneGUI(Material[] materials) {
|
||||
if (materials.Length > 1) {
|
||||
return;
|
||||
}
|
||||
|
||||
var material = materials[0];
|
||||
|
||||
if (Mode == TextureVisualizeMode.None || Selection.activeGameObject == null || Selection.objects.Length != 1) {
|
||||
if (m_oldSelect != null) {
|
||||
EditorUtility.SetSelectedRenderState(m_oldSelect, EditorSelectedRenderState.Highlight);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
var curTex = Property.textureValue;
|
||||
|
||||
if (Mode == TextureVisualizeMode.None) {
|
||||
return;
|
||||
}
|
||||
|
||||
var trans = Property.textureScaleAndOffset;
|
||||
|
||||
var uvMode = 0.0f;
|
||||
var uvName = !m_hasParentTexture ? Property.name + "UV" : m_parentTexture + "UV";
|
||||
|
||||
if (material.HasProperty(uvName)) {
|
||||
uvMode = material.GetFloat(uvName);
|
||||
}
|
||||
|
||||
VisualizeMaterial.SetTexture("_MainTex", curTex);
|
||||
VisualizeMaterial.SetFloat("_Mode", (int) Mode);
|
||||
VisualizeMaterial.SetVector("_Trans", trans);
|
||||
VisualizeMaterial.SetFloat("_UV", uvMode);
|
||||
|
||||
var target = Selection.activeGameObject.GetComponent<Renderer>();
|
||||
|
||||
if (target != m_oldSelect && m_oldSelect != null) {
|
||||
EditorApplication.delayCall += SceneView.RepaintAll;
|
||||
EditorUtility.SetSelectedRenderState(target, EditorSelectedRenderState.Highlight);
|
||||
return;
|
||||
}
|
||||
|
||||
m_oldSelect = target;
|
||||
|
||||
Mesh mesh = null;
|
||||
var meshFilter = target.GetComponent<MeshFilter>();
|
||||
var meshRenderer = target.GetComponent<MeshRenderer>();
|
||||
|
||||
if (meshFilter != null && meshRenderer != null) {
|
||||
mesh = meshFilter.sharedMesh;
|
||||
}
|
||||
|
||||
if (mesh == null) {
|
||||
var skinnedMeshRenderer = target.GetComponent<SkinnedMeshRenderer>();
|
||||
|
||||
if (skinnedMeshRenderer != null) {
|
||||
mesh = skinnedMeshRenderer.sharedMesh;
|
||||
}
|
||||
}
|
||||
|
||||
if (mesh != null) {
|
||||
EditorUtility.SetSelectedRenderState(target, EditorSelectedRenderState.Hidden);
|
||||
Graphics.DrawMesh(mesh, target.localToWorldMatrix, VisualizeMaterial, 0, SceneView.currentDrawingSceneView.camera,
|
||||
TexInst);
|
||||
SceneView.currentDrawingSceneView.Repaint();
|
||||
}
|
||||
else {
|
||||
Debug.LogError("Game object does not have a mesh source.");
|
||||
}
|
||||
}
|
||||
|
||||
public override void Draw(AlloyFieldDrawerArgs args) {
|
||||
TexInst = args.MatInst;
|
||||
|
||||
if (m_firstDraw) {
|
||||
OnFirstDraw();
|
||||
m_firstDraw = false;
|
||||
}
|
||||
|
||||
var curTex = Property.textureValue;
|
||||
GUILayout.Space(9.0f);
|
||||
GUILayout.BeginHorizontal();
|
||||
EditorGUILayout.BeginVertical();
|
||||
|
||||
float oldWidth = EditorGUIUtility.labelWidth;
|
||||
EditorGUIUtility.labelWidth = 80.0f;
|
||||
|
||||
bool drewOpen = false;
|
||||
|
||||
if (m_hasParentTexture || !Controls) {
|
||||
GUILayout.Label(DisplayName);
|
||||
}
|
||||
else {
|
||||
bool isOpen = TabGroup.Foldout(DisplayName, SaveName, GUILayout.Width(10.0f));
|
||||
m_tabOpen.target = isOpen;
|
||||
|
||||
if (EditorGUILayout.BeginFadeGroup(m_tabOpen.faded)) {
|
||||
drewOpen = true;
|
||||
DrawTextureControls(args);
|
||||
}
|
||||
|
||||
EditorGUILayout.EndFadeGroup();
|
||||
}
|
||||
|
||||
if ((EditorGUILayout.BeginFadeGroup(1.0f - m_tabOpen.faded)
|
||||
|| !Controls)
|
||||
&& curTex != null
|
||||
&& !Property.hasMixedValue) {
|
||||
|
||||
if (!DrawWarningString(Property)) {
|
||||
var oldCol = GUI.color;
|
||||
GUI.color = EditorGUIUtility.isProSkin ? Color.gray : new Color(0.3f, 0.3f, 0.3f);
|
||||
|
||||
string name = curTex.name;
|
||||
if (name.Length > 17) {
|
||||
name = name.Substring(0, 14) + "..";
|
||||
}
|
||||
GUILayout.Label(name + " (" + curTex.width + "x" + curTex.height + ")", EditorStyles.whiteLabel);
|
||||
GUI.color = oldCol;
|
||||
}
|
||||
}
|
||||
|
||||
EditorGUILayout.EndFadeGroup();
|
||||
|
||||
if (curTex != null
|
||||
&& (!m_hasParentTexture || Controls)
|
||||
&& !Property.hasMixedValue) {
|
||||
DrawVisualizeButton();
|
||||
}
|
||||
|
||||
if (drewOpen) {
|
||||
EditorGUILayout.EndVertical();
|
||||
TextureField(Mathf.Lerp(74.0f, 100.0f, m_tabOpen.faded), Property, args);
|
||||
}
|
||||
else {
|
||||
GUILayout.EndVertical();
|
||||
|
||||
GUILayout.FlexibleSpace();
|
||||
TextureField(74.0f, Property, args);
|
||||
}
|
||||
|
||||
EditorGUIUtility.labelWidth = oldWidth;
|
||||
GUILayout.EndHorizontal();
|
||||
|
||||
if (IsOpen) {
|
||||
GUILayout.Space(10.0f);
|
||||
}
|
||||
|
||||
|
||||
if (m_tabOpen.isAnimating) {
|
||||
args.Editor.MatEditor.Repaint();
|
||||
}
|
||||
}
|
||||
|
||||
protected void DrawTextureControls(AlloyFieldDrawerArgs args) {
|
||||
|
||||
string velName = Property.name + "Velocity";
|
||||
var scrollProp = args.GetMaterialProperty(velName);
|
||||
|
||||
string spinName = Property.name + "Spin";
|
||||
var spinProp = args.GetMaterialProperty(spinName);
|
||||
|
||||
string uvName = Property.name + "UV";
|
||||
var uvProp = args.GetMaterialProperty(uvName);
|
||||
|
||||
|
||||
BeginMaterialProperty(Property);
|
||||
var trans = Property.textureScaleAndOffset;
|
||||
|
||||
Vector2 tileVal = EditorGUILayout.Vector2Field("Tiling", new Vector2(trans.x, trans.y));
|
||||
Vector2 offsetVal = EditorGUILayout.Vector2Field("Offset", new Vector2(trans.z, trans.w));
|
||||
|
||||
trans.x = tileVal.x;
|
||||
trans.y = tileVal.y;
|
||||
trans.z = offsetVal.x;
|
||||
trans.w = offsetVal.y;
|
||||
|
||||
|
||||
if (scrollProp != null) {
|
||||
BeginMaterialProperty(scrollProp);
|
||||
Vector2 curScroll = EditorGUILayout.Vector2Field("Scroll", scrollProp.vectorValue);
|
||||
|
||||
if (EndMaterialProperty()) {
|
||||
scrollProp.vectorValue = curScroll;
|
||||
}
|
||||
}
|
||||
|
||||
float old = EditorGUIUtility.labelWidth;
|
||||
EditorGUIUtility.labelWidth = 75.0f;
|
||||
|
||||
if (spinProp != null) {
|
||||
BeginMaterialProperty(spinProp);
|
||||
|
||||
float spin = spinProp.floatValue * Mathf.Rad2Deg;
|
||||
spin = EditorGUILayout.FloatField(new GUIContent("Spin"), spin, GUILayout.Width(180.0f));
|
||||
|
||||
if (EndMaterialProperty()) {
|
||||
spinProp.floatValue = spin * Mathf.Deg2Rad;
|
||||
}
|
||||
}
|
||||
|
||||
if (uvProp != null) {
|
||||
BeginMaterialProperty(uvProp);
|
||||
|
||||
float newVal = EditorGUILayout.Popup(new GUIContent("UV Set"), (int) uvProp.floatValue, s_uvModes,
|
||||
GUILayout.Width(180.0f));
|
||||
|
||||
if (EndMaterialProperty()) {
|
||||
uvProp.floatValue = newVal;
|
||||
}
|
||||
}
|
||||
|
||||
EditorGUIUtility.labelWidth = old;
|
||||
|
||||
if (EndMaterialProperty()) {
|
||||
Property.textureScaleAndOffset = trans;
|
||||
}
|
||||
}
|
||||
|
||||
void OnFirstDraw() {
|
||||
m_tabOpen.value = IsOpen;
|
||||
}
|
||||
}
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 26f92e852a911224cbd5f29a496d6698
|
||||
timeCreated: 1430261489
|
||||
licenseType: Pro
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
+67
@@ -0,0 +1,67 @@
|
||||
// Alloy Physical Shader Framework
|
||||
// Copyright 2013-2017 RUST LLC.
|
||||
// http://www.alloy.rustltd.com/
|
||||
|
||||
using System;
|
||||
using System.Linq;
|
||||
using UnityEditor;
|
||||
|
||||
public class AlloyTextureParser : AlloyFieldParser
|
||||
{
|
||||
protected override AlloyFieldDrawer GenerateDrawer(AlloyInspectorBase editor) {
|
||||
var ret = new AlloyTextureFieldDrawer(editor, MaterialProperty);
|
||||
|
||||
foreach (var token in Arguments) {
|
||||
var argName = token.ArgumentName;
|
||||
var argToken = token.ArgumentToken;
|
||||
|
||||
switch (argName) {
|
||||
case "Visualize": {
|
||||
var container = argToken as AlloyCollectionToken;
|
||||
if (container != null) {
|
||||
ret.DisplayModes = container.SubTokens.Select(t => (AlloyTextureFieldDrawer.TextureVisualizeMode)Enum.Parse(typeof(AlloyTextureFieldDrawer.TextureVisualizeMode), t.Token)).ToArray();
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case "Parent": {
|
||||
ret.ParentTexture = argToken.Token;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case "Controls":
|
||||
var valueToken = argToken as AlloyValueToken;
|
||||
if (valueToken != null) {
|
||||
ret.Controls = valueToken.BoolValue;
|
||||
}
|
||||
break;
|
||||
|
||||
// case "Keyword":
|
||||
// ret.Keyword = argToken.Token;
|
||||
// break;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
public AlloyTextureParser(MaterialProperty field)
|
||||
: base(field) {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
public class AlloyCubeParser : AlloyFieldParser
|
||||
{
|
||||
public AlloyCubeParser(MaterialProperty field)
|
||||
: base(field) {
|
||||
|
||||
}
|
||||
|
||||
protected override AlloyFieldDrawer GenerateDrawer(AlloyInspectorBase editor) {
|
||||
return new AlloyDefaultDrawer(editor, MaterialProperty);
|
||||
}
|
||||
}
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 5767db00543c76746b04f3bf27442325
|
||||
timeCreated: 1430261463
|
||||
licenseType: Pro
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
+184
@@ -0,0 +1,184 @@
|
||||
// Alloy Physical Shader Framework
|
||||
// Copyright 2013-2017 RUST LLC.
|
||||
// http://www.alloy.rustltd.com/
|
||||
|
||||
using Alloy;
|
||||
using UnityEditor;
|
||||
using UnityEditor.AnimatedValues;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
|
||||
public class AlloyVectorParser : AlloyFieldParser {
|
||||
protected override AlloyFieldDrawer GenerateDrawer(AlloyInspectorBase editor) {
|
||||
AlloyFieldDrawer ret = null;
|
||||
|
||||
for (int i = 0; i < Arguments.Length; i++) {
|
||||
var argument = Arguments[i];
|
||||
var valProp = argument.ArgumentToken as AlloyValueToken;
|
||||
|
||||
switch (argument.ArgumentName) {
|
||||
case "Vector":
|
||||
|
||||
if (valProp != null) {
|
||||
ret = SetupVectorDrawer(editor, valProp, ret);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (ret == null) {
|
||||
ret = new AlloyVectorDrawer(editor, MaterialProperty);
|
||||
((AlloyVectorDrawer) ret).Mode = AlloyVectorDrawer.VectorMode.Vector4;
|
||||
}
|
||||
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
AlloyFieldDrawer SetupVectorDrawer(AlloyInspectorBase editor,
|
||||
AlloyValueToken valProp,
|
||||
AlloyFieldDrawer ret) {
|
||||
if (valProp.ValueType == AlloyValueToken.ValueTypeEnum.String) {
|
||||
switch (valProp.StringValue) {
|
||||
case "Euler":
|
||||
ret = new AlloyVectorDrawer(editor, MaterialProperty);
|
||||
((AlloyVectorDrawer) ret).Mode = AlloyVectorDrawer.VectorMode.Euler;
|
||||
break;
|
||||
|
||||
case "TexCoord":
|
||||
ret = new AlloyTexCoordDrawer(editor, MaterialProperty);
|
||||
break;
|
||||
|
||||
case "Channels":
|
||||
ret = new AlloyMaskDrawer(editor, MaterialProperty);
|
||||
break;
|
||||
|
||||
default:
|
||||
Debug.LogError("Non supported vector property!");
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (valProp.ValueType == AlloyValueToken.ValueTypeEnum.Float) {
|
||||
switch ((int) valProp.FloatValue) {
|
||||
case 2:
|
||||
ret = new AlloyVectorDrawer(editor, MaterialProperty);
|
||||
((AlloyVectorDrawer) ret).Mode = AlloyVectorDrawer.VectorMode.Vector2;
|
||||
break;
|
||||
|
||||
case 3:
|
||||
ret = new AlloyVectorDrawer(editor, MaterialProperty);
|
||||
((AlloyVectorDrawer) ret).Mode = AlloyVectorDrawer.VectorMode.Vector3;
|
||||
break;
|
||||
|
||||
case 4:
|
||||
ret = new AlloyVectorDrawer(editor, MaterialProperty);
|
||||
((AlloyVectorDrawer) ret).Mode = AlloyVectorDrawer.VectorMode.Vector4;
|
||||
break;
|
||||
|
||||
default:
|
||||
Debug.LogError("Non supported vector property!");
|
||||
break;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
public AlloyVectorParser(MaterialProperty field)
|
||||
: base(field) {
|
||||
}
|
||||
}
|
||||
|
||||
public class AlloyVectorDrawer : AlloyFieldDrawer {
|
||||
public enum VectorMode {
|
||||
Vector2,
|
||||
Vector3,
|
||||
Vector4,
|
||||
Euler
|
||||
}
|
||||
|
||||
public VectorMode Mode = VectorMode.Vector4;
|
||||
|
||||
public override void Draw(AlloyFieldDrawerArgs args) {
|
||||
Vector4 newVal = Vector4.zero;
|
||||
var label = new GUIContent(DisplayName);
|
||||
|
||||
BeginMaterialProperty(Property);
|
||||
|
||||
switch (Mode) {
|
||||
case VectorMode.Vector4:
|
||||
newVal = EditorGUILayout.Vector4Field(label.text, Property.vectorValue);
|
||||
break;
|
||||
|
||||
case VectorMode.Vector3:
|
||||
newVal = EditorGUILayout.Vector3Field(label.text, Property.vectorValue);
|
||||
break;
|
||||
|
||||
case VectorMode.Vector2:
|
||||
newVal = EditorGUILayout.Vector2Field(label.text, Property.vectorValue);
|
||||
break;
|
||||
|
||||
case VectorMode.Euler:
|
||||
var value = args.GetMaterialProperty(Property.name + "EulerUI").vectorValue;
|
||||
//var value = (Vector4)args.Editor.GetProperty(MaterialProperty.PropType.Vector, Property.name + "EulerUI").colorValue;
|
||||
newVal = Quaternion.Euler(value) * Vector3.up;
|
||||
GUI.changed = true;
|
||||
break;
|
||||
}
|
||||
|
||||
if (EndMaterialProperty()) {
|
||||
Property.vectorValue = newVal;
|
||||
}
|
||||
}
|
||||
|
||||
public AlloyVectorDrawer(AlloyInspectorBase editor, MaterialProperty property) : base(editor, property) {
|
||||
}
|
||||
}
|
||||
|
||||
public class AlloyTexCoordDrawer : AlloyTextureFieldDrawer {
|
||||
AnimBool m_tabOpen = new AnimBool(false);
|
||||
|
||||
public AlloyTexCoordDrawer(AlloyInspectorBase editor, MaterialProperty property) : base(editor, property) {
|
||||
}
|
||||
|
||||
public override void Draw(AlloyFieldDrawerArgs args) {
|
||||
TexInst = args.MatInst;
|
||||
|
||||
bool isOpen = TabGroup.Foldout(DisplayName, SaveName, GUILayout.Width(10.0f));
|
||||
m_tabOpen.target = isOpen;
|
||||
|
||||
if (m_tabOpen.value) {
|
||||
EditorGUILayout.BeginFadeGroup(m_tabOpen.faded);
|
||||
DrawTextureControls(args);
|
||||
EditorGUILayout.EndFadeGroup();
|
||||
}
|
||||
|
||||
if (m_tabOpen.isAnimating) {
|
||||
args.Editor.MatEditor.Repaint();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class AlloyMaskDrawer : AlloyFieldDrawer {
|
||||
public AlloyMaskDrawer(AlloyInspectorBase editor, MaterialProperty property) : base(editor, property) {
|
||||
}
|
||||
|
||||
public override void Draw(AlloyFieldDrawerArgs args) {
|
||||
Vector4 newVal = Property.vectorValue;
|
||||
var label = new GUIContent(DisplayName);
|
||||
|
||||
BeginMaterialProperty(Property);
|
||||
|
||||
GUILayout.BeginHorizontal();
|
||||
GUILayout.Label(label);
|
||||
|
||||
newVal.x = GUILayout.Toggle(newVal.x > 0.5f, "R", EditorStyles.toolbarButton) ? 1.0f : 0.0f;
|
||||
newVal.y = GUILayout.Toggle(newVal.y > 0.5f, "G", EditorStyles.toolbarButton) ? 1.0f : 0.0f;
|
||||
newVal.z = GUILayout.Toggle(newVal.z > 0.5f, "B", EditorStyles.toolbarButton) ? 1.0f : 0.0f;
|
||||
newVal.w = GUILayout.Toggle(newVal.w > 0.5f, "A", EditorStyles.toolbarButton) ? 1.0f : 0.0f;
|
||||
GUILayout.EndHorizontal();
|
||||
|
||||
if (EndMaterialProperty()) {
|
||||
Property.vectorValue = newVal;
|
||||
}
|
||||
}
|
||||
}
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 6c2ebab9324a76547a9d5df7b45cd747
|
||||
timeCreated: 1430261728
|
||||
licenseType: Pro
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,5 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 6e87a104f11c6ab4295a1bec1f86e81c
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
userData:
|
||||
@@ -0,0 +1,77 @@
|
||||
// Alloy Physical Shader Framework
|
||||
// Copyright 2013-2017 RUST LLC.
|
||||
// http://www.alloy.rustltd.com/
|
||||
|
||||
Shader "Hidden/Alloy Visualize" {
|
||||
Properties {
|
||||
_MainTex ("Base (RGB)", 2D) = "white" {}
|
||||
_Mode("Mode", Float) = 0
|
||||
_Trans("Trans", Vector) = (0, 0, 0, 0)
|
||||
_UV("UV", Float) = 0
|
||||
}
|
||||
SubShader {
|
||||
Offset 0,-10
|
||||
|
||||
Pass {
|
||||
CGPROGRAM
|
||||
#pragma vertex vert
|
||||
#pragma fragment frag
|
||||
#include "UnityCG.cginc"
|
||||
#pragma target 3.0
|
||||
|
||||
struct v2f {
|
||||
float4 pos : SV_POSITION;
|
||||
float2 uv_MainTex : TEXCOORD0;
|
||||
};
|
||||
|
||||
float4 _MainTex_ST;
|
||||
float _Mode;
|
||||
float _UV;
|
||||
|
||||
v2f vert(appdata_full v) {
|
||||
v2f o;
|
||||
|
||||
o.pos = UnityObjectToClipPos(v.vertex.xyz);
|
||||
float4 posWorld = mul(unity_ObjectToWorld, v.vertex);
|
||||
|
||||
//o.pos.w += 1e-5;
|
||||
|
||||
o.uv_MainTex = _UV == 0.0f ? v.texcoord.xy : v.texcoord1.xy;
|
||||
return o;
|
||||
}
|
||||
|
||||
sampler2D _MainTex;
|
||||
float4 _Trans;
|
||||
|
||||
float4 frag(v2f IN) : SV_Target {
|
||||
float4 c = tex2D (_MainTex, IN.uv_MainTex * _Trans.xy + _Trans.zw).rgba;
|
||||
float eps = 0.001f;
|
||||
|
||||
if (_Mode <= eps){
|
||||
c.rgb = 0.0f;
|
||||
}
|
||||
else if (_Mode <= 1 + eps) {
|
||||
c.rgb = c.rgb; // Assumes automatic sRGB
|
||||
}
|
||||
else if (_Mode <= 2 + eps){
|
||||
c.rgb = pow(c.rrr, 2.2f);
|
||||
}
|
||||
else if (_Mode <= 3 + eps){
|
||||
c.rgb = pow(c.ggg, 2.2f);
|
||||
}
|
||||
else if (_Mode <= 4 + eps){
|
||||
c.rgb = pow(c.bbb, 2.2f);
|
||||
}
|
||||
else if (_Mode <= 5 + eps){
|
||||
c.rgb = pow(c.aaa, 2.2f);
|
||||
}
|
||||
else if (_Mode <= 6 + eps){
|
||||
c.rgb = pow(UnpackNormal(c) * 0.5f + 0.5f, 2.2f);
|
||||
}
|
||||
|
||||
return c;
|
||||
}
|
||||
ENDCG
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 5bca5ef19340cc044b0acb00214f111b
|
||||
ShaderImporter:
|
||||
defaultTextures: []
|
||||
userData:
|
||||
@@ -0,0 +1,5 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 2c93dc09429ea9e4fa76bf67d52294fc
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
userData:
|
||||
@@ -0,0 +1,9 @@
|
||||
fileFormatVersion: 2
|
||||
guid: a69ac5a688c6fbb428b61b55448c7392
|
||||
folderAsset: yes
|
||||
timeCreated: 1467548303
|
||||
licenseType: Pro
|
||||
DefaultImporter:
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,41 @@
|
||||
%YAML 1.1
|
||||
%TAG !u! tag:unity3d.com,2011:
|
||||
--- !u!114 &11400000
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_PrefabParentObject: {fileID: 0}
|
||||
m_PrefabInternal: {fileID: 0}
|
||||
m_GameObject: {fileID: 0}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: f11657fe81562504cb1b05d4e700d54d, type: 3}
|
||||
m_Name: AlphaPack
|
||||
m_EditorClassIdentifier:
|
||||
Title: Alpha
|
||||
Suffix: _AlloyAM
|
||||
VarianceBias: 1
|
||||
ImportSettings:
|
||||
IsLinear: 0
|
||||
Filter: 2
|
||||
DefaultCompressed: 1
|
||||
Channels:
|
||||
- Title: Color
|
||||
HelpText:
|
||||
BackgroundColor: {r: 0, g: .583999991, b: .0520000011, a: 1}
|
||||
CanInvert: 0
|
||||
InputChannels: 7
|
||||
OutputChannels: 7
|
||||
RoughnessCorrect: 0
|
||||
OutputVariance: 0
|
||||
HideChannel: 0
|
||||
DefaultMode: 4
|
||||
- Title: Alpha
|
||||
HelpText:
|
||||
BackgroundColor: {r: 0, g: 0, b: 0, a: 1}
|
||||
CanInvert: 1
|
||||
InputChannels: 2
|
||||
OutputChannels: 8
|
||||
RoughnessCorrect: 0
|
||||
OutputVariance: 0
|
||||
HideChannel: 0
|
||||
DefaultMode: 4
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 5d1947582bfff244299d3af2cb6ab782
|
||||
timeCreated: 1439420452
|
||||
licenseType: Pro
|
||||
NativeFormatImporter:
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,65 @@
|
||||
%YAML 1.1
|
||||
%TAG !u! tag:unity3d.com,2011:
|
||||
--- !u!114 &11400000
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_PrefabParentObject: {fileID: 0}
|
||||
m_PrefabInternal: {fileID: 0}
|
||||
m_GameObject: {fileID: 0}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: f11657fe81562504cb1b05d4e700d54d, type: 3}
|
||||
m_Name: MasksPack
|
||||
m_EditorClassIdentifier:
|
||||
Title: Masks
|
||||
Suffix: _AlloyMM
|
||||
VarianceBias: 1
|
||||
ImportSettings:
|
||||
IsLinear: 1
|
||||
Filter: 2
|
||||
DefaultCompressed: 1
|
||||
Channels:
|
||||
- Title: Red
|
||||
HelpText:
|
||||
BackgroundColor: {r: 0.5882353, g: 0, b: 0, a: 1}
|
||||
CanInvert: 1
|
||||
InvertByDefault: 0
|
||||
InputChannels: 2
|
||||
OutputChannels: 1
|
||||
RoughnessCorrect: 0
|
||||
OutputVariance: 0
|
||||
HideChannel: 0
|
||||
DefaultMode: 4
|
||||
- Title: Green
|
||||
HelpText:
|
||||
BackgroundColor: {r: 0, g: 0.584, b: 0.052, a: 1}
|
||||
CanInvert: 1
|
||||
InvertByDefault: 0
|
||||
InputChannels: 2
|
||||
OutputChannels: 2
|
||||
RoughnessCorrect: 0
|
||||
OutputVariance: 0
|
||||
HideChannel: 0
|
||||
DefaultMode: 4
|
||||
- Title: Blue
|
||||
HelpText:
|
||||
BackgroundColor: {r: 0.043137256, g: 0, b: 0.5803922, a: 1}
|
||||
CanInvert: 1
|
||||
InvertByDefault: 0
|
||||
InputChannels: 2
|
||||
OutputChannels: 4
|
||||
RoughnessCorrect: 0
|
||||
OutputVariance: 0
|
||||
HideChannel: 0
|
||||
DefaultMode: 4
|
||||
- Title: Alpha
|
||||
HelpText:
|
||||
BackgroundColor: {r: 0, g: 0, b: 0, a: 1}
|
||||
CanInvert: 1
|
||||
InvertByDefault: 0
|
||||
InputChannels: 2
|
||||
OutputChannels: 8
|
||||
RoughnessCorrect: 0
|
||||
OutputVariance: 0
|
||||
HideChannel: 0
|
||||
DefaultMode: 4
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f0d4fc30aba4a084ba51be9301faf8a9
|
||||
timeCreated: 1439420318
|
||||
licenseType: Pro
|
||||
NativeFormatImporter:
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,61 @@
|
||||
%YAML 1.1
|
||||
%TAG !u! tag:unity3d.com,2011:
|
||||
--- !u!114 &11400000
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_PrefabParentObject: {fileID: 0}
|
||||
m_PrefabInternal: {fileID: 0}
|
||||
m_GameObject: {fileID: 0}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: f11657fe81562504cb1b05d4e700d54d, type: 3}
|
||||
m_Name: PackedPack
|
||||
m_EditorClassIdentifier:
|
||||
Title: Packed
|
||||
Suffix: _AlloyPM
|
||||
VarianceBias: 1
|
||||
ImportSettings:
|
||||
IsLinear: 1
|
||||
Filter: 2
|
||||
DefaultCompressed: 1
|
||||
Channels:
|
||||
- Title: Metallic
|
||||
HelpText: Black = Non-metal, White = Metal
|
||||
BackgroundColor: {r: .588235319, g: 0, b: 0, a: 1}
|
||||
CanInvert: 1
|
||||
InputChannels: 2
|
||||
OutputChannels: 1
|
||||
RoughnessCorrect: 0
|
||||
OutputVariance: 0
|
||||
HideChannel: 0
|
||||
DefaultMode: 4
|
||||
- Title: Occlusion
|
||||
HelpText: Black = Occluded, White = Unoccluded
|
||||
BackgroundColor: {r: 0, g: .583999991, b: .0520000011, a: 1}
|
||||
CanInvert: 1
|
||||
InputChannels: 2
|
||||
OutputChannels: 2
|
||||
RoughnessCorrect: 0
|
||||
OutputVariance: 0
|
||||
HideChannel: 0
|
||||
DefaultMode: 4
|
||||
- Title: Specularity
|
||||
HelpText: Black = Air, Gray = Paint, White = Gems
|
||||
BackgroundColor: {r: .0431372561, g: 0, b: .580392182, a: 1}
|
||||
CanInvert: 1
|
||||
InputChannels: 2
|
||||
OutputChannels: 4
|
||||
RoughnessCorrect: 0
|
||||
OutputVariance: 0
|
||||
HideChannel: 0
|
||||
DefaultMode: 1
|
||||
- Title: Roughness
|
||||
HelpText: Black = Smooth, White = Rough
|
||||
BackgroundColor: {r: 0, g: 0, b: 0, a: 1}
|
||||
CanInvert: 1
|
||||
InputChannels: 2
|
||||
OutputChannels: 8
|
||||
RoughnessCorrect: 1
|
||||
OutputVariance: 0
|
||||
HideChannel: 0
|
||||
DefaultMode: 4
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 1d42740116df09f4f9c9e144a4b9885f
|
||||
timeCreated: 1439419411
|
||||
licenseType: Pro
|
||||
NativeFormatImporter:
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,41 @@
|
||||
%YAML 1.1
|
||||
%TAG !u! tag:unity3d.com,2011:
|
||||
--- !u!114 &11400000
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_PrefabParentObject: {fileID: 0}
|
||||
m_PrefabInternal: {fileID: 0}
|
||||
m_GameObject: {fileID: 0}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: f11657fe81562504cb1b05d4e700d54d, type: 3}
|
||||
m_Name: TerrainPack
|
||||
m_EditorClassIdentifier:
|
||||
Title: Terrain
|
||||
Suffix: _AlloyTM
|
||||
VarianceBias: 1
|
||||
ImportSettings:
|
||||
IsLinear: 0
|
||||
Filter: 2
|
||||
DefaultCompressed: 1
|
||||
Channels:
|
||||
- Title: Color
|
||||
HelpText: Base color for terrain.
|
||||
BackgroundColor: {r: 0, g: 0.584, b: 0.052, a: 1}
|
||||
CanInvert: 0
|
||||
InputChannels: 7
|
||||
OutputChannels: 7
|
||||
RoughnessCorrect: 0
|
||||
OutputVariance: 0
|
||||
HideChannel: 0
|
||||
DefaultMode: 4
|
||||
- Title: Roughness
|
||||
HelpText: Black = Smooth, White = Rough
|
||||
BackgroundColor: {r: 0, g: 0, b: 0, a: 1}
|
||||
CanInvert: 1
|
||||
InputChannels: 2
|
||||
OutputChannels: 8
|
||||
RoughnessCorrect: 1
|
||||
OutputVariance: 0
|
||||
HideChannel: 0
|
||||
DefaultMode: 4
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 2bf47aefc6b2d2b4fa519cb677bb4346
|
||||
timeCreated: 1439420067
|
||||
licenseType: Pro
|
||||
NativeFormatImporter:
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,65 @@
|
||||
%YAML 1.1
|
||||
%TAG !u! tag:unity3d.com,2011:
|
||||
--- !u!114 &11400000
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_PrefabParentObject: {fileID: 0}
|
||||
m_PrefabInternal: {fileID: 0}
|
||||
m_GameObject: {fileID: 0}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: f11657fe81562504cb1b05d4e700d54d, type: 3}
|
||||
m_Name: UnityPackedPack
|
||||
m_EditorClassIdentifier:
|
||||
Title: Unity PM
|
||||
Suffix: _AlloyUPM
|
||||
VarianceBias: 1
|
||||
ImportSettings:
|
||||
IsLinear: 1
|
||||
Filter: 2
|
||||
DefaultCompressed: 1
|
||||
Channels:
|
||||
- Title: Metallic
|
||||
HelpText: Black = Non-metal, White = Metal
|
||||
BackgroundColor: {r: 0.5882353, g: 0, b: 0, a: 1}
|
||||
CanInvert: 1
|
||||
InvertByDefault: 0
|
||||
InputChannels: 1
|
||||
OutputChannels: 1
|
||||
RoughnessCorrect: 0
|
||||
OutputVariance: 0
|
||||
HideChannel: 0
|
||||
DefaultMode: 4
|
||||
- Title: Occlusion
|
||||
HelpText: Black = Occluded, White = Unoccluded
|
||||
BackgroundColor: {r: 0, g: 0.584, b: 0.052, a: 1}
|
||||
CanInvert: 1
|
||||
InvertByDefault: 0
|
||||
InputChannels: 2
|
||||
OutputChannels: 2
|
||||
RoughnessCorrect: 0
|
||||
OutputVariance: 0
|
||||
HideChannel: 0
|
||||
DefaultMode: 4
|
||||
- Title: Specularity
|
||||
HelpText: Black = Air, Gray = Paint, White = Gems
|
||||
BackgroundColor: {r: 0.043137256, g: 0, b: 0.5803922, a: 1}
|
||||
CanInvert: 1
|
||||
InvertByDefault: 0
|
||||
InputChannels: 4
|
||||
OutputChannels: 4
|
||||
RoughnessCorrect: 0
|
||||
OutputVariance: 0
|
||||
HideChannel: 0
|
||||
DefaultMode: 1
|
||||
- Title: Smoothness
|
||||
HelpText: Black = Rough, White = Smooth
|
||||
BackgroundColor: {r: 0, g: 0, b: 0, a: 1}
|
||||
CanInvert: 1
|
||||
InvertByDefault: 1
|
||||
InputChannels: 8
|
||||
OutputChannels: 8
|
||||
RoughnessCorrect: 1
|
||||
OutputVariance: 0
|
||||
HideChannel: 0
|
||||
DefaultMode: 4
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 23522b2d0809c9c4d9428659169ec2a1
|
||||
timeCreated: 1458592032
|
||||
licenseType: Pro
|
||||
NativeFormatImporter:
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,43 @@
|
||||
%YAML 1.1
|
||||
%TAG !u! tag:unity3d.com,2011:
|
||||
--- !u!114 &11400000
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_PrefabParentObject: {fileID: 0}
|
||||
m_PrefabInternal: {fileID: 0}
|
||||
m_GameObject: {fileID: 0}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: f11657fe81562504cb1b05d4e700d54d, type: 3}
|
||||
m_Name: UnityTerrainPack
|
||||
m_EditorClassIdentifier:
|
||||
Title: Unity TM
|
||||
Suffix: _AlloyUTM
|
||||
VarianceBias: 1
|
||||
ImportSettings:
|
||||
IsLinear: 0
|
||||
Filter: 2
|
||||
DefaultCompressed: 1
|
||||
Channels:
|
||||
- Title: Color
|
||||
HelpText: Base color for terrain.
|
||||
BackgroundColor: {r: 0, g: 0.584, b: 0.052, a: 1}
|
||||
CanInvert: 0
|
||||
InvertByDefault: 0
|
||||
InputChannels: 7
|
||||
OutputChannels: 7
|
||||
RoughnessCorrect: 0
|
||||
OutputVariance: 0
|
||||
HideChannel: 0
|
||||
DefaultMode: 4
|
||||
- Title: Smoothness
|
||||
HelpText: Black = Rough, White = Smooth
|
||||
BackgroundColor: {r: 0, g: 0, b: 0, a: 1}
|
||||
CanInvert: 1
|
||||
InvertByDefault: 1
|
||||
InputChannels: 8
|
||||
OutputChannels: 8
|
||||
RoughnessCorrect: 1
|
||||
OutputVariance: 0
|
||||
HideChannel: 0
|
||||
DefaultMode: 4
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 972cff293012f9740a9250f756d7418b
|
||||
timeCreated: 1458593840
|
||||
licenseType: Pro
|
||||
NativeFormatImporter:
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,26 @@
|
||||
%YAML 1.1
|
||||
%TAG !u! tag:unity3d.com,2011:
|
||||
--- !u!114 &11400000
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_PrefabParentObject: {fileID: 0}
|
||||
m_PrefabInternal: {fileID: 0}
|
||||
m_GameObject: {fileID: 0}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: e5c13c2962344f14d8d0d22b07fa9495, type: 3}
|
||||
m_Name: _PackerDefinition
|
||||
m_EditorClassIdentifier:
|
||||
PackedMaps:
|
||||
- {fileID: 11400000, guid: 1d42740116df09f4f9c9e144a4b9885f, type: 2}
|
||||
- {fileID: 11400000, guid: 2bf47aefc6b2d2b4fa519cb677bb4346, type: 2}
|
||||
- {fileID: 11400000, guid: f0d4fc30aba4a084ba51be9301faf8a9, type: 2}
|
||||
- {fileID: 11400000, guid: 5d1947582bfff244299d3af2cb6ab782, type: 2}
|
||||
- {fileID: 11400000, guid: 23522b2d0809c9c4d9428659169ec2a1, type: 2}
|
||||
- {fileID: 11400000, guid: 972cff293012f9740a9250f756d7418b, type: 2}
|
||||
NRMChannel:
|
||||
Title: Normal map
|
||||
HelpText: (Optional) Used for Specular AA
|
||||
BackgroundColor: {r: 0.322, g: 0, b: 0.472, a: 1}
|
||||
VarianceText: Bias normal map variance toward zero to reduce Specular AA effect.
|
||||
AutoRegenerateText: Regenerate this map when any of its input textures are updated./
|
||||
@@ -0,0 +1,9 @@
|
||||
fileFormatVersion: 2
|
||||
guid: e29b4e8febd8e3949a1d18cf25c0271a
|
||||
timeCreated: 1491251285
|
||||
licenseType: Pro
|
||||
NativeFormatImporter:
|
||||
mainObjectFileID: 11400000
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,5 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 0ce61627d85169d48874646872429200
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
userData:
|
||||
@@ -0,0 +1,288 @@
|
||||
// Alloy Physical Shader Framework
|
||||
// Copyright 2013-2017 RUST LLC.
|
||||
// http://www.alloy.rustltd.com/
|
||||
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.IO;
|
||||
using System.Reflection;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
using Object = UnityEngine.Object;
|
||||
|
||||
namespace Alloy {
|
||||
public class AlloyCustomImportAction : AssetPostprocessor {
|
||||
delegate void OnAlloyImportFunc(AlloyCustomImportObject settings, Texture2D texture, string path);
|
||||
|
||||
public static bool IsAlloyPackedMapPath(string path) {
|
||||
path = Path.GetFileNameWithoutExtension(path);
|
||||
var definition = AlloyMaterialMapChannelPacker.GlobalDefinition;
|
||||
|
||||
//Alloy not imported yet -> Assume we're either importing new alloy
|
||||
//and we're importing it now
|
||||
if (definition == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return definition.IsPackedMap(path);
|
||||
}
|
||||
|
||||
//Make sure to generate PNG alongside .asset file if it doesn't exist yet
|
||||
private static void OnPostprocessAllAssets(string[] importedAssets, string[] deletedAssets, string[] movedAssets,
|
||||
string[] movedFromAssetPath) {
|
||||
foreach (var asset in importedAssets) {
|
||||
if (!IsAlloyPackedMapPath(asset)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (File.Exists(asset.Replace(".asset", ".png"))) {
|
||||
continue;
|
||||
}
|
||||
|
||||
var settings = AssetDatabase.LoadAssetAtPath(asset, typeof (AlloyCustomImportObject)) as AlloyCustomImportObject;
|
||||
|
||||
if (settings != null) {
|
||||
settings.GenerateMap();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void OnAlloyImport(Texture2D texture, OnAlloyImportFunc onImport) {
|
||||
// Check to see if this is an Alloy material that we need to edit.
|
||||
if (!IsAlloyPackedMapPath(assetPath)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// and if we've got saved settings/data for it...
|
||||
var textureName = Path.GetFileNameWithoutExtension(assetPath);
|
||||
var path = Path.Combine(Path.GetDirectoryName(assetPath), textureName) + ".asset";
|
||||
|
||||
//Import can fail because of a variety of reasons, so make sure it's all good here
|
||||
if (!File.Exists(path)) {
|
||||
Debug.LogError(textureName + " has no post-processing data! Please contact Alloy support.");
|
||||
Selection.activeObject = texture;
|
||||
return;
|
||||
}
|
||||
|
||||
var settings = AssetDatabase.LoadAssetAtPath(path, typeof (AlloyCustomImportObject)) as AlloyCustomImportObject;
|
||||
if (settings == null) {
|
||||
if (AlloyImporterSupervisor.IsFinalTry) {
|
||||
Debug.LogError(textureName + " settings file is corrupt! Contact Alloy support");
|
||||
return;
|
||||
}
|
||||
|
||||
AlloyImporterSupervisor.OnFailedImport(path);
|
||||
return;
|
||||
}
|
||||
|
||||
for (int i = 0; i < 4; ++i) {
|
||||
if (settings.SelectedModes[i] == TextureValueChannelMode.Texture && settings.GetTexture(i) == null) {
|
||||
if (AlloyImporterSupervisor.IsFinalTry) {
|
||||
Debug.LogError(textureName + " texture input " + (i + 1) + " can't be loaded!");
|
||||
return;
|
||||
}
|
||||
|
||||
AlloyImporterSupervisor.OnFailedImport(path);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(settings.NormalGUID) && settings.NormalMapTexture == null) {
|
||||
if (AlloyImporterSupervisor.IsFinalTry) {
|
||||
Debug.LogError(textureName + " normalmap texture input can't be loaded!");
|
||||
return;
|
||||
}
|
||||
|
||||
AlloyImporterSupervisor.OnFailedImport(path);
|
||||
return;
|
||||
}
|
||||
|
||||
//If it's all good, do the importing action
|
||||
onImport(settings, texture, path);
|
||||
}
|
||||
|
||||
void ApplyImportSettings(AlloyCustomImportObject settings, Texture2D texture, string path) {
|
||||
var importer = assetImporter as TextureImporter;
|
||||
var size = settings.GetOutputSize();
|
||||
var def = settings.PackMode;
|
||||
var importSettings = def.ImportSettings;
|
||||
|
||||
importer.textureType = TextureImporterType.Default;
|
||||
importer.sRGBTexture = !importSettings.IsLinear;
|
||||
importer.filterMode = importSettings.Filter;
|
||||
importer.mipmapEnabled = true;
|
||||
|
||||
// They need the ability to set this themselves, but we should cap it.
|
||||
var nextPowerOfTwo = Mathf.NextPowerOfTwo((int) Mathf.Max(size.x, size.y));
|
||||
|
||||
if (importer.maxTextureSize > nextPowerOfTwo) {
|
||||
importer.maxTextureSize = nextPowerOfTwo;
|
||||
}
|
||||
|
||||
// Allow setting to uncompressed, else use compressed. Disallows any other format!
|
||||
if (def.ImportSettings.DefaultCompressed
|
||||
&& importer.textureCompression != TextureImporterCompression.Uncompressed
|
||||
&& importer.textureCompression != TextureImporterCompression.CompressedLQ
|
||||
&& importer.textureCompression != TextureImporterCompression.CompressedHQ) {
|
||||
importer.textureCompression = TextureImporterCompression.Compressed;
|
||||
}
|
||||
}
|
||||
|
||||
private void HandleAutoRefresh() {
|
||||
var paths = AssetDatabase.GetAllAssetPaths();
|
||||
var texGUID = AssetDatabase.AssetPathToGUID(assetPath);
|
||||
|
||||
foreach (var path in paths) {
|
||||
if (!IsAlloyPackedMapPath(path)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
var setting = AssetDatabase.LoadAssetAtPath(path, typeof (AlloyCustomImportObject)) as AlloyCustomImportObject;
|
||||
if (setting == null || (texGUID != setting.NormalGUID && !setting.TexturesGUID.Contains(texGUID))) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (setting.DoAutoRegenerate) {
|
||||
AssetDatabase.ImportAsset(path.Replace(".asset", ".png"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void OnPreprocessTexture() {
|
||||
OnAlloyImport(null, ApplyImportSettings);
|
||||
HandleAutoRefresh();
|
||||
}
|
||||
|
||||
private void OnPostprocessTexture(Texture2D texture) {
|
||||
OnAlloyImport(texture, GeneratePackedMaterialMap);
|
||||
}
|
||||
|
||||
public static void CreatePostProcessingInformation(string filePath, AlloyCustomImportObject settings) {
|
||||
settings.hideFlags = HideFlags.None;
|
||||
AssetDatabase.CreateAsset(settings, filePath);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Generates the packed material map for an object
|
||||
/// </summary>
|
||||
public static void GeneratePackedMaterialMap(AlloyCustomImportObject settings, Texture2D target, string filePath) {
|
||||
var size = settings.GetOutputSize();
|
||||
var normalMap = settings.NormalMapTexture;
|
||||
var useUnityGeneratedMipmaps = normalMap == null;
|
||||
int width = (int) size.x;
|
||||
int height = (int) size.y;
|
||||
int mipmapCount = 1;
|
||||
|
||||
// When explicitly generating mip levels pick output count based on the largest input texture.
|
||||
if (!useUnityGeneratedMipmaps) {
|
||||
mipmapCount = GetMipmapCount(normalMap);
|
||||
|
||||
for (int i = 0; i < 4; ++i) {
|
||||
if (settings.SelectedModes[i] != TextureValueChannelMode.Texture
|
||||
|| settings.GetTexture(i) == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
mipmapCount = Math.Max(mipmapCount, GetMipmapCount(settings.GetTexture(i)));
|
||||
}
|
||||
}
|
||||
|
||||
// Adjust the dimensions of the output texture if necessary.
|
||||
if (target.width != width || target.height != height) {
|
||||
target.Resize(width, height);
|
||||
}
|
||||
|
||||
if (!Mathf.IsPowerOfTwo(width) || !Mathf.IsPowerOfTwo(height)) {
|
||||
Debug.LogWarning(
|
||||
"Alloy: Texture resolution is not power of 2; will have issues generating correct mip maps if custom sizing is specified in generated texture platform settings.");
|
||||
}
|
||||
|
||||
// Get readable input textures.
|
||||
var readableNormal = AlloyTextureReader.GetReadable(normalMap, true);
|
||||
var readableTextures = new Texture2D[settings.TexturesGUID.Length];
|
||||
|
||||
for (int i = 0; i < settings.TexturesGUID.Length; ++i) {
|
||||
if (settings.SelectedModes[i] != TextureValueChannelMode.Texture) {
|
||||
continue;
|
||||
}
|
||||
|
||||
var settingsTex = settings.GetTexture(i);
|
||||
|
||||
if (settingsTex == null) {
|
||||
readableTextures[i] = null;
|
||||
} else {
|
||||
readableTextures[i] = AlloyTextureReader.GetReadable(settingsTex, false);
|
||||
}
|
||||
}
|
||||
|
||||
// Use renderer to sample mipmaps.
|
||||
try {
|
||||
var message = string.Format("Packing: \"{0}\"", settings.name);
|
||||
var progress = 1.0f;
|
||||
var bodyText = message;
|
||||
|
||||
for (int mipLevel = 0; mipLevel < mipmapCount; mipLevel++) {
|
||||
if (mipmapCount > 1) {
|
||||
progress = (float)mipLevel / (mipmapCount - 1);
|
||||
bodyText = string.Format("{0} ({1})", message, progress.ToString("0%"));
|
||||
}
|
||||
|
||||
EditorUtility.DisplayProgressBar("Building Packed maps...", bodyText, progress);
|
||||
|
||||
// CPU Method - more reliable/consistent across GPUs, but slower.
|
||||
var normalCache = new AlloyTextureColorCache(readableNormal, target);
|
||||
|
||||
UnityEngine.Profiling.Profiler.BeginSample("Read");
|
||||
var texCache = readableTextures.Select(tex => new AlloyTextureColorCache(tex, target)).ToArray();
|
||||
UnityEngine.Profiling.Profiler.EndSample();
|
||||
|
||||
AlloyPackerCompositor.CompositeMips(target, settings, texCache, normalCache, mipLevel);
|
||||
}
|
||||
} finally {
|
||||
EditorUtility.ClearProgressBar();
|
||||
}
|
||||
|
||||
// Clean up the readable textures.
|
||||
foreach (var texture in readableTextures) {
|
||||
Object.DestroyImmediate(texture);
|
||||
}
|
||||
|
||||
Object.DestroyImmediate(readableNormal);
|
||||
|
||||
// Update the texture's associated settings .asset object.
|
||||
settings.Width = width;
|
||||
settings.Height = height;
|
||||
settings.MaxResolution = 0;
|
||||
EditorUtility.SetDirty(settings);
|
||||
|
||||
// Update the texture object.
|
||||
target.Apply(useUnityGeneratedMipmaps, false);
|
||||
}
|
||||
|
||||
private static int GetMipmapCount(Texture tex) {
|
||||
int count = 1;
|
||||
var texture2D = tex as Texture2D;
|
||||
var renderTexture = tex as RenderTexture;
|
||||
var proceduralTexture = tex as ProceduralTexture;
|
||||
|
||||
if (texture2D != null) {
|
||||
count = texture2D.mipmapCount;
|
||||
} else if (renderTexture != null) {
|
||||
count = renderTexture.useMipMap ? GetMipCountFromSize(tex) : 1;
|
||||
} else if (proceduralTexture != null) {
|
||||
var mat =
|
||||
proceduralTexture.GetType()
|
||||
.GetMethod("GetProceduralMaterial", BindingFlags.Instance | BindingFlags.NonPublic)
|
||||
.Invoke(proceduralTexture, null) as ProceduralMaterial;
|
||||
var imp = AssetImporter.GetAtPath(AssetDatabase.GetAssetPath(mat)) as SubstanceImporter;
|
||||
count = imp != null && imp.GetGenerateMipMaps(mat) ? GetMipCountFromSize(tex) : 1;
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
private static int GetMipCountFromSize(Texture tex) {
|
||||
return Mathf.CeilToInt(Mathf.Log(Mathf.Max(tex.width, tex.height), 2.0f)) + 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: e111aca273d4c2b4783aa7111c7f715f
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
@@ -0,0 +1,161 @@
|
||||
// Alloy Physical Shader Framework
|
||||
// Copyright 2013-2017 RUST LLC.
|
||||
// http://www.alloy.rustltd.com/
|
||||
|
||||
using System;
|
||||
using System.IO;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Alloy
|
||||
{
|
||||
// This stores information used by the asset re-importer;
|
||||
// to rebuild Mip Maps with corrected roughness information.
|
||||
public class AlloyCustomImportObject : ScriptableObject
|
||||
{
|
||||
[HideInInspector]
|
||||
public Vector4 ChannelValues = new Vector4(0.0f, 0.0f, 0.5f, 0.0f);
|
||||
|
||||
public string[] TexturesGUID = {"", "", "", ""};
|
||||
public string NormalGUID;
|
||||
|
||||
public bool[] DoInvert = {false, false, false, false};
|
||||
|
||||
|
||||
public float VarianceBias;
|
||||
|
||||
public int Width;
|
||||
public int Height;
|
||||
|
||||
public bool DoAutoRegenerate;
|
||||
public TextureValueChannelMode[] SelectedModes = {
|
||||
TextureValueChannelMode.Texture,
|
||||
TextureValueChannelMode.Texture,
|
||||
TextureValueChannelMode.Gray,
|
||||
TextureValueChannelMode.Texture
|
||||
};
|
||||
|
||||
Texture2D[] m_textures;
|
||||
public static readonly int[] s_Resolutions = {0, 32, 64, 128, 256, 512, 1024, 2048, 4096};
|
||||
[HideInInspector] public int MaxResolution = 0;
|
||||
|
||||
|
||||
/// ///LEGACY:
|
||||
public bool IsDetailMap;
|
||||
public bool IsTerrainMap;
|
||||
/// ///
|
||||
|
||||
[SerializeField]
|
||||
PackedMapDefinition m_packMode;
|
||||
|
||||
public PackedMapDefinition PackMode {
|
||||
get {
|
||||
if (m_packMode == null) {
|
||||
var defintion = AlloyMaterialMapChannelPacker.GlobalDefinition;
|
||||
|
||||
if (IsDetailMap) {
|
||||
m_packMode = defintion.DetailPack;
|
||||
}else if (IsTerrainMap) {
|
||||
m_packMode = defintion.TerrainPack;
|
||||
} else {
|
||||
m_packMode = defintion.PackedPack;
|
||||
}
|
||||
}
|
||||
return m_packMode;
|
||||
}
|
||||
set { m_packMode = value; }
|
||||
}
|
||||
|
||||
|
||||
Texture2D m_normalTex;
|
||||
public Texture2D NormalMapTexture {
|
||||
get {
|
||||
if (m_normalTex == null) {
|
||||
m_normalTex =
|
||||
AssetDatabase.LoadAssetAtPath(AssetDatabase.GUIDToAssetPath(NormalGUID), typeof(Texture2D)) as Texture2D;
|
||||
}
|
||||
|
||||
return m_normalTex;
|
||||
}
|
||||
set {
|
||||
m_normalTex = value;
|
||||
NormalGUID = AssetDatabase.AssetPathToGUID(AssetDatabase.GetAssetPath(value));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void SetTextures(Texture2D[] textures, Texture2D normalMap) {
|
||||
m_textures = textures;
|
||||
NormalMapTexture = normalMap;
|
||||
|
||||
TexturesGUID = new string[textures.Length];
|
||||
|
||||
for (int i = 0; i < textures.Length; ++i) {
|
||||
TexturesGUID[i] = AssetDatabase.AssetPathToGUID(AssetDatabase.GetAssetPath(textures[i]));
|
||||
}
|
||||
|
||||
NormalGUID = AssetDatabase.AssetPathToGUID(AssetDatabase.GetAssetPath(normalMap));
|
||||
}
|
||||
|
||||
public Texture2D GetTexture(int index) {
|
||||
if (m_textures == null || m_textures.Length == 0) {
|
||||
m_textures = new Texture2D[4];
|
||||
}
|
||||
|
||||
if (m_textures[index] == null) {
|
||||
m_textures[index] =
|
||||
AssetDatabase.LoadAssetAtPath(AssetDatabase.GUIDToAssetPath(TexturesGUID[index]), typeof (Texture2D)) as Texture2D;
|
||||
}
|
||||
|
||||
return m_textures[index];
|
||||
}
|
||||
|
||||
public const int DefaultOutputWidth = 32,
|
||||
DefaultOutputHeight = 32,
|
||||
DefaultOutputMipmapCount = 1;
|
||||
|
||||
public Vector2 GetOutputSize() {
|
||||
int width = DefaultOutputWidth;
|
||||
int height = DefaultOutputHeight;
|
||||
|
||||
// Pick output texture dimensions based on the largest input texture.
|
||||
for (int i = 0; i < 4; ++i) {
|
||||
var texture = GetTexture(i);
|
||||
|
||||
if (SelectedModes[i] == TextureValueChannelMode.Texture && texture != null) {
|
||||
// So we can accomodate rectangles, if need be.
|
||||
width = Math.Max(width, texture.width);
|
||||
height = Math.Max(height, texture.height);
|
||||
}
|
||||
}
|
||||
|
||||
if (NormalMapTexture != null) {
|
||||
width = Math.Max(width, NormalMapTexture.width);
|
||||
height = Math.Max(height, NormalMapTexture.height);
|
||||
}
|
||||
|
||||
return new Vector2(width, height);
|
||||
}
|
||||
|
||||
public void GenerateMap() {
|
||||
string path = AssetDatabase.GetAssetPath(this).Replace(".asset", ".png");
|
||||
|
||||
var tempTex = new Texture2D(4, 4, TextureFormat.ARGB32, true);
|
||||
AssetDatabase.DeleteAsset(path);
|
||||
File.WriteAllBytes(path, tempTex.EncodeToPNG());
|
||||
AssetDatabase.Refresh(ImportAssetOptions.ForceSynchronousImport);
|
||||
}
|
||||
|
||||
public void SetTexture(Texture2D selTex, int texIndex) {
|
||||
TexturesGUID[texIndex] = AssetDatabase.AssetPathToGUID(AssetDatabase.GetAssetPath(selTex));
|
||||
m_textures[texIndex] = selTex;
|
||||
}
|
||||
|
||||
public void ClearCache() {
|
||||
m_textures[0] = null;
|
||||
m_textures[1] = null;
|
||||
m_textures[2] = null;
|
||||
m_textures[3] = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 3b158258a30cea746ad413697b1d071b
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
@@ -0,0 +1,40 @@
|
||||
// Alloy Physical Shader Framework
|
||||
// Copyright 2013-2017 RUST LLC.
|
||||
// http://www.alloy.rustltd.com/
|
||||
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Alloy
|
||||
{
|
||||
[CustomEditor(typeof(AlloyCustomImportObject))]
|
||||
public class AlloyCustomImportObjectEditor : Editor
|
||||
{
|
||||
private AlloyMaterialMapChannelPacker m_packer;
|
||||
|
||||
private Vector2 m_scrollPos;
|
||||
|
||||
void OnEnable() {
|
||||
m_packer = CreateInstance<AlloyMaterialMapChannelPacker>();
|
||||
m_packer.hideFlags = HideFlags.HideAndDontSave;
|
||||
|
||||
m_packer.Target = target as AlloyCustomImportObject;
|
||||
}
|
||||
|
||||
void OnDisable() {
|
||||
DestroyImmediate(m_packer);
|
||||
}
|
||||
|
||||
public override void OnInspectorGUI() {
|
||||
m_scrollPos = GUILayout.BeginScrollView(m_scrollPos);
|
||||
bool isValid = m_packer.BaseGUI();
|
||||
bool isButtonClicked = m_packer.GenerateButtonGUI("Regenerate", isValid);
|
||||
|
||||
GUILayout.EndScrollView();
|
||||
|
||||
if (isButtonClicked) {
|
||||
m_packer.Target.GenerateMap();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+8
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: a625ab56dacfde649b3eb51e51a49a52
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
@@ -0,0 +1,83 @@
|
||||
// Alloy Physical Shader Framework
|
||||
// Copyright 2013-2017 RUST LLC.
|
||||
// http://www.alloy.rustltd.com/
|
||||
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using UnityEditor;
|
||||
|
||||
namespace Alloy
|
||||
{
|
||||
public class AlloyImportFloat : ScriptableObject {}
|
||||
|
||||
[InitializeOnLoad]
|
||||
public static class AlloyImporterSupervisor
|
||||
{
|
||||
private static List<string> s_failedImportAttempts = new List<string>();
|
||||
|
||||
public static bool IsFinalTry;
|
||||
private static AlloyImportFloat m_float;
|
||||
|
||||
public static void OnFailedImport(string path) {
|
||||
if (!s_failedImportAttempts.Contains(path)) {
|
||||
s_failedImportAttempts.Add(path);
|
||||
}
|
||||
}
|
||||
|
||||
static AlloyImporterSupervisor() {
|
||||
var all = Resources.FindObjectsOfTypeAll<AlloyImportFloat>();
|
||||
|
||||
if (all.Length == 0) {
|
||||
m_float = ScriptableObject.CreateInstance<AlloyImportFloat>();
|
||||
m_float.hideFlags = HideFlags.HideAndDontSave;
|
||||
|
||||
ScanForLateImport();
|
||||
} else {
|
||||
m_float = all[0];
|
||||
}
|
||||
|
||||
EditorApplication.update += Update;
|
||||
}
|
||||
|
||||
private static void ScanForLateImport() {
|
||||
var assets = AssetDatabase.FindAssets("t:AlloyCustomImportObject");
|
||||
|
||||
|
||||
foreach (var asset in assets) {
|
||||
var path = AssetDatabase.GUIDToAssetPath(asset);
|
||||
var png = path.Replace(".asset", ".png");
|
||||
var tex = AssetDatabase.LoadAssetAtPath<Texture2D>(png);
|
||||
|
||||
if (tex == null) {
|
||||
AssetDatabase.ImportAsset(path);
|
||||
} else {
|
||||
if (tex.width == 4 && tex.height == 4) {
|
||||
AssetDatabase.ImportAsset(png);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Update is called once per frame
|
||||
private static void Update() {
|
||||
if (s_failedImportAttempts.Count == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
var failed = s_failedImportAttempts.ToArray();
|
||||
foreach (var path in failed) {
|
||||
|
||||
var settings = AssetDatabase.LoadAssetAtPath(path, typeof (AlloyCustomImportObject)) as AlloyCustomImportObject;
|
||||
if (settings == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
IsFinalTry = true;
|
||||
settings.GenerateMap();
|
||||
IsFinalTry = false;
|
||||
|
||||
s_failedImportAttempts.Remove(path);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: ea64fb811f5753944b3b1fa1735e0f23
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
+537
@@ -0,0 +1,537 @@
|
||||
// Alloy Physical Shader Framework
|
||||
// Copyright 2013-2017 RUST LLC.
|
||||
// http://www.alloy.rustltd.com/
|
||||
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
using Alloy;
|
||||
using Object = UnityEngine.Object;
|
||||
|
||||
public class AlloyMaterialMapChannelPacker : EditorWindow {
|
||||
protected const string SelectTextureOrValueErrorMessage = "Please select a texture or a value.";
|
||||
protected const string EnterFilenameErrorMessage = "Please enter a filename.";
|
||||
|
||||
private const string c_assetPathRoot = "Assets";
|
||||
private const string c_defaultFilename = "Output";
|
||||
|
||||
protected Vector2 ScrollPosition = new Vector2(0, 0);
|
||||
|
||||
[SerializeField]
|
||||
protected string SaveName = string.Empty;
|
||||
|
||||
private static Texture2D s_rectTexture;
|
||||
private static GUIStyle s_staticRectStyle;
|
||||
|
||||
private void OnEnable() {
|
||||
SaveName = GetSelectedOrDefaultFilename();
|
||||
Undo.undoRedoPerformed += UndoRedoPerformed;
|
||||
|
||||
}
|
||||
|
||||
private void OnSelectionChange() {
|
||||
Repaint();
|
||||
SaveName = GetSelectedOrDefaultFilename();
|
||||
}
|
||||
|
||||
protected string GetSelectedAssetPath() {
|
||||
var path = c_assetPathRoot;
|
||||
|
||||
foreach (Object obj in Selection.GetFiltered(typeof(Object), SelectionMode.Assets)) {
|
||||
path = AssetDatabase.GetAssetPath(obj);
|
||||
|
||||
if (File.Exists(path)) {
|
||||
path = Path.GetDirectoryName(path);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
return path;
|
||||
}
|
||||
|
||||
protected string GetSelectedOrDefaultFilename() {
|
||||
string fileName;
|
||||
|
||||
var path = AssetDatabase.GetAssetPath(Selection.activeObject);
|
||||
|
||||
if (string.IsNullOrEmpty(path) || !Path.HasExtension(path)) {
|
||||
fileName = c_defaultFilename;
|
||||
} else {
|
||||
fileName = Path.GetFileNameWithoutExtension(path);
|
||||
}
|
||||
|
||||
return fileName;
|
||||
}
|
||||
|
||||
protected void TitleLabel(string text) {
|
||||
GUILayout.Label(text, EditorStyles.boldLabel, GUILayout.Width(150.0f));
|
||||
}
|
||||
|
||||
protected void HelpLabel(string text) {
|
||||
GUI.color = EditorGUIUtility.isProSkin ? Color.gray : Color.black;
|
||||
var wrappedWhiteLabel = new GUIStyle(EditorStyles.whiteLabel);
|
||||
wrappedWhiteLabel.wordWrap = true;
|
||||
GUILayout.Label(text, wrappedWhiteLabel);
|
||||
}
|
||||
|
||||
// Note that this function is only meant to be called from OnGUI() functions.
|
||||
public static void GUIDrawRect(Rect position, Color color) {
|
||||
if (s_rectTexture == null) {
|
||||
// Use this format so that input colors are treated as though they
|
||||
// are in gamma-space.
|
||||
s_rectTexture = new Texture2D(1, 1, TextureFormat.RGB24, false, true);
|
||||
}
|
||||
|
||||
if (s_staticRectStyle == null) {
|
||||
s_staticRectStyle = new GUIStyle();
|
||||
}
|
||||
|
||||
s_rectTexture.SetPixel(0, 0, color);
|
||||
|
||||
s_rectTexture.Apply();
|
||||
s_staticRectStyle.normal.background = s_rectTexture;
|
||||
|
||||
GUI.Box(position, GUIContent.none, s_staticRectStyle);
|
||||
}
|
||||
|
||||
protected bool FileEntryGUI(string suffix, string extension, ref string filename, out string curPath) {
|
||||
curPath = GetSelectedAssetPath();
|
||||
var displayPath = curPath + "/";
|
||||
|
||||
if (filename.Contains(suffix)) {
|
||||
int fileExtPos = filename.LastIndexOf(suffix, StringComparison.Ordinal);
|
||||
|
||||
if (fileExtPos >= 0) {
|
||||
filename = filename.Substring(0, fileExtPos);
|
||||
}
|
||||
}
|
||||
|
||||
displayPath = displayPath.Remove(0, 7);
|
||||
var dirs = displayPath.Split('/');
|
||||
var dirsCount = dirs.Length - 4;
|
||||
|
||||
for (int i = 0; i < dirsCount; i++) {
|
||||
dirs[i] = "..";
|
||||
}
|
||||
|
||||
displayPath = string.Join("/", dirs);
|
||||
|
||||
// Output filename section.
|
||||
using (new EditorGUILayout.VerticalScope()) {
|
||||
using (new EditorGUILayout.HorizontalScope()) {
|
||||
Color defaultContentColor = GUI.contentColor;
|
||||
GUI.contentColor = EditorGUIUtility.isProSkin ? Color.yellow : Color.black;
|
||||
GUILayout.Label(displayPath, EditorStyles.whiteLabel);
|
||||
GUI.contentColor = defaultContentColor;
|
||||
|
||||
GUILayout.Space(10.0f);
|
||||
SaveName = GUILayout.TextField(filename, GUILayout.Width(180.0f));
|
||||
GUILayout.Label(suffix + extension);
|
||||
GUILayout.FlexibleSpace();
|
||||
}
|
||||
}
|
||||
|
||||
GUILayout.Space(5.0f);
|
||||
|
||||
// Warning message.
|
||||
bool isValid = true;
|
||||
|
||||
using (new EditorGUILayout.HorizontalScope()) {
|
||||
if (string.IsNullOrEmpty(filename)) {
|
||||
EditorGUILayout.HelpBox(EnterFilenameErrorMessage, MessageType.Warning);
|
||||
isValid = false;
|
||||
}
|
||||
|
||||
if (filename.Contains("/") || filename.Contains("\\") || filename.Contains(".")) {
|
||||
EditorGUILayout.HelpBox("Name is not valid!", MessageType.Warning);
|
||||
isValid = false;
|
||||
}
|
||||
|
||||
GUILayout.FlexibleSpace();
|
||||
}
|
||||
|
||||
return isValid;
|
||||
}
|
||||
|
||||
[SerializeField] public AlloyCustomImportObject Target;
|
||||
static MaterialMapChannelPackerDefinition s_definition;
|
||||
|
||||
public static MaterialMapChannelPackerDefinition GlobalDefinition {
|
||||
get {
|
||||
if (s_definition == null) {
|
||||
string path = "Assets/Alloy/Scripts/MaterialMapChannelPacker/Config/_PackerDefinition.asset";
|
||||
s_definition =
|
||||
AssetDatabase.LoadAssetAtPath(path, typeof (MaterialMapChannelPackerDefinition)) as
|
||||
MaterialMapChannelPackerDefinition;
|
||||
}
|
||||
|
||||
return s_definition;
|
||||
}
|
||||
}
|
||||
|
||||
private const int c_editorMinWidth = 236;
|
||||
|
||||
[MenuItem(AlloyUtils.MenuItem + "Material Map Channel Packer", false, 0)]
|
||||
private static void LoadWindow() {
|
||||
var all = Resources.FindObjectsOfTypeAll<AlloyMaterialMapChannelPacker>();
|
||||
|
||||
foreach (var channelPacker in all) {
|
||||
DestroyImmediate(channelPacker);
|
||||
}
|
||||
|
||||
GetWindow<AlloyMaterialMapChannelPacker>(false, "Material Map");
|
||||
}
|
||||
|
||||
|
||||
private void UndoRedoPerformed() {
|
||||
Target.ClearCache();
|
||||
Repaint();
|
||||
}
|
||||
|
||||
private void OnDisable() {
|
||||
if (Target != null && !EditorUtility.IsPersistent(Target)) {
|
||||
DestroyImmediate(Target);
|
||||
}
|
||||
|
||||
Undo.undoRedoPerformed -= UndoRedoPerformed;
|
||||
}
|
||||
|
||||
|
||||
void OnGUI() {
|
||||
if (Target == null) {
|
||||
Target = CreateInstance<AlloyCustomImportObject>();
|
||||
UpdateDefaults();
|
||||
}
|
||||
|
||||
var definition = GlobalDefinition;
|
||||
|
||||
|
||||
if (definition == null) {
|
||||
EditorGUILayout.HelpBox("Error: Cannot find packed map defintion file. Please ask for support on the forum", MessageType.Error);
|
||||
return;
|
||||
}
|
||||
|
||||
ScrollPosition = EditorGUILayout.BeginScrollView(ScrollPosition, false, false,
|
||||
GUILayout.MinWidth(c_editorMinWidth),
|
||||
GUILayout.MaxWidth(position.width));
|
||||
|
||||
GUILayout.Space(10.0f);
|
||||
var def = Target.PackMode;
|
||||
|
||||
// Pack mode tabs.
|
||||
using (new EditorGUILayout.HorizontalScope()) {
|
||||
foreach (var tabMode in definition.PackedMaps) {
|
||||
EditorGUI.BeginChangeCheck();
|
||||
bool toggle = GUILayout.Toggle(def == tabMode, tabMode.Title, EditorStyles.toolbarButton);
|
||||
|
||||
if (EditorGUI.EndChangeCheck()) {
|
||||
if (toggle && def != tabMode) {
|
||||
Target.PackMode = tabMode; // Update packed map definition.
|
||||
UpdateDefaults();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
string curPath;
|
||||
var suffix = Target.PackMode.Suffix;
|
||||
bool isValid = true;
|
||||
|
||||
isValid = BaseGUI();
|
||||
isValid = FileEntryGUI(suffix, ".png", ref SaveName, out curPath) && isValid;
|
||||
|
||||
if (GenerateButtonGUI("Generate", isValid)) {
|
||||
var path = curPath + "/" + SaveName;
|
||||
|
||||
path += suffix;
|
||||
Target = Instantiate(Target);
|
||||
AlloyCustomImportAction.CreatePostProcessingInformation(path + ".asset", Target);
|
||||
}
|
||||
|
||||
EditorGUILayout.EndScrollView();
|
||||
}
|
||||
|
||||
private void UpdateDefaults() {
|
||||
var channels = Target.PackMode.Channels;
|
||||
|
||||
foreach (var channel in channels) {
|
||||
var outIndices = channel.OutputIndices.ToArray();
|
||||
|
||||
foreach (var outIndex in outIndices) {
|
||||
Target.DoInvert[outIndex] = channel.InvertByDefault;
|
||||
Target.SelectedModes[outIndex] = channel.DefaultMode;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool DrawPackedMapDefinition(PackedMapDefinition def) {
|
||||
var definition = GlobalDefinition;
|
||||
|
||||
if (definition == null) {
|
||||
EditorGUILayout.HelpBox("Error: Cannot find packed map defintion file. Please ask for support on the forum", MessageType.Error);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool anyNrm = false;
|
||||
bool isValid = true;
|
||||
|
||||
foreach (var channel in def.Channels) {
|
||||
if (!(channel.OutputVariance || channel.HideChannel)) {
|
||||
isValid = DrawChannel(channel, false) && isValid;
|
||||
}
|
||||
|
||||
if (channel.UseNormals) {
|
||||
anyNrm = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (anyNrm) {
|
||||
isValid = DrawChannel(definition.NRMChannel, true) && isValid;
|
||||
}
|
||||
|
||||
using (new EditorGUILayout.VerticalScope("HelpBox")) {
|
||||
TitleLabel("Auto Regenerate");
|
||||
|
||||
using (new EditorGUILayout.HorizontalScope()) {
|
||||
HelpLabel(definition.AutoRegenerateText);
|
||||
GUI.color = Color.white;
|
||||
GUILayout.FlexibleSpace();
|
||||
Target.DoAutoRegenerate = EditorGUILayout.Toggle("", Target.DoAutoRegenerate, GUILayout.Width(120.0f));
|
||||
}
|
||||
|
||||
// Does anyone really use this?
|
||||
//if (def.Channels.Any(c => c.UseNormals) && def.VarianceBias) {
|
||||
// TitleLabel("Variance Bias");
|
||||
|
||||
// using (new EditorGUILayout.HorizontalScope()) {
|
||||
// HelpLabel(GlobalDefinition.VarianceText);
|
||||
// GUI.color = Color.white;
|
||||
// GUILayout.FlexibleSpace();
|
||||
|
||||
// Target.VarianceBias = EditorGUILayout.Slider(Target.VarianceBias, 0.0f, 1.0f, GUILayout.Width(120.0f));
|
||||
// }
|
||||
//}
|
||||
}
|
||||
|
||||
return isValid;
|
||||
}
|
||||
|
||||
private bool DrawChannel(BaseTextureChannelMapping def, bool normal) {
|
||||
bool isValid = true;
|
||||
|
||||
GUI.backgroundColor = def.BackgroundColor;
|
||||
|
||||
using (new EditorGUILayout.VerticalScope("HelpBox")) {
|
||||
GUI.backgroundColor = Color.white;
|
||||
|
||||
using (new EditorGUILayout.HorizontalScope()) {
|
||||
var map = def as MapTextureChannelMapping;
|
||||
|
||||
using (new EditorGUILayout.VerticalScope()) {
|
||||
using (new EditorGUILayout.HorizontalScope()) {
|
||||
TitleLabel(def.Title);
|
||||
|
||||
if (map != null) {
|
||||
string inChannel = map.InputString;
|
||||
string outChannel = map.OutputString;
|
||||
|
||||
HelpLabel("(" + inChannel + " → " + outChannel + ")");
|
||||
}
|
||||
}
|
||||
HelpLabel(def.HelpText);
|
||||
|
||||
GUI.color = Color.white;
|
||||
|
||||
if (normal) {
|
||||
Texture2D normalMap = Target.NormalMapTexture;
|
||||
|
||||
if (normalMap != null) {
|
||||
string path = AssetDatabase.GetAssetPath(normalMap);
|
||||
|
||||
if (!string.IsNullOrEmpty(path)) {
|
||||
TextureImporter importer = AssetImporter.GetAtPath(path) as TextureImporter;
|
||||
|
||||
if (!importer.mipmapEnabled || importer.textureType != TextureImporterType.NormalMap) {
|
||||
isValid = false;
|
||||
EditorGUILayout.HelpBox("Texture type must be \"Normal map\" with mipmaps.", MessageType.Error);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (map != null
|
||||
&& (Target.SelectedModes[map.MainIndex] == TextureValueChannelMode.Texture)
|
||||
&& Target.GetTexture(map.MainIndex) == null) {
|
||||
isValid = false;
|
||||
EditorGUILayout.HelpBox(SelectTextureOrValueErrorMessage, MessageType.Warning);
|
||||
}
|
||||
}
|
||||
|
||||
GUILayout.FlexibleSpace();
|
||||
|
||||
if (normal) {
|
||||
Target.NormalMapTexture =
|
||||
EditorGUILayout.ObjectField(Target.NormalMapTexture, typeof (Texture2D), false, GUILayout.Width(70.0f),
|
||||
GUILayout.Height(70.0f))
|
||||
as Texture2D;
|
||||
} else if (map != null) {
|
||||
int texIndex = map.MainIndex;
|
||||
|
||||
var mode = Target.SelectedModes[texIndex];
|
||||
int index = (int) mode;
|
||||
GUILayout.BeginVertical();
|
||||
|
||||
bool ch1 = GUILayout.Toggle(index == 0, "Black", EditorStyles.toolbarButton);
|
||||
bool ch2 = GUILayout.Toggle(index == 1, "Gray", EditorStyles.toolbarButton);
|
||||
bool ch3 = GUILayout.Toggle(index == 2, "White", EditorStyles.toolbarButton);
|
||||
bool ch4 = GUILayout.Toggle(index == 3, "Custom", EditorStyles.toolbarButton);
|
||||
bool ch5 = GUILayout.Toggle(index == 4, "Texture", EditorStyles.toolbarButton);
|
||||
|
||||
float channelValue = 0.0f;
|
||||
|
||||
if (ch1 && index != 0) {
|
||||
index = 0;
|
||||
} else if (ch2 && index != 1) {
|
||||
index = 1;
|
||||
} else if (ch3 && index != 2) {
|
||||
index = 2;
|
||||
} else if (ch4 && index != 3) {
|
||||
index = 3;
|
||||
} else if (ch5 && index != 4) {
|
||||
index = 4;
|
||||
}
|
||||
|
||||
GUILayout.EndVertical();
|
||||
|
||||
var selTex = Target.GetTexture((int) texIndex);
|
||||
|
||||
if (mode != TextureValueChannelMode.Texture) {
|
||||
selTex = null;
|
||||
}
|
||||
|
||||
GUILayout.Space(10.0f);
|
||||
// Color or texture picker.
|
||||
switch (mode) {
|
||||
case TextureValueChannelMode.Texture:
|
||||
using (new EditorGUILayout.VerticalScope()) {
|
||||
selTex =
|
||||
EditorGUILayout.ObjectField(selTex, typeof (Texture2D), false, GUILayout.Width(70.0f), GUILayout.Height(70.0f))
|
||||
as Texture2D;
|
||||
|
||||
if (map.CanInvert) {
|
||||
float label = EditorGUIUtility.labelWidth;
|
||||
EditorGUIUtility.labelWidth = 60.0f;
|
||||
Target.DoInvert[texIndex] = EditorGUILayout.Toggle("Invert", Target.DoInvert[texIndex], GUILayout.Width(70.0f));
|
||||
EditorGUIUtility.labelWidth = label;
|
||||
}
|
||||
}
|
||||
|
||||
Target.SetTexture(selTex, texIndex);
|
||||
|
||||
foreach (var mapIndex in map.OutputIndices) {
|
||||
Target.SetTexture(selTex, mapIndex);
|
||||
Target.DoInvert[mapIndex] = Target.DoInvert[texIndex];
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
case TextureValueChannelMode.Black:
|
||||
channelValue = 0.0f;
|
||||
DrawColorBox(Color.black);
|
||||
break;
|
||||
case TextureValueChannelMode.Gray:
|
||||
channelValue = 0.5f;
|
||||
DrawColorBox(Color.gray);
|
||||
break;
|
||||
case TextureValueChannelMode.White:
|
||||
channelValue = 1.0f;
|
||||
DrawColorBox(Color.white);
|
||||
break;
|
||||
|
||||
case TextureValueChannelMode.Custom:
|
||||
channelValue = Target.ChannelValues[(int) texIndex];
|
||||
EditorGUILayout.BeginVertical();
|
||||
channelValue = Mathf.Clamp01(channelValue);
|
||||
channelValue = EditorGUILayout.FloatField(channelValue,
|
||||
GUILayout.Width(50.0f));
|
||||
|
||||
DrawColorBox(new Color(channelValue, channelValue, channelValue));
|
||||
EditorGUILayout.EndVertical();
|
||||
break;
|
||||
}
|
||||
|
||||
if (mode != TextureValueChannelMode.Texture) {
|
||||
foreach (var mapIndex in map.OutputIndices) {
|
||||
Target.DoInvert[mapIndex] = false;
|
||||
}
|
||||
}
|
||||
|
||||
Target.ChannelValues[texIndex] = channelValue;
|
||||
Target.SelectedModes[texIndex] = (TextureValueChannelMode) index;
|
||||
|
||||
foreach (var mapIndex in map.OutputIndices) {
|
||||
Target.ChannelValues[mapIndex] = channelValue;
|
||||
Target.SelectedModes[mapIndex] = (TextureValueChannelMode) index;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
GUILayout.Space(10.0f);
|
||||
}
|
||||
|
||||
return isValid;
|
||||
}
|
||||
|
||||
private static void DrawColorBox(Color col) {
|
||||
var rect = GUILayoutUtility.GetRect(74.0f, 74.0f);
|
||||
var borderColor = new Color {
|
||||
r = (col.r + 0.2f) / 2.0f,
|
||||
g = (col.g + 0.2f) / 2.0f,
|
||||
b = (col.b + 0.2f) / 2.0f,
|
||||
a = 1.0f
|
||||
};
|
||||
|
||||
GUIDrawRect(rect, borderColor);
|
||||
|
||||
rect.x += 2.0f;
|
||||
rect.width -= 4.0f;
|
||||
rect.y += 2.0f;
|
||||
rect.height -= 4.0f;
|
||||
|
||||
GUIDrawRect(rect, col);
|
||||
}
|
||||
|
||||
public bool BaseGUI() {
|
||||
EditorGUI.BeginChangeCheck();
|
||||
Undo.RecordObject(Target, "Packed map");
|
||||
|
||||
bool isValid = DrawPackedMapDefinition(Target.PackMode);
|
||||
|
||||
if (EditorGUI.EndChangeCheck()) {
|
||||
EditorUtility.SetDirty(Target);
|
||||
}
|
||||
|
||||
return isValid;
|
||||
}
|
||||
|
||||
public bool GenerateButtonGUI(string text, bool enabled)
|
||||
{
|
||||
bool isButtonClicked;
|
||||
|
||||
GUI.enabled = enabled;
|
||||
|
||||
using (new EditorGUILayout.HorizontalScope())
|
||||
{
|
||||
GUILayout.FlexibleSpace();
|
||||
isButtonClicked = GUILayout.Button(text, EditorStyles.toolbarButton, GUILayout.Width(120.0f),
|
||||
GUILayout.Height(70.0f));
|
||||
GUILayout.FlexibleSpace();
|
||||
}
|
||||
|
||||
GUI.enabled = true;
|
||||
GUILayout.Space(5.0f);
|
||||
|
||||
return isButtonClicked;
|
||||
}
|
||||
}
|
||||
+8
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: bdefa218d1369324ca83faefe3c27067
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
@@ -0,0 +1,294 @@
|
||||
// Alloy Physical Shader Framework
|
||||
// Copyright 2013-2017 RUST LLC.
|
||||
// http://www.alloy.rustltd.com/
|
||||
using System.Linq;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Alloy {
|
||||
public struct AlloyTextureColorCache {
|
||||
public bool NativeSize;
|
||||
public bool EmptyTexture;
|
||||
|
||||
|
||||
public Color[] Values;
|
||||
public float[] ValueChannelR;
|
||||
public float[] ValueChannelG;
|
||||
public float[] ValueChannelB;
|
||||
public float[] ValueChannelA;
|
||||
|
||||
public float[] ActiveChannel;
|
||||
|
||||
private int m_texWidth;
|
||||
private int m_texHeight;
|
||||
|
||||
public AlloyTextureColorCache(Texture2D texture, Texture2D target) {
|
||||
if (texture == null) {
|
||||
EmptyTexture = true;
|
||||
m_texWidth = 0;
|
||||
m_texHeight = 0;
|
||||
Values = null;
|
||||
ValueChannelR = null;
|
||||
ValueChannelG = null;
|
||||
ValueChannelB = null;
|
||||
ValueChannelA = null;
|
||||
NativeSize = false;
|
||||
}
|
||||
else {
|
||||
Values = texture.GetPixels();
|
||||
m_texWidth = texture.width;
|
||||
m_texHeight = texture.height;
|
||||
EmptyTexture = false;
|
||||
NativeSize = texture.width == target.width && texture.height == target.height;
|
||||
|
||||
|
||||
ValueChannelR = new float[Values.Length];
|
||||
ValueChannelG = new float[Values.Length];
|
||||
ValueChannelB = new float[Values.Length];
|
||||
ValueChannelA = new float[Values.Length];
|
||||
|
||||
for (int i = 0; i < Values.Length; ++i) {
|
||||
ValueChannelR[i] = Values[i].r;
|
||||
ValueChannelG[i] = Values[i].g;
|
||||
ValueChannelB[i] = Values[i].b;
|
||||
ValueChannelA[i] = Values[i].a;
|
||||
}
|
||||
}
|
||||
|
||||
ActiveChannel = null;
|
||||
}
|
||||
|
||||
|
||||
public void SetActiveChannel(int channel) {
|
||||
switch (channel) {
|
||||
case 0:
|
||||
ActiveChannel = ValueChannelR;
|
||||
break;
|
||||
|
||||
case 1:
|
||||
ActiveChannel = ValueChannelG;
|
||||
break;
|
||||
|
||||
case 2:
|
||||
ActiveChannel = ValueChannelB;
|
||||
break;
|
||||
|
||||
case 3:
|
||||
ActiveChannel = ValueChannelA;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public float GetChannelBilinear(float u, float v, int mipLevel, float rangeX, float rangeY) {
|
||||
|
||||
if (mipLevel == 0) {
|
||||
u = Mathf.Clamp01(u);
|
||||
v = Mathf.Clamp01(v);
|
||||
|
||||
float uScaled = u * (m_texWidth - 1);
|
||||
float vScaled = v * (m_texHeight - 1);
|
||||
|
||||
int left = Mathf.FloorToInt(uScaled);
|
||||
int bottom = Mathf.FloorToInt(vScaled);
|
||||
|
||||
int right = Mathf.CeilToInt(uScaled);
|
||||
int top = Mathf.CeilToInt(vScaled);
|
||||
|
||||
float lbVal = ActiveChannel[left + bottom * m_texWidth];
|
||||
float rbVal = ActiveChannel[right + bottom * m_texWidth];
|
||||
|
||||
float luVal = ActiveChannel[left + top * m_texWidth];
|
||||
float ruVal = ActiveChannel[right + top * m_texWidth];
|
||||
|
||||
float uFrac = uScaled - Mathf.Floor(uScaled);
|
||||
float vFrac = vScaled - Mathf.Floor(vScaled);
|
||||
|
||||
float lrBottom = Mathf.LerpUnclamped(lbVal, rbVal, uFrac);
|
||||
float lrUp = Mathf.LerpUnclamped(luVal, ruVal, uFrac);
|
||||
|
||||
return Mathf.Lerp(lrBottom, lrUp, vFrac);
|
||||
}
|
||||
|
||||
float value = 0.0f;
|
||||
// Averages the result over the area within the 'pixel' for this mip level
|
||||
// this is similar, but not quite exactly the same as trilinear filtering.
|
||||
for (int i = -mipLevel; i < mipLevel; ++i) {
|
||||
for (int j = -mipLevel; j < mipLevel; ++j) {
|
||||
float um = u + (i * rangeX);
|
||||
float vm = v - (j * rangeY);
|
||||
value += GetChannelBilinear(um, vm, 0, rangeX, rangeY);
|
||||
}
|
||||
}
|
||||
int t = mipLevel * 2;
|
||||
value /= t * t;
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
public Vector3 GetPixelNormal(float u, float v, int mipLevel, float rangeX, float rangeY) {
|
||||
if (mipLevel == 0) {
|
||||
u = Mathf.Clamp01(u);
|
||||
v = Mathf.Clamp01(v);
|
||||
|
||||
float uScaled = u * (m_texWidth - 1);
|
||||
float vScaled = v * (m_texHeight - 1);
|
||||
|
||||
int left = Mathf.FloorToInt(uScaled);
|
||||
int bottom = Mathf.FloorToInt(vScaled);
|
||||
|
||||
int right = Mathf.CeilToInt(uScaled);
|
||||
int top = Mathf.CeilToInt(vScaled);
|
||||
|
||||
Color lbVal = Values[left + bottom * m_texWidth];
|
||||
Color rbVal = Values[right + bottom * m_texWidth];
|
||||
|
||||
Color luVal = Values[left + top * m_texWidth];
|
||||
Color ruVal = Values[right + top * m_texWidth];
|
||||
|
||||
float uFrac = uScaled - Mathf.Floor(uScaled);
|
||||
float vFrac = vScaled - Mathf.Floor(vScaled);
|
||||
|
||||
float rLerp = Mathf.LerpUnclamped(Mathf.LerpUnclamped(lbVal.r, rbVal.r, uFrac), Mathf.LerpUnclamped(luVal.r, ruVal.r, uFrac), vFrac);
|
||||
float gLerp = Mathf.LerpUnclamped(Mathf.LerpUnclamped(lbVal.g, rbVal.g, uFrac), Mathf.LerpUnclamped(luVal.g, ruVal.g, uFrac), vFrac);
|
||||
float bLerp = Mathf.LerpUnclamped(Mathf.LerpUnclamped(lbVal.b, rbVal.b, uFrac), Mathf.LerpUnclamped(luVal.b, ruVal.b, uFrac), vFrac);
|
||||
|
||||
return new Vector3(rLerp, gLerp, bLerp);
|
||||
}
|
||||
|
||||
Vector3 value = Vector3.zero;
|
||||
// Averages the result over the area within the 'pixel' for this mip level
|
||||
// this is similar, but not quite exactly the same as trilinear filtering.
|
||||
for (int i = -mipLevel; i < mipLevel; ++i) {
|
||||
for (int j = -mipLevel; j < mipLevel; ++j) {
|
||||
float um = u + (i * rangeX);
|
||||
float vm = v - (j * rangeY);
|
||||
value += GetPixelNormal(um, vm, 0, rangeX, rangeY);
|
||||
}
|
||||
}
|
||||
|
||||
int t = mipLevel * 2;
|
||||
value /= t * t;
|
||||
|
||||
return value;
|
||||
}
|
||||
}
|
||||
|
||||
public static class AlloyPackerCompositor {
|
||||
public static void CompositeMips(Texture2D target, AlloyCustomImportObject source,
|
||||
AlloyTextureColorCache[] mapCache, AlloyTextureColorCache normalCache, int mipLevel) {
|
||||
|
||||
|
||||
// Basically a 1:1 port of the original shader
|
||||
// The only point of major difference is the filtering method used; which is a fraction simpler.
|
||||
|
||||
// This was disabled, since it appears GetPixels results don't appear to be affected by Unity's messing with Linear inputs; the same way they do at runtime. Re-enable if you like.
|
||||
|
||||
int w = Mathf.Max(2, target.width >> mipLevel);
|
||||
int h = Mathf.Max(2, target.height >> mipLevel);
|
||||
|
||||
var colors = new Color[w * h];
|
||||
|
||||
|
||||
float rangeX = (1.0f / (mipLevel + 1)) / target.width;
|
||||
float rangeY = (1.0f / (mipLevel + 1)) / target.height;
|
||||
|
||||
UnityEngine.Profiling.Profiler.BeginSample("Composite mips");
|
||||
for (int channelIndex = 0; channelIndex < source.PackMode.Channels.Count; channelIndex++) {
|
||||
var channel = source.PackMode.Channels[channelIndex];
|
||||
var inIndices = channel.InputIndices.ToArray();
|
||||
var outIndices = channel.OutputIndices.ToArray();
|
||||
bool hasInputs = inIndices.Length > 0;
|
||||
|
||||
for (int i = 0; i < outIndices.Length; ++i) {
|
||||
int storeIndex = outIndices[i];
|
||||
var tex = mapCache[storeIndex];
|
||||
var channelVal = source.ChannelValues[storeIndex];
|
||||
|
||||
if (hasInputs) {
|
||||
int readIndex = inIndices[Mathf.Min(i, inIndices.Length - 1)];
|
||||
|
||||
tex.SetActiveChannel(readIndex);
|
||||
}
|
||||
|
||||
bool doInvert = source.DoInvert[storeIndex];
|
||||
bool doNormal = channel.UseNormals && !normalCache.EmptyTexture;
|
||||
bool doNative = hasInputs && tex.NativeSize && mipLevel == 0;
|
||||
|
||||
UnityEngine.Profiling.Profiler.BeginSample("Blit");
|
||||
for (int x = 0; x < w; ++x) {
|
||||
for (int y = 0; y < h; ++y) {
|
||||
var pixelIndex = x + y * w;
|
||||
var input = 0.0f;
|
||||
|
||||
if (!hasInputs || tex.EmptyTexture) {
|
||||
input = channelVal;
|
||||
}
|
||||
else if (doNative) {
|
||||
input = tex.ActiveChannel[pixelIndex];
|
||||
}
|
||||
else {
|
||||
input = tex.GetChannelBilinear((float)x / (w - 1), (float)y / (h - 1), mipLevel, rangeX, rangeY);
|
||||
}
|
||||
|
||||
if (doInvert) {
|
||||
input = 1.0f - input;
|
||||
}
|
||||
|
||||
if (doNormal) {
|
||||
Vector3 normal;
|
||||
|
||||
if (normalCache.NativeSize && mipLevel == 0) {
|
||||
normal = (Vector4)normalCache.Values[pixelIndex];
|
||||
}
|
||||
else {
|
||||
normal = normalCache.GetPixelNormal((float)x / (w - 1), (float)y / (h - 1), mipLevel, rangeX,
|
||||
rangeY);
|
||||
}
|
||||
|
||||
normal.x = (normal.x * 2.0f) - 1.0f;
|
||||
normal.y = (normal.y * 2.0f) - 1.0f;
|
||||
normal.z = (normal.z * 2.0f) - 1.0f;
|
||||
|
||||
// Specular AA for Beckmann roughness.
|
||||
// cf http://www.frostbite.com/wp-content/uploads/2014/11/course_notes_moving_frostbite_to_pbr.pdf pg92
|
||||
var variance = 0.0f;
|
||||
var avgNormalLength = normal.magnitude;
|
||||
var applyAA = avgNormalLength < 1.0f;
|
||||
|
||||
if (applyAA) {
|
||||
float avgNormLen2 = avgNormalLength * avgNormalLength;
|
||||
float kappa = (3.0f * avgNormalLength - avgNormalLength * avgNormLen2) / (1.0f - avgNormLen2);
|
||||
|
||||
variance = Mathf.Clamp01(1.0f / (2.0f * kappa));// - source.VarianceBias);
|
||||
}
|
||||
|
||||
if (channel.OutputVariance) {
|
||||
input = variance;
|
||||
}
|
||||
else if (channel.RoughnessCorrect && applyAA) {
|
||||
float a = input * input;
|
||||
a = Mathf.Sqrt(Mathf.Clamp01(a * a + variance));
|
||||
input = Mathf.Sqrt(a);
|
||||
}
|
||||
}
|
||||
|
||||
switch (storeIndex) {
|
||||
case 0: colors[pixelIndex].r = input; break;
|
||||
case 1: colors[pixelIndex].g = input; break;
|
||||
case 2: colors[pixelIndex].b = input; break;
|
||||
case 3: colors[pixelIndex].a = input; break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
UnityEngine.Profiling.Profiler.EndSample();
|
||||
}
|
||||
}
|
||||
|
||||
UnityEngine.Profiling.Profiler.BeginSample("Set pixels");
|
||||
target.SetPixels(colors, mipLevel);
|
||||
UnityEngine.Profiling.Profiler.EndSample();
|
||||
|
||||
UnityEngine.Profiling.Profiler.EndSample();
|
||||
}
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user