Initial commit

This commit is contained in:
msk
2022-01-22 20:13:49 -08:00
parent f9d23e5bcf
commit 687473573d
878 changed files with 70957 additions and 0 deletions
@@ -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();
}
}
}
}
@@ -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:
@@ -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;
}
}
@@ -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();
}
}
}
@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 71af2ea0d77504d40854c6460ae15f5e
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
@@ -0,0 +1,70 @@
// Alloy Physical Shader Framework
// Copyright 2013-2017 RUST LLC.
// http://www.alloy.rustltd.com/
using UnityEditor;
using UnityEngine;
namespace Alloy
{
public class AlloyTextureReader{
private static Material s_passthroughMat;
protected static Material PassthroughMaterial {
get {
if (s_passthroughMat == null) {
s_passthroughMat = new Material(Shader.Find("Hidden/AlloyPassthroughBlit")) { hideFlags = HideFlags.HideAndDontSave };
}
return s_passthroughMat;
}
}
private static Material s_normMat;
protected static Material NormalMaterial {
get {
if (s_normMat == null) {
s_normMat = new Material(Shader.Find("Hidden/AlloyNormalBlit"));
s_normMat.hideFlags = HideFlags.HideAndDontSave;
}
return s_normMat;
}
}
public static Texture2D GetReadable(Texture texture, bool normalMap) {
if (texture == null) {
return null;
}
var texImporter = AssetImporter.GetAtPath(AssetDatabase.GetAssetPath(texture)) as TextureImporter;
if (texImporter == null) {
Debug.LogError("Couldn't find packed map texture in asset database!");
return null;
}
bool isEditorInLinearSpace = PlayerSettings.colorSpace == ColorSpace.Linear;
bool linear = isEditorInLinearSpace && texImporter.sRGBTexture;
Shader.SetGlobalFloat("_EditorIsLinear", linear ? 1.0f : 0.0f);
var render = new RenderTexture(texture.width, texture.height, 0, RenderTextureFormat.ARGB32);
Graphics.Blit(texture, render, normalMap ? NormalMaterial : PassthroughMaterial);
var readTex = new Texture2D(texture.width, texture.height, TextureFormat.ARGB32, false, false);
Graphics.SetRenderTarget(render);
readTex.ReadPixels(new Rect(0, 0, texture.width, texture.height), 0, 0, false);
Graphics.SetRenderTarget(null);
Object.DestroyImmediate(render);
readTex.hideFlags = HideFlags.HideAndDontSave;
return readTex;
}
}
}
@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 94b668420c3f65e4c992ef2542203df6
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
@@ -0,0 +1,24 @@
// Alloy Physical Shader Framework
// Copyright 2013-2017 RUST LLC.
// http://www.alloy.rustltd.com/
using UnityEditor;
using UnityEngine;
namespace Alloy {
[CustomPropertyDrawer(typeof(EnumFlagsAttribute))]
public class ChannelDrawer : PropertyDrawer {
public override void OnGUI(Rect position, SerializedProperty property, GUIContent label) {
EditorGUI.BeginProperty(position, label, property);
EditorGUI.BeginChangeCheck();
int index = EditorGUI.MaskField(position, label, property.intValue, property.enumDisplayNames);
if (EditorGUI.EndChangeCheck()) {
property.intValue = index;
}
EditorGUI.EndProperty();
}
}
}
@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 8f9808b8cb7540540bbfbc3d58b51f3d
timeCreated: 1438474773
licenseType: Pro
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,105 @@
// Alloy Physical Shader Framework
// Copyright 2013-2017 RUST LLC.
// http://www.alloy.rustltd.com/
using System.Linq;
using UnityEditor;
using UnityEngine;
namespace Alloy {
[CustomEditor(typeof (PackedMapDefinition))]
public class PackedMapDefintionEdtior : Editor {
public override void OnInspectorGUI() {
serializedObject.Update();
EditorGUILayout.PropertyField(serializedObject.FindProperty("Title"));
EditorGUILayout.PropertyField(serializedObject.FindProperty("Suffix"));
EditorGUILayout.PropertyField(serializedObject.FindProperty("ImportSettings"), true);
GUILayout.Space(20.0f);
var map = target as PackedMapDefinition;
var channels = serializedObject.FindProperty("Channels");
//int rI = 0, gI = 0, bI = 0, aI = 0;
int rO = 0, gO = 0, bO = 0, aO = 0;
int del = -1;
for (int i = 0; i < channels.arraySize; i++) {
var ser = channels.GetArrayElementAtIndex(i);
var channel = map.Channels[i];
var outputs = channel.OutputChannels;
if (GUILayout.Button("", "OL Minus")) {
del = i;
}
EditorGUILayout.PropertyField(ser.FindPropertyRelative("Title"));
EditorGUILayout.PropertyField(ser.FindPropertyRelative("HelpText"));
EditorGUILayout.PropertyField(ser.FindPropertyRelative("BackgroundColor"));
if (!channel.RoughnessCorrect) {
EditorGUILayout.PropertyField(ser.FindPropertyRelative("OutputVariance"));
}
if (!channel.OutputVariance) {
EditorGUILayout.PropertyField(ser.FindPropertyRelative("RoughnessCorrect"));
}
EditorGUILayout.PropertyField(ser.FindPropertyRelative("HideChannel"));
EditorGUILayout.PropertyField(ser.FindPropertyRelative("CanInvert"));
if (channel.CanInvert) {
EditorGUILayout.PropertyField(ser.FindPropertyRelative("InvertByDefault"));
}
EditorGUILayout.PropertyField(ser.FindPropertyRelative("InputChannels"));
EditorGUILayout.PropertyField(ser.FindPropertyRelative("OutputChannels"));
EditorGUILayout.PropertyField(ser.FindPropertyRelative("DefaultMode"));
if (outputs.HasFlag(MapChannel.R)) {
rO++;
}
if (outputs.HasFlag(MapChannel.G)) {
gO++;
}
if (outputs.HasFlag(MapChannel.B)) {
bO++;
}
if (outputs.HasFlag(MapChannel.A)) {
aO++;
}
}
if (rO == 0 || gO == 0 || bO == 0 || aO == 0) {
EditorGUILayout.HelpBox("Missing output channel!", MessageType.Error);
}
if (rO > 1 || gO > 1 || bO > 1 || aO > 1) {
EditorGUILayout.HelpBox("Output channel is doubly written!", MessageType.Error);
}
if (del != -1) {
channels.DeleteArrayElementAtIndex(del);
}
if (GUILayout.Button("", "OL Plus")) {
channels.InsertArrayElementAtIndex(channels.arraySize);
}
GUILayout.Space(10.0f);
if (map.Channels.Any(channel => channel.UseNormals)) {
GUILayout.Label("Packed map uses normals");
}
serializedObject.ApplyModifiedProperties();
}
}
}
@@ -0,0 +1,10 @@
fileFormatVersion: 2
guid: d517231fecc575946853bb6f5631de34
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant: