diff --git a/Guides/Material Editor Guide/shader_manifest_template.xml b/Guides/Material Editor Guide/shader_manifest_template.xml
index b8cb1505..d34444d9 100644
--- a/Guides/Material Editor Guide/shader_manifest_template.xml
+++ b/Guides/Material Editor Guide/shader_manifest_template.xml
@@ -36,6 +36,10 @@
+
+
+
+
@@ -47,6 +51,10 @@
+
+
+
+
@@ -58,6 +66,10 @@
+
+
+
+
@@ -69,6 +81,10 @@
+
+
+
+
diff --git a/src/MaterialEditor.Base/MaterialEditor.Base.projitems b/src/MaterialEditor.Base/MaterialEditor.Base.projitems
index 515ede4c..6bf7736e 100644
--- a/src/MaterialEditor.Base/MaterialEditor.Base.projitems
+++ b/src/MaterialEditor.Base/MaterialEditor.Base.projitems
@@ -18,6 +18,7 @@
+
diff --git a/src/MaterialEditor.Base/PluginBase.cs b/src/MaterialEditor.Base/PluginBase.cs
index fd792c82..233e1a31 100644
--- a/src/MaterialEditor.Base/PluginBase.cs
+++ b/src/MaterialEditor.Base/PluginBase.cs
@@ -1,319 +1,333 @@
-using BepInEx;
-using BepInEx.Configuration;
-using BepInEx.Logging;
-using System;
-using System.Collections.Generic;
-using System.IO;
-using System.Reflection;
-using System.Xml;
-using UnityEngine;
-using XUnity.ResourceRedirector;
-using static MaterialEditorAPI.MaterialAPI;
-
-namespace MaterialEditorAPI
-{
- ///
- /// MaterialEditor plugin base
- ///
- [BepInDependency(XUnity.ResourceRedirector.Constants.PluginData.Identifier, XUnity.ResourceRedirector.Constants.PluginData.Version)]
- public partial class MaterialEditorPluginBase : BaseUnityPlugin
- {
- public static new ManualLogSource Logger;
- public static MaterialEditorPluginBase Instance;
-
- ///
- /// Path where textures will be exported
- ///
- public static string ExportPathDefault = Path.Combine(Paths.GameRootPath, @"UserData\MaterialEditor");
- ///
- /// Path where textures will be exported
- ///
- public static string ExportPath = ExportPathDefault;
- ///
- /// Saved material edits
- ///
- public static CopyContainer CopyData = new CopyContainer();
-
- public static Dictionary LoadedShaders = new Dictionary();
- public static SortedDictionary> XMLShaderProperties = new SortedDictionary>();
-
- public static ConfigEntry UIScale { get; set; }
- public static ConfigEntry UIWidth { get; set; }
- public static ConfigEntry UIHeight { get; set; }
- public static ConfigEntry UIListWidth { get; set; }
- public static ConfigEntry DragSensitivity { get; set; }
- public static ConfigEntry FilterDelay { get; set; }
- public static ConfigEntry WatchTexChanges { get; set; }
- public static ConfigEntry ShaderOptimization { get; set; }
- public static ConfigEntry ExportBakedMesh { get; set; }
- public static ConfigEntry ExportBakedWorldPosition { get; set; }
- internal static ConfigEntry ConfigExportPath { get; private set; }
- public static ConfigEntry PersistFilter { get; set; }
- public static ConfigEntry Showtooltips { get; set; }
- public static ConfigEntry ProjectorNearClipPlaneMax { get; set; }
- public static ConfigEntry ProjectorFarClipPlaneMax { get; set; }
- public static ConfigEntry ProjectorFieldOfViewMax { get; set; }
- public static ConfigEntry ProjectorAspectRatioMax { get; set; }
- public static ConfigEntry ProjectorOrthographicSizeMax { get; set; }
-
- public virtual void Awake()
- {
- Instance = this;
- Logger = base.Logger;
- Directory.CreateDirectory(ExportPath);
-
- UIScale = Config.Bind("Config", "UI Scale", 1.75f, new ConfigDescription("Controls the size of the window.", new AcceptableValueRange(1f, 3f), new ConfigurationManagerAttributes { Order = 7 }));
- UIWidth = Config.Bind("Config", "UI Width", 0.3f, new ConfigDescription("Controls the size of the window.", new AcceptableValueRange(0f, 1f), new ConfigurationManagerAttributes { Order = 6, ShowRangeAsPercent = false }));
- UIHeight = Config.Bind("Config", "UI Height", 0.3f, new ConfigDescription("Controls the size of the window.", new AcceptableValueRange(0f, 1f), new ConfigurationManagerAttributes { Order = 5, ShowRangeAsPercent = false }));
- UIListWidth = Config.Bind("Config", "UI List Width", 180f, new ConfigDescription("Controls width of the renderer/materials lists to the side of the window", new AcceptableValueRange(100f, 500f), new ConfigurationManagerAttributes { Order = 4, ShowRangeAsPercent = false }));
- DragSensitivity = Config.Bind("Config", "Drag Sensitivity", 30f, new ConfigDescription("Controls the sensitivity of dragging labels to edit float values", new AcceptableValueRange(1f, 100f), new ConfigurationManagerAttributes { Order = 3, ShowRangeAsPercent = false }));
- WatchTexChanges = Config.Bind("Config", "Watch File Changes", true, new ConfigDescription("Watch for file changes and reload textures on change. Can be toggled in the UI.", null, new ConfigurationManagerAttributes { Order = 2 }));
- ShaderOptimization = Config.Bind("Config", "Shader Optimization", true, new ConfigDescription("Replaces every loaded shader with the MaterialEditor copy of the shader. Reduces the number of copies of shaders loaded which reduces RAM usage and improves performance.", null, new ConfigurationManagerAttributes { Order = 1 }));
- ExportBakedMesh = Config.Bind("Config", "Export Baked Mesh", false, new ConfigDescription("When enabled, skinned meshes will be exported in their current state with all customization applied as well as in the current pose.", null, new ConfigurationManagerAttributes { Order = 1 }));
- ExportBakedWorldPosition = Config.Bind("Config", "Export Baked World Position", false, new ConfigDescription("When enabled, objects will be exported with their position changes intact so that, i.e. when exporting two objects they retain their position relative to each other.\nOnly works when Export Baked Mesh is also enabled.", null, new ConfigurationManagerAttributes { Order = 1 }));
- ConfigExportPath = Config.Bind("Config", "Export Path Override", "", new ConfigDescription($"Textures and models will be exported to this folder. If empty, exports to {ExportPathDefault}", null, new ConfigurationManagerAttributes { Order = 1 }));
- PersistFilter = Config.Bind("Config", "Persist Filter", false, "Persist search filter across editor windows");
- Showtooltips = Config.Bind("Config", "Show Tooltips", true, "Whether to show tooltips or not");
- FilterDelay = Config.Bind("Config", "Filter search delay (in ms)", 200, new ConfigDescription("Time to wait until the filter actually refreshes the UI when stopped typing", new AcceptableValueRange(1, 2000)));
-
- //Everything in these games is 10x the size of KK/KKS
-#if AI || HS2 || PH
- ProjectorNearClipPlaneMax = Config.Bind("Projector", "Max Near Clip Plane", 100f, new ConfigDescription("Controls the max value of the slider for this projector property", new AcceptableValueRange(0.01f, 1000f), new ConfigurationManagerAttributes { Order = 5 }));
- ProjectorFarClipPlaneMax = Config.Bind("Projector", "Max Far Clip Plane", 1000f, new ConfigDescription("Controls the max value of the slider for this projector property", new AcceptableValueRange(0.01f, 1000f), new ConfigurationManagerAttributes { Order = 4 }));
- ProjectorOrthographicSizeMax = Config.Bind("Projector", "Max Orthographic Size", 20f, new ConfigDescription("Controls the max value of the slider for this projector property", new AcceptableValueRange(0.01f, 1000f), new ConfigurationManagerAttributes { Order = 1 }));
-#else
- ProjectorNearClipPlaneMax = Config.Bind("Projector", "Max Near Clip Plane", 10f, new ConfigDescription("Controls the max value of the slider for this projector property", new AcceptableValueRange(0.01f, 100f), new ConfigurationManagerAttributes { Order = 5 }));
- ProjectorFarClipPlaneMax = Config.Bind("Projector", "Max Far Clip Plane", 100f, new ConfigDescription("Controls the max value of the slider for this projector property", new AcceptableValueRange(0.01f, 100f), new ConfigurationManagerAttributes { Order = 4 }));
- ProjectorOrthographicSizeMax = Config.Bind("Projector", "Max Orthographic Size", 2f, new ConfigDescription("Controls the max value of the slider for this projector property", new AcceptableValueRange(0.01f, 100f), new ConfigurationManagerAttributes { Order = 1 }));
-#endif
- ProjectorFieldOfViewMax = Config.Bind("Projector", "Max Field Of View", 180f, new ConfigDescription("Controls the max value of the slider for this projector property", new AcceptableValueRange(0.01f, 180f), new ConfigurationManagerAttributes { Order = 3 }));
- ProjectorAspectRatioMax = Config.Bind("Projector", "Max Aspect Ratio", 2f, new ConfigDescription("Controls the max value of the slider for this projector property", new AcceptableValueRange(0.01f, 100f), new ConfigurationManagerAttributes { Order = 2 }));
-
- UIScale.SettingChanged += MaterialEditorUI.UISettingChanged;
- UIWidth.SettingChanged += MaterialEditorUI.UISettingChanged;
- UIHeight.SettingChanged += MaterialEditorUI.UISettingChanged;
- UIListWidth.SettingChanged += MaterialEditorUI.UISettingChanged;
- WatchTexChanges.SettingChanged += WatchTexChanges_SettingChanged;
- ShaderOptimization.SettingChanged += ShaderOptimization_SettingChanged;
- ConfigExportPath.SettingChanged += ConfigExportPath_SettingChanged;
- FilterDelay.SettingChanged += (sender, e) => MaterialEditorUI.filterTimer.Interval = FilterDelay.Value;
- SetExportPath();
-
- ResourceRedirection.RegisterAssetLoadedHook(HookBehaviour.OneCallbackPerResourceLoaded, AssetLoadedHook);
- LoadXML();
- }
-
- ///
- /// Every time an asset is loaded, swap its shader for the one loaded by MaterialEditor. This reduces the number of instances of a shader once they are cleaned up by garbage collection
- /// which reduce RAM usage, etc. Also fixes KK mods in EC by swapping them to the equivalent EC shader.
- ///
- protected virtual void AssetLoadedHook(AssetLoadedContext context)
- {
- if (!ShaderOptimization.Value) return;
-
- if (context.Asset is GameObject go)
- {
- var renderers = go.GetComponentsInChildren();
- for (var i = 0; i < renderers.Length; i++)
- {
- var renderer = renderers[i];
- for (var j = 0; j < renderer.materials.Length; j++)
- {
- var material = renderer.materials[j];
- if (LoadedShaders.TryGetValue(material.shader.name, out var shaderData) && shaderData.Shader != null && shaderData.ShaderOptimization)
- {
- int renderQueue = material.renderQueue;
- material.shader = shaderData.Shader;
- material.renderQueue = renderQueue;
- }
- }
- }
- }
- else if (context.Asset is Material mat)
- {
- if (LoadedShaders.TryGetValue(mat.shader.name, out var shaderData) && shaderData.Shader != null && shaderData.ShaderOptimization)
- {
- int renderQueue = mat.renderQueue;
- mat.shader = shaderData.Shader;
- mat.renderQueue = renderQueue;
- }
- }
- else if (context.Asset is Shader shader)
- {
- if (LoadedShaders.TryGetValue(shader.name, out var shaderData) && shaderData.Shader != null && shaderData.ShaderOptimization)
- context.Asset = shaderData.Shader;
- }
- }
-
- private static void LoadXML()
- {
- XMLShaderProperties["default"] = new Dictionary();
-
- using (Stream stream = Assembly.GetExecutingAssembly().GetManifestResourceStream($"{nameof(MaterialEditorAPI)}.Resources.default.xml"))
- if (stream != null)
- using (XmlReader reader = XmlReader.Create(stream))
- {
- XmlDocument doc = new XmlDocument();
- doc.Load(stream);
- XmlElement materialEditorElement = doc.DocumentElement;
-
- var shaderElements = materialEditorElement.GetElementsByTagName("Shader");
- foreach (var shaderElementObj in shaderElements)
- {
- if (shaderElementObj != null)
- {
- var shaderElement = (XmlElement)shaderElementObj;
- {
- string shaderName = shaderElement.GetAttribute("Name");
-
- XMLShaderProperties[shaderName] = new Dictionary();
-
- var shaderPropertyElements = shaderElement.GetElementsByTagName("Property");
- foreach (var shaderPropertyElementObj in shaderPropertyElements)
- {
- if (shaderPropertyElementObj != null)
- {
- var shaderPropertyElement = (XmlElement)shaderPropertyElementObj;
- {
- string propertyName = shaderPropertyElement.GetAttribute("Name");
- ShaderPropertyType propertyType = (ShaderPropertyType)Enum.Parse(typeof(ShaderPropertyType), shaderPropertyElement.GetAttribute("Type"));
- string defaultValue = shaderPropertyElement.GetAttribute("DefaultValue");
- string defaultValueAB = shaderPropertyElement.GetAttribute("DefaultValueAssetBundle");
- string hidden = shaderPropertyElement.GetAttribute("Hidden");
- string range = shaderPropertyElement.GetAttribute("Range");
- string min = null;
- string max = null;
- if (!range.IsNullOrWhiteSpace())
- {
- var rangeSplit = range.Split(',');
- if (rangeSplit.Length == 2)
- {
- min = rangeSplit[0];
- max = rangeSplit[1];
- }
- }
- ShaderPropertyData shaderPropertyData = new ShaderPropertyData(propertyName, propertyType, defaultValue, defaultValueAB, hidden, min, max);
-
- XMLShaderProperties["default"][propertyName] = shaderPropertyData;
- }
- }
- }
- }
- }
- }
- }
- }
-
- internal virtual void WatchTexChanges_SettingChanged(object sender, EventArgs e)
- {
- if (!WatchTexChanges.Value)
- MaterialEditorUI.TexChangeWatcher?.Dispose();
- }
-
- internal virtual void ShaderOptimization_SettingChanged(object sender, EventArgs e) { }
-
- internal virtual void ConfigExportPath_SettingChanged(object sender, EventArgs e)
- {
- SetExportPath();
- }
-
- private void SetExportPath()
- {
- if (ConfigExportPath.Value == "")
- ExportPath = ExportPathDefault;
- else
- ExportPath = ConfigExportPath.Value;
- }
-
- ///
- /// Always returns false, i.e. does nothing. Override to prevent certain materials from showing in the UI.
- ///
- /// Name of the material
- /// Name of the property
- ///
- public virtual bool CheckBlacklist(string materialName, string propertyName) => false;
-
- internal static Texture2D GetT2D(RenderTexture renderTexture)
- {
- var currentActiveRT = RenderTexture.active;
- RenderTexture.active = renderTexture;
- var tex = new Texture2D(renderTexture.width, renderTexture.height);
- tex.ReadPixels(new Rect(0, 0, tex.width, tex.height), 0, 0);
- RenderTexture.active = currentActiveRT;
- return tex;
- }
-
- internal static void SaveTexR(RenderTexture renderTexture, string path)
- {
- var tex = GetT2D(renderTexture);
- File.WriteAllBytes(path, tex.EncodeToPNG());
- DestroyImmediate(tex);
- }
-
- internal static void SaveTex(Texture tex, string path, RenderTextureFormat rtf = RenderTextureFormat.Default, RenderTextureReadWrite cs = RenderTextureReadWrite.Default)
- {
- var tmp = RenderTexture.GetTemporary(tex.width, tex.height, 0, rtf, cs);
- var currentActiveRT = RenderTexture.active;
- RenderTexture.active = tmp;
- GL.Clear(false, true, new Color(0, 0, 0, 0));
- Graphics.Blit(tex, tmp);
- SaveTexR(tmp, path);
- RenderTexture.active = currentActiveRT;
- RenderTexture.ReleaseTemporary(tmp);
- }
-
- public class ShaderData
- {
- public string ShaderName;
- public Shader Shader;
- public int? RenderQueue;
- public bool ShaderOptimization;
-
- public ShaderData(Shader shader, string shaderName, string renderQueue = "", string shaderOptimization = null)
- {
- Shader = shader;
- ShaderName = shaderName;
-
- if (renderQueue.IsNullOrEmpty())
- RenderQueue = null;
- else if (int.TryParse(renderQueue, out int result))
- RenderQueue = result;
- else
- RenderQueue = null;
-
- if (bool.TryParse(shaderOptimization, out bool shaderOptimizationBool))
- ShaderOptimization = shaderOptimizationBool;
- else
- ShaderOptimization = true;
- }
- }
-
- public class ShaderPropertyData
- {
- public string Name;
- public ShaderPropertyType Type;
- public string DefaultValue;
- public string DefaultValueAssetBundle;
- public bool Hidden;
- public float? MinValue;
- public float? MaxValue;
-
- public ShaderPropertyData(string name, ShaderPropertyType type, string defaultValue = null, string defaultValueAB = null, string hidden = null, string minValue = null, string maxValue = null)
- {
- Name = name;
- Type = type;
- DefaultValue = defaultValue.IsNullOrEmpty() ? null : defaultValue;
- DefaultValueAssetBundle = defaultValueAB.IsNullOrEmpty() ? null : defaultValueAB;
- Hidden = bool.TryParse(hidden, out bool result) && result;
- if (!minValue.IsNullOrWhiteSpace() && !maxValue.IsNullOrWhiteSpace())
- {
- if (float.TryParse(minValue, out float min) && float.TryParse(maxValue, out float max))
- {
- MinValue = min;
- MaxValue = max;
- }
- }
- }
- }
- }
-}
+using BepInEx;
+using BepInEx.Configuration;
+using BepInEx.Logging;
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Reflection;
+using System.Xml;
+using UnityEngine;
+using XUnity.ResourceRedirector;
+using static MaterialEditorAPI.MaterialAPI;
+
+namespace MaterialEditorAPI
+{
+ ///
+ /// MaterialEditor plugin base
+ ///
+ [BepInDependency(XUnity.ResourceRedirector.Constants.PluginData.Identifier, XUnity.ResourceRedirector.Constants.PluginData.Version)]
+ public partial class MaterialEditorPluginBase : BaseUnityPlugin
+ {
+ public static new ManualLogSource Logger;
+ public static MaterialEditorPluginBase Instance;
+
+ ///
+ /// Path where textures will be exported
+ ///
+ public static string ExportPathDefault = Path.Combine(Paths.GameRootPath, @"UserData\MaterialEditor");
+ ///
+ /// Path where textures will be exported
+ ///
+ public static string ExportPath = ExportPathDefault;
+ ///
+ /// Saved material edits
+ ///
+ public static CopyContainer CopyData = new CopyContainer();
+
+ public static Dictionary LoadedShaders = new Dictionary();
+ public static SortedDictionary> XMLShaderProperties = new SortedDictionary>();
+
+ public static ConfigEntry UIScale { get; set; }
+ public static ConfigEntry UIWidth { get; set; }
+ public static ConfigEntry UIHeight { get; set; }
+ public static ConfigEntry UIListWidth { get; set; }
+ public static ConfigEntry DragSensitivity { get; set; }
+ public static ConfigEntry FilterDelay { get; set; }
+ public static ConfigEntry WatchTexChanges { get; set; }
+ public static ConfigEntry ShaderOptimization { get; set; }
+ public static ConfigEntry ExportBakedMesh { get; set; }
+ public static ConfigEntry ExportBakedWorldPosition { get; set; }
+ internal static ConfigEntry ConfigExportPath { get; private set; }
+ public static ConfigEntry PersistFilter { get; set; }
+ public static ConfigEntry Showtooltips { get; set; }
+ public static ConfigEntry SortPropertiesByType { get; set; }
+ public static ConfigEntry SortPropertiesByName { get; set; }
+ public static ConfigEntry ProjectorNearClipPlaneMax { get; set; }
+ public static ConfigEntry ProjectorFarClipPlaneMax { get; set; }
+ public static ConfigEntry ProjectorFieldOfViewMax { get; set; }
+ public static ConfigEntry ProjectorAspectRatioMax { get; set; }
+ public static ConfigEntry ProjectorOrthographicSizeMax { get; set; }
+
+ public virtual void Awake()
+ {
+ Instance = this;
+ Logger = base.Logger;
+ Directory.CreateDirectory(ExportPath);
+
+ UIScale = Config.Bind("Config", "UI Scale", 1.75f, new ConfigDescription("Controls the size of the window.", new AcceptableValueRange(1f, 3f), new ConfigurationManagerAttributes { Order = 7 }));
+ UIWidth = Config.Bind("Config", "UI Width", 0.3f, new ConfigDescription("Controls the size of the window.", new AcceptableValueRange(0f, 1f), new ConfigurationManagerAttributes { Order = 6, ShowRangeAsPercent = false }));
+ UIHeight = Config.Bind("Config", "UI Height", 0.3f, new ConfigDescription("Controls the size of the window.", new AcceptableValueRange(0f, 1f), new ConfigurationManagerAttributes { Order = 5, ShowRangeAsPercent = false }));
+ UIListWidth = Config.Bind("Config", "UI List Width", 180f, new ConfigDescription("Controls width of the renderer/materials lists to the side of the window", new AcceptableValueRange(100f, 500f), new ConfigurationManagerAttributes { Order = 4, ShowRangeAsPercent = false }));
+ DragSensitivity = Config.Bind("Config", "Drag Sensitivity", 30f, new ConfigDescription("Controls the sensitivity of dragging labels to edit float values", new AcceptableValueRange(1f, 100f), new ConfigurationManagerAttributes { Order = 3, ShowRangeAsPercent = false }));
+ WatchTexChanges = Config.Bind("Config", "Watch File Changes", true, new ConfigDescription("Watch for file changes and reload textures on change. Can be toggled in the UI.", null, new ConfigurationManagerAttributes { Order = 2 }));
+ ShaderOptimization = Config.Bind("Config", "Shader Optimization", true, new ConfigDescription("Replaces every loaded shader with the MaterialEditor copy of the shader. Reduces the number of copies of shaders loaded which reduces RAM usage and improves performance.", null, new ConfigurationManagerAttributes { Order = 1 }));
+ ExportBakedMesh = Config.Bind("Config", "Export Baked Mesh", false, new ConfigDescription("When enabled, skinned meshes will be exported in their current state with all customization applied as well as in the current pose.", null, new ConfigurationManagerAttributes { Order = 1 }));
+ ExportBakedWorldPosition = Config.Bind("Config", "Export Baked World Position", false, new ConfigDescription("When enabled, objects will be exported with their position changes intact so that, i.e. when exporting two objects they retain their position relative to each other.\nOnly works when Export Baked Mesh is also enabled.", null, new ConfigurationManagerAttributes { Order = 1 }));
+ ConfigExportPath = Config.Bind("Config", "Export Path Override", "", new ConfigDescription($"Textures and models will be exported to this folder. If empty, exports to {ExportPathDefault}", null, new ConfigurationManagerAttributes { Order = 1 }));
+ PersistFilter = Config.Bind("Config", "Persist Filter", false, "Persist search filter across editor windows");
+ Showtooltips = Config.Bind("Config", "Show Tooltips", true, "Whether to show tooltips or not");
+ SortPropertiesByType = Config.Bind("Config", "Sort Properties by Type", true, "Whether to sort shader properties by their types.");
+ SortPropertiesByName = Config.Bind("Config", "Sort Properties by Name", true, "Whether to sort shader properties by their names.");
+ FilterDelay = Config.Bind("Config", "Filter search delay (in ms)", 200, new ConfigDescription("Time to wait until the filter actually refreshes the UI when stopped typing", new AcceptableValueRange(1, 2000)));
+
+ //Everything in these games is 10x the size of KK/KKS
+#if AI || HS2 || PH
+ ProjectorNearClipPlaneMax = Config.Bind("Projector", "Max Near Clip Plane", 100f, new ConfigDescription("Controls the max value of the slider for this projector property", new AcceptableValueRange(0.01f, 1000f), new ConfigurationManagerAttributes { Order = 5 }));
+ ProjectorFarClipPlaneMax = Config.Bind("Projector", "Max Far Clip Plane", 1000f, new ConfigDescription("Controls the max value of the slider for this projector property", new AcceptableValueRange(0.01f, 1000f), new ConfigurationManagerAttributes { Order = 4 }));
+ ProjectorOrthographicSizeMax = Config.Bind("Projector", "Max Orthographic Size", 20f, new ConfigDescription("Controls the max value of the slider for this projector property", new AcceptableValueRange(0.01f, 1000f), new ConfigurationManagerAttributes { Order = 1 }));
+#else
+ ProjectorNearClipPlaneMax = Config.Bind("Projector", "Max Near Clip Plane", 10f, new ConfigDescription("Controls the max value of the slider for this projector property", new AcceptableValueRange(0.01f, 100f), new ConfigurationManagerAttributes { Order = 5 }));
+ ProjectorFarClipPlaneMax = Config.Bind("Projector", "Max Far Clip Plane", 100f, new ConfigDescription("Controls the max value of the slider for this projector property", new AcceptableValueRange(0.01f, 100f), new ConfigurationManagerAttributes { Order = 4 }));
+ ProjectorOrthographicSizeMax = Config.Bind("Projector", "Max Orthographic Size", 2f, new ConfigDescription("Controls the max value of the slider for this projector property", new AcceptableValueRange(0.01f, 100f), new ConfigurationManagerAttributes { Order = 1 }));
+#endif
+ ProjectorFieldOfViewMax = Config.Bind("Projector", "Max Field Of View", 180f, new ConfigDescription("Controls the max value of the slider for this projector property", new AcceptableValueRange(0.01f, 180f), new ConfigurationManagerAttributes { Order = 3 }));
+ ProjectorAspectRatioMax = Config.Bind("Projector", "Max Aspect Ratio", 2f, new ConfigDescription("Controls the max value of the slider for this projector property", new AcceptableValueRange(0.01f, 100f), new ConfigurationManagerAttributes { Order = 2 }));
+
+ UIScale.SettingChanged += MaterialEditorUI.UISettingChanged;
+ UIWidth.SettingChanged += MaterialEditorUI.UISettingChanged;
+ UIHeight.SettingChanged += MaterialEditorUI.UISettingChanged;
+ UIListWidth.SettingChanged += MaterialEditorUI.UISettingChanged;
+ WatchTexChanges.SettingChanged += WatchTexChanges_SettingChanged;
+ ShaderOptimization.SettingChanged += ShaderOptimization_SettingChanged;
+ ConfigExportPath.SettingChanged += ConfigExportPath_SettingChanged;
+ SortPropertiesByType.SettingChanged += (object sender, EventArgs e) => PropertyOrganizer.Refresh();
+ SortPropertiesByName.SettingChanged += (object sender, EventArgs e) => PropertyOrganizer.Refresh();
+ FilterDelay.SettingChanged += (sender, e) => MaterialEditorUI.filterTimer.Interval = FilterDelay.Value;
+ SetExportPath();
+
+ ResourceRedirection.RegisterAssetLoadedHook(HookBehaviour.OneCallbackPerResourceLoaded, AssetLoadedHook);
+ LoadXML();
+ }
+
+ ///
+ /// Every time an asset is loaded, swap its shader for the one loaded by MaterialEditor. This reduces the number of instances of a shader once they are cleaned up by garbage collection
+ /// which reduce RAM usage, etc. Also fixes KK mods in EC by swapping them to the equivalent EC shader.
+ ///
+ protected virtual void AssetLoadedHook(AssetLoadedContext context)
+ {
+ if (!ShaderOptimization.Value) return;
+
+ if (context.Asset is GameObject go)
+ {
+ var renderers = go.GetComponentsInChildren();
+ for (var i = 0; i < renderers.Length; i++)
+ {
+ var renderer = renderers[i];
+ for (var j = 0; j < renderer.materials.Length; j++)
+ {
+ var material = renderer.materials[j];
+ if (LoadedShaders.TryGetValue(material.shader.name, out var shaderData) && shaderData.Shader != null && shaderData.ShaderOptimization)
+ {
+ int renderQueue = material.renderQueue;
+ material.shader = shaderData.Shader;
+ material.renderQueue = renderQueue;
+ }
+ }
+ }
+ }
+ else if (context.Asset is Material mat)
+ {
+ if (LoadedShaders.TryGetValue(mat.shader.name, out var shaderData) && shaderData.Shader != null && shaderData.ShaderOptimization)
+ {
+ int renderQueue = mat.renderQueue;
+ mat.shader = shaderData.Shader;
+ mat.renderQueue = renderQueue;
+ }
+ }
+ else if (context.Asset is Shader shader)
+ {
+ if (LoadedShaders.TryGetValue(shader.name, out var shaderData) && shaderData.Shader != null && shaderData.ShaderOptimization)
+ context.Asset = shaderData.Shader;
+ }
+ }
+
+ private static void LoadXML()
+ {
+ XMLShaderProperties["default"] = new Dictionary();
+
+ using (Stream stream = Assembly.GetExecutingAssembly().GetManifestResourceStream($"{nameof(MaterialEditorAPI)}.Resources.default.xml"))
+ if (stream != null)
+ using (XmlReader reader = XmlReader.Create(stream))
+ {
+ XmlDocument doc = new XmlDocument();
+ doc.Load(stream);
+ XmlElement materialEditorElement = doc.DocumentElement;
+
+ var shaderElements = materialEditorElement.GetElementsByTagName("Shader");
+ foreach (var shaderElementObj in shaderElements)
+ {
+ if (shaderElementObj != null)
+ {
+ var shaderElement = (XmlElement)shaderElementObj;
+ {
+ string shaderName = shaderElement.GetAttribute("Name");
+
+ XMLShaderProperties[shaderName] = new Dictionary();
+
+ var shaderPropertyElements = shaderElement.GetElementsByTagName("Property");
+ foreach (var shaderPropertyElementObj in shaderPropertyElements)
+ {
+ if (shaderPropertyElementObj != null)
+ {
+ var shaderPropertyElement = (XmlElement)shaderPropertyElementObj;
+ {
+ string propertyName = shaderPropertyElement.GetAttribute("Name");
+ ShaderPropertyType propertyType = (ShaderPropertyType)Enum.Parse(typeof(ShaderPropertyType), shaderPropertyElement.GetAttribute("Type"));
+ string defaultValue = shaderPropertyElement.GetAttribute("DefaultValue");
+ string defaultValueAB = shaderPropertyElement.GetAttribute("DefaultValueAssetBundle");
+ string hidden = shaderPropertyElement.GetAttribute("Hidden");
+ string range = shaderPropertyElement.GetAttribute("Range");
+ string min = null;
+ string max = null;
+ string category = shaderPropertyElement.GetAttribute("Category");
+ if (!range.IsNullOrWhiteSpace())
+ {
+ var rangeSplit = range.Split(',');
+ if (rangeSplit.Length == 2)
+ {
+ min = rangeSplit[0];
+ max = rangeSplit[1];
+ }
+ }
+ ShaderPropertyData shaderPropertyData = new ShaderPropertyData(propertyName, propertyType, defaultValue, defaultValueAB, hidden, min, max, category);
+
+ XMLShaderProperties["default"][propertyName] = shaderPropertyData;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ internal virtual void WatchTexChanges_SettingChanged(object sender, EventArgs e)
+ {
+ if (!WatchTexChanges.Value)
+ MaterialEditorUI.TexChangeWatcher?.Dispose();
+ }
+
+ internal virtual void ShaderOptimization_SettingChanged(object sender, EventArgs e) { }
+
+ internal virtual void ConfigExportPath_SettingChanged(object sender, EventArgs e)
+ {
+ SetExportPath();
+ }
+
+ private void SetExportPath()
+ {
+ if (ConfigExportPath.Value == "")
+ ExportPath = ExportPathDefault;
+ else
+ ExportPath = ConfigExportPath.Value;
+ }
+
+ ///
+ /// Always returns false, i.e. does nothing. Override to prevent certain materials from showing in the UI.
+ ///
+ /// Name of the material
+ /// Name of the property
+ ///
+ public virtual bool CheckBlacklist(string materialName, string propertyName) => false;
+
+ internal static Texture2D GetT2D(RenderTexture renderTexture)
+ {
+ var currentActiveRT = RenderTexture.active;
+ RenderTexture.active = renderTexture;
+ var tex = new Texture2D(renderTexture.width, renderTexture.height);
+ tex.ReadPixels(new Rect(0, 0, tex.width, tex.height), 0, 0);
+ RenderTexture.active = currentActiveRT;
+ return tex;
+ }
+
+ internal static void SaveTexR(RenderTexture renderTexture, string path)
+ {
+ var tex = GetT2D(renderTexture);
+ File.WriteAllBytes(path, tex.EncodeToPNG());
+ DestroyImmediate(tex);
+ }
+
+ internal static void SaveTex(Texture tex, string path, RenderTextureFormat rtf = RenderTextureFormat.Default, RenderTextureReadWrite cs = RenderTextureReadWrite.Default)
+ {
+ var tmp = RenderTexture.GetTemporary(tex.width, tex.height, 0, rtf, cs);
+ var currentActiveRT = RenderTexture.active;
+ RenderTexture.active = tmp;
+ GL.Clear(false, true, new Color(0, 0, 0, 0));
+ Graphics.Blit(tex, tmp);
+ SaveTexR(tmp, path);
+ RenderTexture.active = currentActiveRT;
+ RenderTexture.ReleaseTemporary(tmp);
+ }
+
+ protected static void RefreshPropertyOrganization()
+ {
+ PropertyOrganizer.Refresh();
+ }
+
+ public class ShaderData
+ {
+ public string ShaderName;
+ public Shader Shader;
+ public int? RenderQueue;
+ public bool ShaderOptimization;
+
+ public ShaderData(Shader shader, string shaderName, string renderQueue = "", string shaderOptimization = null)
+ {
+ Shader = shader;
+ ShaderName = shaderName;
+
+ if (renderQueue.IsNullOrEmpty())
+ RenderQueue = null;
+ else if (int.TryParse(renderQueue, out int result))
+ RenderQueue = result;
+ else
+ RenderQueue = null;
+
+ if (bool.TryParse(shaderOptimization, out bool shaderOptimizationBool))
+ ShaderOptimization = shaderOptimizationBool;
+ else
+ ShaderOptimization = true;
+ }
+ }
+
+ public class ShaderPropertyData
+ {
+ public string Name;
+ public ShaderPropertyType Type;
+ public string DefaultValue;
+ public string DefaultValueAssetBundle;
+ public bool Hidden;
+ public float? MinValue;
+ public float? MaxValue;
+ public string Category;
+
+ public ShaderPropertyData(string name, ShaderPropertyType type, string defaultValue = null, string defaultValueAB = null, string hidden = null, string minValue = null, string maxValue = null, string category = null)
+ {
+ Name = name;
+ Type = type;
+ DefaultValue = defaultValue.IsNullOrEmpty() ? null : defaultValue;
+ DefaultValueAssetBundle = defaultValueAB.IsNullOrEmpty() ? null : defaultValueAB;
+ Hidden = bool.TryParse(hidden, out bool result) && result;
+ if (!minValue.IsNullOrWhiteSpace() && !maxValue.IsNullOrWhiteSpace())
+ {
+ if (float.TryParse(minValue, out float min) && float.TryParse(maxValue, out float max))
+ {
+ MinValue = min;
+ MaxValue = max;
+ }
+ }
+ Category = category;
+ }
+ }
+ }
+}
diff --git a/src/MaterialEditor.Base/UI/UI.ItemInfo.cs b/src/MaterialEditor.Base/UI/UI.ItemInfo.cs
index 89e3014e..18aa490c 100644
--- a/src/MaterialEditor.Base/UI/UI.ItemInfo.cs
+++ b/src/MaterialEditor.Base/UI/UI.ItemInfo.cs
@@ -1,4 +1,4 @@
-using System;
+using System;
using UnityEngine;
namespace MaterialEditorAPI
@@ -99,6 +99,6 @@ public ItemInfo(RowItemType itemType, string labelText = "")
LabelText = labelText;
}
- public enum RowItemType { Renderer, RendererEnabled, RendererShadowCastingMode, RendererReceiveShadows, RendererUpdateWhenOffscreen, RendererRecalculateNormals, Material, Shader, ShaderRenderQueue, TextureProperty, TextureOffsetScale, ColorProperty, FloatProperty, KeywordProperty }
+ public enum RowItemType { Renderer, RendererEnabled, RendererShadowCastingMode, RendererReceiveShadows, RendererUpdateWhenOffscreen, RendererRecalculateNormals, Material, Shader, ShaderRenderQueue, PropertyCategory, TextureProperty, TextureOffsetScale, ColorProperty, FloatProperty, KeywordProperty }
}
-}
+}
\ No newline at end of file
diff --git a/src/MaterialEditor.Base/UI/UI.ItemTemplate.cs b/src/MaterialEditor.Base/UI/UI.ItemTemplate.cs
index e737ef19..a17f1722 100644
--- a/src/MaterialEditor.Base/UI/UI.ItemTemplate.cs
+++ b/src/MaterialEditor.Base/UI/UI.ItemTemplate.cs
@@ -1,564 +1,579 @@
-using UILib;
-using UnityEngine;
-using UnityEngine.UI;
-using static MaterialEditorAPI.MaterialEditorUI;
-
-namespace MaterialEditorAPI
-{
- internal static class ItemTemplate
- {
- internal static GameObject CreateTemplate(Transform parent)
- {
- var contentList = UIUtility.CreatePanel("ListEntry", parent);
- contentList.gameObject.AddComponent().preferredHeight = PanelHeight;
- contentList.gameObject.AddComponent();
- contentList.color = RowColor;
-
- //Renderer
- {
- var itemPanel = UIUtility.CreatePanel("RendererPanel", contentList.transform);
- itemPanel.gameObject.AddComponent();
- itemPanel.gameObject.AddComponent().padding = Padding;
- itemPanel.color = SeparatorItemColor;
-
- var label = UIUtility.CreateText("RendererLabel", itemPanel.transform, "");
- label.alignment = TextAnchor.MiddleLeft;
- label.color = Color.black;
- var labelLE = label.gameObject.AddComponent();
- labelLE.preferredWidth = LabelWidth;
- labelLE.flexibleWidth = LabelWidth;
-
- Text labelRenderer = UIUtility.CreateText("RendererText", itemPanel.transform);
- labelRenderer.alignment = TextAnchor.MiddleRight;
- labelRenderer.color = Color.black;
- var labelRendererLE = labelRenderer.gameObject.AddComponent();
- labelRendererLE.preferredWidth = 200;
- labelRendererLE.flexibleWidth = 0;
-
- CreateInterpolableButton("SelectInterpolableRendererButton", itemPanel.transform);
-
- Button exportUVButton = UIUtility.CreateButton("ExportUVButton", itemPanel.transform, "Export UV Map");
- var exportUVButtonLE = exportUVButton.gameObject.AddComponent();
- exportUVButtonLE.preferredWidth = 110;
- exportUVButtonLE.flexibleWidth = 0;
-
- Button exportMeshButton = UIUtility.CreateButton("ExportObjButton", itemPanel.transform, "Export .obj");
- var exportMeshButtonLE = exportMeshButton.gameObject.AddComponent();
- exportMeshButtonLE.preferredWidth = 85;
- exportMeshButtonLE.flexibleWidth = 0;
- }
-
- //Renderer Enabled
- {
- var itemPanel = UIUtility.CreatePanel("RendererEnabledPanel", contentList.transform);
- itemPanel.gameObject.AddComponent();
- itemPanel.gameObject.AddComponent().padding = Padding;
- itemPanel.color = ItemColor;
-
- var label = UIUtility.CreateText("RendererEnabledLabel", itemPanel.transform, "");
- label.alignment = TextAnchor.MiddleLeft;
- label.color = Color.black;
- var labelLE = label.gameObject.AddComponent();
- labelLE.preferredWidth = LabelWidth;
- labelLE.flexibleWidth = LabelWidth;
-
- Toggle toggleEnabled = UIUtility.CreateToggle("RendererEnabledToggle", itemPanel.transform, "");
- var toggleEnabledLE = toggleEnabled.gameObject.AddComponent();
- toggleEnabledLE.preferredWidth = 12;
- toggleEnabledLE.flexibleWidth = 0;
- toggleEnabled.isOn = true;
-
- var reset = UIUtility.CreateButton($"RendererEnabledResetButton", itemPanel.transform, "Reset");
- var resetLE = reset.gameObject.AddComponent();
- resetLE.preferredWidth = ResetButtonWidth;
- resetLE.flexibleWidth = 0;
- }
-
- //Renderer ShadowCastingMode
- {
- var itemPanel = UIUtility.CreatePanel("RendererShadowCastingModePanel", contentList.transform);
- itemPanel.gameObject.AddComponent();
- itemPanel.gameObject.AddComponent().padding = Padding;
- itemPanel.color = ItemColor;
-
- var label = UIUtility.CreateText("RendererShadowCastingModeLabel", itemPanel.transform, "");
- label.alignment = TextAnchor.MiddleLeft;
- label.color = Color.black;
- var labelLE = label.gameObject.AddComponent();
- labelLE.preferredWidth = LabelWidth;
- labelLE.flexibleWidth = LabelWidth;
-
- Dropdown dropdownShadowCastingMode = UIUtility.CreateDropdown("RendererShadowCastingModeDropdown", itemPanel.transform);
- dropdownShadowCastingMode.transform.SetRect(0f, 0f, 0f, 1f, 0f, 0f, 100f);
- dropdownShadowCastingMode.captionText.transform.SetRect(0f, 0f, 1f, 1f, 5f, 2f, -15f, -2f);
- dropdownShadowCastingMode.captionText.alignment = TextAnchor.MiddleLeft;
- dropdownShadowCastingMode.options.Clear();
- dropdownShadowCastingMode.options.Add(new Dropdown.OptionData("Off"));
- dropdownShadowCastingMode.options.Add(new Dropdown.OptionData("On"));
- dropdownShadowCastingMode.options.Add(new Dropdown.OptionData("Two Sided"));
- dropdownShadowCastingMode.options.Add(new Dropdown.OptionData("Shadows Only"));
- dropdownShadowCastingMode.value = 0;
- dropdownShadowCastingMode.captionText.text = "Off";
- var dropdownShadowCastingModeLE = dropdownShadowCastingMode.gameObject.AddComponent();
- dropdownShadowCastingModeLE.preferredWidth = DropdownWidth;
- dropdownShadowCastingModeLE.flexibleWidth = 0;
-
- var reset = UIUtility.CreateButton($"RendererShadowCastingModeResetButton", itemPanel.transform, "Reset");
- var resetLE = reset.gameObject.AddComponent();
- resetLE.preferredWidth = ResetButtonWidth;
- resetLE.flexibleWidth = 0;
- }
-
- //Renderer ReceiveShadows
- {
- var itemPanel = UIUtility.CreatePanel("RendererReceiveShadowsPanel", contentList.transform);
- itemPanel.gameObject.AddComponent();
- itemPanel.gameObject.AddComponent().padding = Padding;
- itemPanel.color = ItemColor;
-
- var label = UIUtility.CreateText("RendererReceiveShadowsLabel", itemPanel.transform, "");
- label.alignment = TextAnchor.MiddleLeft;
- label.color = Color.black;
- var labelLE = label.gameObject.AddComponent();
- labelLE.preferredWidth = LabelWidth;
- labelLE.flexibleWidth = LabelWidth;
-
- Toggle toggleReceiveShadows = UIUtility.CreateToggle("RendererReceiveShadowsToggle", itemPanel.transform, "");
- var toggleReceiveShadowsLE = toggleReceiveShadows.gameObject.AddComponent();
- toggleReceiveShadowsLE.preferredWidth = 12;
- toggleReceiveShadowsLE.flexibleWidth = 0;
- toggleReceiveShadows.isOn = true;
-
- var reset = UIUtility.CreateButton($"RendererReceiveShadowsResetButton", itemPanel.transform, "Reset");
- var resetLE = reset.gameObject.AddComponent();
- resetLE.preferredWidth = ResetButtonWidth;
- resetLE.flexibleWidth = 0;
- }
-
- //Renderer RendererUpdateWhenOffscreen
- {
- var itemPanel = UIUtility.CreatePanel("RendererUpdateWhenOffscreenPanel", contentList.transform);
- itemPanel.gameObject.AddComponent();
- itemPanel.gameObject.AddComponent().padding = Padding;
- itemPanel.color = ItemColor;
-
- var label = UIUtility.CreateText("RendererUpdateWhenOffscreenLabel", itemPanel.transform, "");
- label.alignment = TextAnchor.MiddleLeft;
- label.color = Color.black;
- var labelLE = label.gameObject.AddComponent();
- labelLE.preferredWidth = LabelWidth;
- labelLE.flexibleWidth = LabelWidth;
-
- Toggle toggleRendererUpdateWhenOffscreen = UIUtility.CreateToggle("RendererUpdateWhenOffscreenToggle", itemPanel.transform, "");
- var toggleRendererUpdateWhenOffscreenLE = toggleRendererUpdateWhenOffscreen.gameObject.AddComponent();
- toggleRendererUpdateWhenOffscreenLE.preferredWidth = 12;
- toggleRendererUpdateWhenOffscreenLE.flexibleWidth = 0;
- toggleRendererUpdateWhenOffscreen.isOn = false;
-
- var reset = UIUtility.CreateButton($"RendererUpdateWhenOffscreenResetButton", itemPanel.transform, "Reset");
- var resetLE = reset.gameObject.AddComponent();
- resetLE.preferredWidth = ResetButtonWidth;
- resetLE.flexibleWidth = 0;
- }
-
- //Renderer RecalulateNormals
- {
- var itemPanel = UIUtility.CreatePanel("RendererRecalculateNormalsPanel", contentList.transform);
- itemPanel.gameObject.AddComponent();
- itemPanel.gameObject.AddComponent().padding = Padding;
- itemPanel.color = ItemColor;
-
- var label = UIUtility.CreateText("RendererRecalculateNormalsLabel", itemPanel.transform, "");
- label.alignment = TextAnchor.MiddleLeft;
- label.color = Color.black;
- var labelLE = label.gameObject.AddComponent();
- labelLE.preferredWidth = LabelWidth;
- labelLE.flexibleWidth = LabelWidth;
-
- Toggle toggleRecalculateNormals = UIUtility.CreateToggle("RendererRecalculateNormalsToggle", itemPanel.transform, "");
- var toggleRecalculateNormalsLE = toggleRecalculateNormals.gameObject.AddComponent();
- toggleRecalculateNormalsLE.preferredWidth = 12;
- toggleRecalculateNormalsLE.flexibleWidth = 0;
- toggleRecalculateNormals.isOn = false;
-
- var reset = UIUtility.CreateButton($"RendererRecalculateNormalsResetButton", itemPanel.transform, "Reset");
- var resetLE = reset.gameObject.AddComponent();
- resetLE.preferredWidth = ResetButtonWidth;
- resetLE.flexibleWidth = 0;
- }
-
- //Material
- {
- var itemPanel = UIUtility.CreatePanel("MaterialPanel", contentList.transform);
- itemPanel.gameObject.AddComponent();
- itemPanel.gameObject.AddComponent().padding = Padding;
- itemPanel.color = SeparatorItemColor;
-
- var label = UIUtility.CreateText("MaterialLabel", itemPanel.transform, "");
- label.alignment = TextAnchor.MiddleLeft;
- label.color = Color.black;
- var labelLE = label.gameObject.AddComponent();
- labelLE.preferredWidth = LabelWidth;
- labelLE.flexibleWidth = LabelWidth;
-
- Text materialText = UIUtility.CreateText("MaterialText", itemPanel.transform);
- materialText.alignment = TextAnchor.MiddleRight;
- materialText.color = Color.black;
- var materialTextLE = materialText.gameObject.AddComponent();
- materialTextLE.preferredWidth = 200;
- materialTextLE.flexibleWidth = 0;
-
- var copyEdits = UIUtility.CreateButton($"MaterialCopy", itemPanel.transform, "Copy Edits");
- var copyEditsLE = copyEdits.gameObject.AddComponent();
- copyEditsLE.preferredWidth = ButtonWidth;
- copyEditsLE.flexibleWidth = 0;
-
- var pasteEdits = UIUtility.CreateButton($"MaterialPaste", itemPanel.transform, "Paste Edits");
- var pasteEditsLE = pasteEdits.gameObject.AddComponent();
- pasteEditsLE.preferredWidth = ButtonWidth;
- pasteEditsLE.flexibleWidth = 0;
-
- var copy = UIUtility.CreateButton($"MaterialCopyRemove", itemPanel.transform, "Copy Material");
- var copyLE = copy.gameObject.AddComponent();
- copyLE.preferredWidth = ButtonWidth;
- copyLE.flexibleWidth = 0;
-
- var rename = UIUtility.CreateButton($"MaterialRename", itemPanel.transform, ">");
- var renameLE = rename.gameObject.AddComponent();
- renameLE.preferredWidth = ButtonWidth / 4;
- renameLE.flexibleWidth = 0;
- }
-
- //Material Shader
- {
- var itemPanel = UIUtility.CreatePanel("ShaderPanel", contentList.transform);
- itemPanel.gameObject.AddComponent();
- itemPanel.gameObject.AddComponent().padding = Padding;
- itemPanel.color = ItemColor;
-
- var label = UIUtility.CreateText("ShaderLabel", itemPanel.transform, "");
- label.alignment = TextAnchor.MiddleLeft;
- label.color = Color.black;
- var labelLE = label.gameObject.AddComponent();
- labelLE.preferredWidth = LabelWidth;
- labelLE.flexibleWidth = LabelWidth;
-
- CreateInterpolableButton("SelectInterpolableShaderButton", itemPanel.transform);
-
- Dropdown dropdownShader = UIUtility.CreateDropdown("ShaderDropdown", itemPanel.transform);
- dropdownShader.transform.SetRect(0f, 0f, 0f, 1f, 0f, 0f, 100f);
- dropdownShader.captionText.transform.SetRect(0f, 0f, 1f, 1f, 5f, 2f, -15f, -2f);
- dropdownShader.captionText.alignment = TextAnchor.MiddleLeft;
- dropdownShader.options.Clear();
- dropdownShader.options.Add(new Dropdown.OptionData("Reset"));
- foreach (var shader in MaterialEditorPluginBase.XMLShaderProperties)
- if (shader.Key != "default")
- dropdownShader.options.Add(new Dropdown.OptionData(shader.Key));
- var dropdownShaderLE = dropdownShader.gameObject.AddComponent();
- dropdownShaderLE.preferredWidth = DropdownWidth * 3;
- dropdownShaderLE.flexibleWidth = 0;
-
- var reset = UIUtility.CreateButton($"ShaderResetButton", itemPanel.transform, "Reset");
- var resetLE = reset.gameObject.AddComponent();
- resetLE.preferredWidth = ResetButtonWidth;
- resetLE.flexibleWidth = 0;
- }
-
- //Material RenderQueue
- {
- var itemPanel = UIUtility.CreatePanel("ShaderRenderQueuePanel", contentList.transform);
- itemPanel.gameObject.AddComponent();
- itemPanel.gameObject.AddComponent().padding = Padding;
- itemPanel.color = ItemColor;
-
- var label = UIUtility.CreateText("ShaderRenderQueueLabel", itemPanel.transform, "");
- label.alignment = TextAnchor.MiddleLeft;
- label.color = Color.black;
- var labelLE = label.gameObject.AddComponent();
- labelLE.preferredWidth = LabelWidth;
- labelLE.flexibleWidth = LabelWidth;
-
- InputField textBoxShaderRenderQueue = UIUtility.CreateInputField("ShaderRenderQueueInput", itemPanel.transform);
- textBoxShaderRenderQueue.text = "0";
- var textBoxShaderRenderQueueLE = textBoxShaderRenderQueue.gameObject.AddComponent();
- textBoxShaderRenderQueueLE.preferredWidth = TextBoxWidth;
- textBoxShaderRenderQueueLE.flexibleWidth = 0;
-
- var reset = UIUtility.CreateButton($"ShaderRenderQueueResetButton", itemPanel.transform, "Reset");
- var resetLE = reset.gameObject.AddComponent();
- resetLE.preferredWidth = ResetButtonWidth;
- resetLE.flexibleWidth = 0;
- }
-
- //Texture properties
- {
- var itemPanel = UIUtility.CreatePanel("TexturePanel", contentList.transform);
- itemPanel.gameObject.AddComponent();
- itemPanel.gameObject.AddComponent().padding = Padding;
- itemPanel.color = ItemColor;
-
- var label = UIUtility.CreateText("TextureLabel", itemPanel.transform, "");
- label.alignment = TextAnchor.MiddleLeft;
- label.color = Color.black;
- var labelLE = label.gameObject.AddComponent();
- labelLE.preferredWidth = LabelWidth;
- labelLE.flexibleWidth = LabelWidth;
-
- CreateInterpolableButton("SelectInterpolableTextureButton", itemPanel.transform);
-
- Button exportButton = UIUtility.CreateButton($"TextureExportButton", itemPanel.transform, $"Export Texture");
- var exportButtonLE = exportButton.gameObject.AddComponent();
- exportButtonLE.preferredWidth = ButtonWidth;
- exportButtonLE.flexibleWidth = 0;
-
- Button importButton = UIUtility.CreateButton($"TextureImportButton", itemPanel.transform, $"Import Texture");
- var importButtonLE = importButton.gameObject.AddComponent();
- importButtonLE.preferredWidth = ButtonWidth;
- importButtonLE.flexibleWidth = 0;
-
- var reset = UIUtility.CreateButton($"TextureResetButton", itemPanel.transform, "Reset");
- var resetLE = reset.gameObject.AddComponent();
- resetLE.preferredWidth = ResetButtonWidth;
- resetLE.flexibleWidth = 0;
- }
-
- //Offset and Scale
- {
- var itemPanel = UIUtility.CreatePanel("OffsetScalePanel", contentList.transform);
- itemPanel.gameObject.AddComponent();
- itemPanel.gameObject.AddComponent().padding = Padding;
- itemPanel.color = ItemColor;
-
- var label = UIUtility.CreateText("OffsetScaleLabel", itemPanel.transform, "");
- label.alignment = TextAnchor.MiddleLeft;
- label.color = Color.black;
- var labelLE = label.gameObject.AddComponent();
- labelLE.preferredWidth = LabelWidth;
- labelLE.flexibleWidth = LabelWidth;
-
- Text labelOffsetX = UIUtility.CreateText("OffsetXText", itemPanel.transform, "Offset X");
- labelOffsetX.alignment = TextAnchor.MiddleLeft;
- labelOffsetX.color = Color.black;
- var labelOffsetXLE = labelOffsetX.gameObject.AddComponent();
- labelOffsetXLE.preferredWidth = LabelXWidth;
- labelOffsetXLE.flexibleWidth = 0;
-
- InputField textBoxOffsetX = UIUtility.CreateInputField("OffsetXInput", itemPanel.transform);
- textBoxOffsetX.text = "0";
- var textBoxOffsetXLE = textBoxOffsetX.gameObject.AddComponent();
- textBoxOffsetXLE.preferredWidth = TextBoxXYWidth;
- textBoxOffsetXLE.flexibleWidth = 0;
-
- Text labelOffsetY = UIUtility.CreateText("OffsetYText", itemPanel.transform, "Y");
- labelOffsetY.alignment = TextAnchor.MiddleLeft;
- labelOffsetY.color = Color.black;
- var labelOffsetYLE = labelOffsetY.gameObject.AddComponent();
- labelOffsetYLE.preferredWidth = LabelYWidth;
- labelOffsetYLE.flexibleWidth = 0;
-
- InputField textBoxOffsetY = UIUtility.CreateInputField("OffsetYInput", itemPanel.transform);
- textBoxOffsetY.text = "0";
- var textBoxOffsetYLE = textBoxOffsetY.gameObject.AddComponent();
- textBoxOffsetYLE.preferredWidth = TextBoxXYWidth;
- textBoxOffsetYLE.flexibleWidth = 0;
-
- labelOffsetX.gameObject.AddComponent().Initialize(textBoxOffsetX, new[] { textBoxOffsetY });
- labelOffsetY.gameObject.AddComponent().Initialize(textBoxOffsetY, new[] { textBoxOffsetX });
-
- //Scale
- Text labelScaleX = UIUtility.CreateText("ScaleXText", itemPanel.transform, "Scale X");
- labelScaleX.alignment = TextAnchor.MiddleLeft;
- labelScaleX.color = Color.black;
- var labelScaleXLE = labelScaleX.gameObject.AddComponent();
- labelScaleXLE.preferredWidth = LabelXWidth;
- labelScaleXLE.flexibleWidth = 0;
-
- InputField textBoxScaleX = UIUtility.CreateInputField("ScaleXInput", itemPanel.transform);
- textBoxScaleX.text = "0";
- var textBoxScaleXLE = textBoxScaleX.gameObject.AddComponent();
- textBoxScaleXLE.preferredWidth = TextBoxXYWidth;
- textBoxScaleXLE.flexibleWidth = 0;
-
- Text labelScaleY = UIUtility.CreateText("ScaleYText", itemPanel.transform, "Y");
- labelScaleY.alignment = TextAnchor.MiddleLeft;
- labelScaleY.color = Color.black;
- var labelScaleYLE = labelScaleY.gameObject.AddComponent();
- labelScaleYLE.preferredWidth = LabelYWidth;
- labelScaleYLE.flexibleWidth = 0;
-
- InputField textBoxScaleY = UIUtility.CreateInputField("ScaleYInput", itemPanel.transform);
- textBoxScaleY.text = "0";
- var textBoxScaleYLE = textBoxScaleY.gameObject.AddComponent();
- textBoxScaleYLE.preferredWidth = TextBoxXYWidth;
- textBoxScaleYLE.flexibleWidth = 0;
-
- var reset = UIUtility.CreateButton($"OffsetScaleResetButton", itemPanel.transform, "Reset");
- var resetLE = reset.gameObject.AddComponent();
- resetLE.preferredWidth = ResetButtonWidth;
- resetLE.flexibleWidth = 0;
-
- labelScaleX.gameObject.AddComponent().Initialize(textBoxScaleX, new[] { textBoxScaleY });
- labelScaleY.gameObject.AddComponent().Initialize(textBoxScaleY, new[] { textBoxScaleX });
- }
-
- //Color properties
- {
- var itemPanel = UIUtility.CreatePanel("ColorPanel", contentList.transform);
- itemPanel.gameObject.AddComponent();
- itemPanel.gameObject.AddComponent().padding = Padding;
- itemPanel.color = ItemColor;
-
- var label = UIUtility.CreateText("ColorLabel", itemPanel.transform, "");
- label.alignment = TextAnchor.MiddleLeft;
- label.color = Color.black;
- var labelLE = label.gameObject.AddComponent();
- labelLE.preferredWidth = LabelWidth;
- labelLE.flexibleWidth = LabelWidth;
-
- CreateInterpolableButton("SelectInterpolableColorButton", itemPanel.transform);
-
- Text labelR = UIUtility.CreateText("ColorRText", itemPanel.transform, "R");
- labelR.alignment = TextAnchor.MiddleLeft;
- labelR.color = Color.black;
- var labelRLE = labelR.gameObject.AddComponent();
- labelRLE.preferredWidth = ColorLabelWidth;
- labelRLE.flexibleWidth = 0;
-
- InputField textBoxR = UIUtility.CreateInputField("ColorRInput", itemPanel.transform);
- textBoxR.text = "0";
- var textBoxRLE = textBoxR.gameObject.AddComponent();
- textBoxRLE.preferredWidth = TextBoxWidth;
- textBoxRLE.flexibleWidth = 0;
-
- Text labelG = UIUtility.CreateText("ColorGText", itemPanel.transform, "G");
- labelG.alignment = TextAnchor.MiddleLeft;
- labelG.color = Color.black;
- var labelGLE = labelG.gameObject.AddComponent();
- labelGLE.preferredWidth = ColorLabelWidth;
- labelGLE.flexibleWidth = 0;
-
- InputField textBoxG = UIUtility.CreateInputField("ColorGInput", itemPanel.transform);
- textBoxG.text = "0";
- var textBoxGLE = textBoxG.gameObject.AddComponent();
- textBoxGLE.preferredWidth = TextBoxWidth;
- textBoxGLE.flexibleWidth = 0;
-
- Text labelB = UIUtility.CreateText("ColorBText", itemPanel.transform, "B");
- labelB.alignment = TextAnchor.MiddleLeft;
- labelB.color = Color.black;
- var labelBLE = labelB.gameObject.AddComponent();
- labelBLE.preferredWidth = ColorLabelWidth;
- labelBLE.flexibleWidth = 0;
-
- InputField textBoxB = UIUtility.CreateInputField("ColorBInput", itemPanel.transform);
- textBoxB.text = "0";
- var textBoxBLE = textBoxB.gameObject.AddComponent();
- textBoxBLE.preferredWidth = TextBoxWidth;
- textBoxBLE.flexibleWidth = 0;
-
- Text labelA = UIUtility.CreateText("ColorAText", itemPanel.transform, "A");
- labelA.alignment = TextAnchor.MiddleLeft;
- labelA.color = Color.black;
- var labelALE = labelA.gameObject.AddComponent();
- labelALE.preferredWidth = ColorLabelWidth;
- labelALE.flexibleWidth = 0;
-
- InputField textBoxA = UIUtility.CreateInputField("ColorAInput", itemPanel.transform);
- textBoxA.text = "0";
- var textBoxALE = textBoxA.gameObject.AddComponent();
- textBoxALE.preferredWidth = TextBoxWidth;
- textBoxALE.flexibleWidth = 0;
-
- var edit = UIUtility.CreateButton("ColorEditButton", itemPanel.transform, "");
- var editLE = edit.gameObject.AddComponent();
- editLE.preferredWidth = ColorEditButtonWidth;
- editLE.flexibleWidth = 0;
-
- var reset = UIUtility.CreateButton($"ColorResetButton", itemPanel.transform, "Reset");
- var resetLE = reset.gameObject.AddComponent();
- resetLE.preferredWidth = ResetButtonWidth;
- resetLE.flexibleWidth = 0;
-
- labelR.gameObject.AddComponent().Initialize(textBoxR, new[] { textBoxG, textBoxB });
- labelG.gameObject.AddComponent().Initialize(textBoxG, new[] { textBoxR, textBoxB });
- labelB.gameObject.AddComponent().Initialize(textBoxB, new[] { textBoxR, textBoxG });
- labelA.gameObject.AddComponent().Initialize(textBoxA);
- }
-
- //Float properties
- {
- var itemPanel = UIUtility.CreatePanel("FloatPanel", contentList.transform);
- itemPanel.gameObject.AddComponent();
- itemPanel.gameObject.AddComponent().padding = Padding;
- itemPanel.color = ItemColor;
-
- var label = UIUtility.CreateText("FloatLabel", itemPanel.transform, "");
- label.alignment = TextAnchor.MiddleLeft;
- label.color = Color.black;
- var labelLE = label.gameObject.AddComponent();
- labelLE.preferredWidth = LabelWidth;
- labelLE.flexibleWidth = LabelWidth;
-
- CreateInterpolableButton("SelectInterpolableFloatButton", itemPanel.transform);
-
- Slider sliderFloat = UIUtility.CreateSlider("FloatSlider", itemPanel.transform);
- var sliderFloatLE = sliderFloat.gameObject.AddComponent();
- sliderFloatLE.preferredWidth = SliderWidth;
- sliderFloatLE.flexibleWidth = 0;
-
- InputField textBoxFloat = UIUtility.CreateInputField("FloatInputField", itemPanel.transform);
- textBoxFloat.text = "0";
- var textBoxFloatLE = textBoxFloat.gameObject.AddComponent();
- textBoxFloatLE.preferredWidth = TextBoxWidth;
- textBoxFloatLE.flexibleWidth = 0;
-
- var reset = UIUtility.CreateButton($"FloatResetButton", itemPanel.transform, "Reset");
- var resetLE = reset.gameObject.AddComponent();
- resetLE.preferredWidth = ResetButtonWidth;
- resetLE.flexibleWidth = 0;
- label.gameObject.AddComponent().Initialize(textBoxFloat);
- }
-
- //Keyword properties
- {
- var itemPanel = UIUtility.CreatePanel("KeywordPanel", contentList.transform);
- itemPanel.gameObject.AddComponent();
- itemPanel.gameObject.AddComponent().padding = Padding;
- itemPanel.color = ItemColor;
-
- var label = UIUtility.CreateText("KeywordLabel", itemPanel.transform, "");
- label.alignment = TextAnchor.MiddleLeft;
- label.color = Color.black;
- var labelLE = label.gameObject.AddComponent();
- labelLE.preferredWidth = LabelWidth;
- labelLE.flexibleWidth = LabelWidth;
-
- Toggle toggleKeyword = UIUtility.CreateToggle("KeywordToggle", itemPanel.transform, "");
- var toggleKeywordLE = toggleKeyword.gameObject.AddComponent();
- toggleKeywordLE.preferredWidth = TextBoxWidth;
- toggleKeywordLE.flexibleWidth = 0;
-
- var reset = UIUtility.CreateButton($"KeywordResetButton", itemPanel.transform, "Reset");
- var resetLE = reset.gameObject.AddComponent();
- resetLE.preferredWidth = ResetButtonWidth;
- resetLE.flexibleWidth = 0;
- }
-
- return contentList.gameObject;
- }
-
- private static void CreateInterpolableButton(string objectName, Transform parent)
- {
- Button interpolableButton = UIUtility.CreateButton(objectName, parent, "O");
- var sinterpolableButtonLE = interpolableButton.gameObject.AddComponent();
- sinterpolableButtonLE.preferredWidth = 15;
- sinterpolableButtonLE.flexibleWidth = 0;
- interpolableButton.gameObject.SetActive(false);
-
-#if !API && !EC
- if (TimelineCompatibilityHelper.IsTimelineAvailable())
- interpolableButton.gameObject.SetActive(true);
-#endif
- }
- }
-}
+using UILib;
+using UnityEngine;
+using UnityEngine.UI;
+using static MaterialEditorAPI.MaterialEditorUI;
+
+namespace MaterialEditorAPI
+{
+ internal static class ItemTemplate
+ {
+ internal static GameObject CreateTemplate(Transform parent)
+ {
+ var contentList = UIUtility.CreatePanel("ListEntry", parent);
+ contentList.gameObject.AddComponent().preferredHeight = PanelHeight;
+ contentList.gameObject.AddComponent();
+ contentList.color = RowColor;
+
+ //Renderer
+ {
+ var itemPanel = UIUtility.CreatePanel("RendererPanel", contentList.transform);
+ itemPanel.gameObject.AddComponent();
+ itemPanel.gameObject.AddComponent().padding = Padding;
+ itemPanel.color = RendererColor;
+
+ var label = UIUtility.CreateText("RendererLabel", itemPanel.transform, "");
+ label.alignment = TextAnchor.MiddleLeft;
+ label.color = Color.black;
+ var labelLE = label.gameObject.AddComponent();
+ labelLE.preferredWidth = LabelWidth;
+ labelLE.flexibleWidth = LabelWidth;
+
+ Text labelRenderer = UIUtility.CreateText("RendererText", itemPanel.transform);
+ labelRenderer.alignment = TextAnchor.MiddleRight;
+ labelRenderer.color = Color.black;
+ var labelRendererLE = labelRenderer.gameObject.AddComponent();
+ labelRendererLE.preferredWidth = 200;
+ labelRendererLE.flexibleWidth = 0;
+
+ CreateInterpolableButton("SelectInterpolableRendererButton", itemPanel.transform);
+
+ Button exportUVButton = UIUtility.CreateButton("ExportUVButton", itemPanel.transform, "Export UV Map");
+ var exportUVButtonLE = exportUVButton.gameObject.AddComponent();
+ exportUVButtonLE.preferredWidth = 110;
+ exportUVButtonLE.flexibleWidth = 0;
+
+ Button exportMeshButton = UIUtility.CreateButton("ExportObjButton", itemPanel.transform, "Export .obj");
+ var exportMeshButtonLE = exportMeshButton.gameObject.AddComponent();
+ exportMeshButtonLE.preferredWidth = 85;
+ exportMeshButtonLE.flexibleWidth = 0;
+ }
+
+ //Renderer Enabled
+ {
+ var itemPanel = UIUtility.CreatePanel("RendererEnabledPanel", contentList.transform);
+ itemPanel.gameObject.AddComponent();
+ itemPanel.gameObject.AddComponent().padding = Padding;
+ itemPanel.color = ItemColor;
+
+ var label = UIUtility.CreateText("RendererEnabledLabel", itemPanel.transform, "");
+ label.alignment = TextAnchor.MiddleLeft;
+ label.color = Color.black;
+ var labelLE = label.gameObject.AddComponent();
+ labelLE.preferredWidth = LabelWidth;
+ labelLE.flexibleWidth = LabelWidth;
+
+ Toggle toggleEnabled = UIUtility.CreateToggle("RendererEnabledToggle", itemPanel.transform, "");
+ var toggleEnabledLE = toggleEnabled.gameObject.AddComponent();
+ toggleEnabledLE.preferredWidth = 12;
+ toggleEnabledLE.flexibleWidth = 0;
+ toggleEnabled.isOn = true;
+
+ var reset = UIUtility.CreateButton($"RendererEnabledResetButton", itemPanel.transform, "Reset");
+ var resetLE = reset.gameObject.AddComponent();
+ resetLE.preferredWidth = ResetButtonWidth;
+ resetLE.flexibleWidth = 0;
+ }
+
+ //Renderer ShadowCastingMode
+ {
+ var itemPanel = UIUtility.CreatePanel("RendererShadowCastingModePanel", contentList.transform);
+ itemPanel.gameObject.AddComponent();
+ itemPanel.gameObject.AddComponent().padding = Padding;
+ itemPanel.color = ItemColor;
+
+ var label = UIUtility.CreateText("RendererShadowCastingModeLabel", itemPanel.transform, "");
+ label.alignment = TextAnchor.MiddleLeft;
+ label.color = Color.black;
+ var labelLE = label.gameObject.AddComponent();
+ labelLE.preferredWidth = LabelWidth;
+ labelLE.flexibleWidth = LabelWidth;
+
+ Dropdown dropdownShadowCastingMode = UIUtility.CreateDropdown("RendererShadowCastingModeDropdown", itemPanel.transform);
+ dropdownShadowCastingMode.transform.SetRect(0f, 0f, 0f, 1f, 0f, 0f, 100f);
+ dropdownShadowCastingMode.captionText.transform.SetRect(0f, 0f, 1f, 1f, 5f, 2f, -15f, -2f);
+ dropdownShadowCastingMode.captionText.alignment = TextAnchor.MiddleLeft;
+ dropdownShadowCastingMode.options.Clear();
+ dropdownShadowCastingMode.options.Add(new Dropdown.OptionData("Off"));
+ dropdownShadowCastingMode.options.Add(new Dropdown.OptionData("On"));
+ dropdownShadowCastingMode.options.Add(new Dropdown.OptionData("Two Sided"));
+ dropdownShadowCastingMode.options.Add(new Dropdown.OptionData("Shadows Only"));
+ dropdownShadowCastingMode.value = 0;
+ dropdownShadowCastingMode.captionText.text = "Off";
+ var dropdownShadowCastingModeLE = dropdownShadowCastingMode.gameObject.AddComponent();
+ dropdownShadowCastingModeLE.preferredWidth = DropdownWidth;
+ dropdownShadowCastingModeLE.flexibleWidth = 0;
+
+ var reset = UIUtility.CreateButton($"RendererShadowCastingModeResetButton", itemPanel.transform, "Reset");
+ var resetLE = reset.gameObject.AddComponent();
+ resetLE.preferredWidth = ResetButtonWidth;
+ resetLE.flexibleWidth = 0;
+ }
+
+ //Renderer ReceiveShadows
+ {
+ var itemPanel = UIUtility.CreatePanel("RendererReceiveShadowsPanel", contentList.transform);
+ itemPanel.gameObject.AddComponent();
+ itemPanel.gameObject.AddComponent().padding = Padding;
+ itemPanel.color = ItemColor;
+
+ var label = UIUtility.CreateText("RendererReceiveShadowsLabel", itemPanel.transform, "");
+ label.alignment = TextAnchor.MiddleLeft;
+ label.color = Color.black;
+ var labelLE = label.gameObject.AddComponent();
+ labelLE.preferredWidth = LabelWidth;
+ labelLE.flexibleWidth = LabelWidth;
+
+ Toggle toggleReceiveShadows = UIUtility.CreateToggle("RendererReceiveShadowsToggle", itemPanel.transform, "");
+ var toggleReceiveShadowsLE = toggleReceiveShadows.gameObject.AddComponent();
+ toggleReceiveShadowsLE.preferredWidth = 12;
+ toggleReceiveShadowsLE.flexibleWidth = 0;
+ toggleReceiveShadows.isOn = true;
+
+ var reset = UIUtility.CreateButton($"RendererReceiveShadowsResetButton", itemPanel.transform, "Reset");
+ var resetLE = reset.gameObject.AddComponent();
+ resetLE.preferredWidth = ResetButtonWidth;
+ resetLE.flexibleWidth = 0;
+ }
+
+ //Renderer RendererUpdateWhenOffscreen
+ {
+ var itemPanel = UIUtility.CreatePanel("RendererUpdateWhenOffscreenPanel", contentList.transform);
+ itemPanel.gameObject.AddComponent();
+ itemPanel.gameObject.AddComponent().padding = Padding;
+ itemPanel.color = ItemColor;
+
+ var label = UIUtility.CreateText("RendererUpdateWhenOffscreenLabel", itemPanel.transform, "");
+ label.alignment = TextAnchor.MiddleLeft;
+ label.color = Color.black;
+ var labelLE = label.gameObject.AddComponent();
+ labelLE.preferredWidth = LabelWidth;
+ labelLE.flexibleWidth = LabelWidth;
+
+ Toggle toggleRendererUpdateWhenOffscreen = UIUtility.CreateToggle("RendererUpdateWhenOffscreenToggle", itemPanel.transform, "");
+ var toggleRendererUpdateWhenOffscreenLE = toggleRendererUpdateWhenOffscreen.gameObject.AddComponent();
+ toggleRendererUpdateWhenOffscreenLE.preferredWidth = 12;
+ toggleRendererUpdateWhenOffscreenLE.flexibleWidth = 0;
+ toggleRendererUpdateWhenOffscreen.isOn = false;
+
+ var reset = UIUtility.CreateButton($"RendererUpdateWhenOffscreenResetButton", itemPanel.transform, "Reset");
+ var resetLE = reset.gameObject.AddComponent();
+ resetLE.preferredWidth = ResetButtonWidth;
+ resetLE.flexibleWidth = 0;
+ }
+
+ //Renderer RecalulateNormals
+ {
+ var itemPanel = UIUtility.CreatePanel("RendererRecalculateNormalsPanel", contentList.transform);
+ itemPanel.gameObject.AddComponent();
+ itemPanel.gameObject.AddComponent().padding = Padding;
+ itemPanel.color = ItemColor;
+
+ var label = UIUtility.CreateText("RendererRecalculateNormalsLabel", itemPanel.transform, "");
+ label.alignment = TextAnchor.MiddleLeft;
+ label.color = Color.black;
+ var labelLE = label.gameObject.AddComponent();
+ labelLE.preferredWidth = LabelWidth;
+ labelLE.flexibleWidth = LabelWidth;
+
+ Toggle toggleRecalculateNormals = UIUtility.CreateToggle("RendererRecalculateNormalsToggle", itemPanel.transform, "");
+ var toggleRecalculateNormalsLE = toggleRecalculateNormals.gameObject.AddComponent();
+ toggleRecalculateNormalsLE.preferredWidth = 12;
+ toggleRecalculateNormalsLE.flexibleWidth = 0;
+ toggleRecalculateNormals.isOn = false;
+
+ var reset = UIUtility.CreateButton($"RendererRecalculateNormalsResetButton", itemPanel.transform, "Reset");
+ var resetLE = reset.gameObject.AddComponent();
+ resetLE.preferredWidth = ResetButtonWidth;
+ resetLE.flexibleWidth = 0;
+ }
+
+ //Material
+ {
+ var itemPanel = UIUtility.CreatePanel("MaterialPanel", contentList.transform);
+ itemPanel.gameObject.AddComponent();
+ itemPanel.gameObject.AddComponent().padding = Padding;
+ itemPanel.color = MaterialColor;
+
+ var label = UIUtility.CreateText("MaterialLabel", itemPanel.transform, "");
+ label.alignment = TextAnchor.MiddleLeft;
+ label.color = Color.black;
+ var labelLE = label.gameObject.AddComponent();
+ labelLE.preferredWidth = LabelWidth;
+ labelLE.flexibleWidth = LabelWidth;
+
+ Text materialText = UIUtility.CreateText("MaterialText", itemPanel.transform);
+ materialText.alignment = TextAnchor.MiddleRight;
+ materialText.color = Color.black;
+ var materialTextLE = materialText.gameObject.AddComponent();
+ materialTextLE.preferredWidth = 200;
+ materialTextLE.flexibleWidth = 0;
+
+ var copyEdits = UIUtility.CreateButton($"MaterialCopy", itemPanel.transform, "Copy Edits");
+ var copyEditsLE = copyEdits.gameObject.AddComponent();
+ copyEditsLE.preferredWidth = ButtonWidth;
+ copyEditsLE.flexibleWidth = 0;
+
+ var pasteEdits = UIUtility.CreateButton($"MaterialPaste", itemPanel.transform, "Paste Edits");
+ var pasteEditsLE = pasteEdits.gameObject.AddComponent();
+ pasteEditsLE.preferredWidth = ButtonWidth;
+ pasteEditsLE.flexibleWidth = 0;
+
+ var copy = UIUtility.CreateButton($"MaterialCopyRemove", itemPanel.transform, "Copy Material");
+ var copyLE = copy.gameObject.AddComponent();
+ copyLE.preferredWidth = ButtonWidth;
+ copyLE.flexibleWidth = 0;
+
+ var rename = UIUtility.CreateButton($"MaterialRename", itemPanel.transform, ">");
+ var renameLE = rename.gameObject.AddComponent();
+ renameLE.preferredWidth = ButtonWidth / 4;
+ renameLE.flexibleWidth = 0;
+ }
+
+ //Material Shader
+ {
+ var itemPanel = UIUtility.CreatePanel("ShaderPanel", contentList.transform);
+ itemPanel.gameObject.AddComponent();
+ itemPanel.gameObject.AddComponent().padding = Padding;
+ itemPanel.color = ItemColor;
+
+ var label = UIUtility.CreateText("ShaderLabel", itemPanel.transform, "");
+ label.alignment = TextAnchor.MiddleLeft;
+ label.color = Color.black;
+ var labelLE = label.gameObject.AddComponent();
+ labelLE.preferredWidth = LabelWidth;
+ labelLE.flexibleWidth = LabelWidth;
+
+ CreateInterpolableButton("SelectInterpolableShaderButton", itemPanel.transform);
+
+ Dropdown dropdownShader = UIUtility.CreateDropdown("ShaderDropdown", itemPanel.transform);
+ dropdownShader.transform.SetRect(0f, 0f, 0f, 1f, 0f, 0f, 100f);
+ dropdownShader.captionText.transform.SetRect(0f, 0f, 1f, 1f, 5f, 2f, -15f, -2f);
+ dropdownShader.captionText.alignment = TextAnchor.MiddleLeft;
+ dropdownShader.options.Clear();
+ dropdownShader.options.Add(new Dropdown.OptionData("Reset"));
+ foreach (var shader in MaterialEditorPluginBase.XMLShaderProperties)
+ if (shader.Key != "default")
+ dropdownShader.options.Add(new Dropdown.OptionData(shader.Key));
+ var dropdownShaderLE = dropdownShader.gameObject.AddComponent();
+ dropdownShaderLE.preferredWidth = DropdownWidth * 3;
+ dropdownShaderLE.flexibleWidth = 0;
+
+ var reset = UIUtility.CreateButton($"ShaderResetButton", itemPanel.transform, "Reset");
+ var resetLE = reset.gameObject.AddComponent();
+ resetLE.preferredWidth = ResetButtonWidth;
+ resetLE.flexibleWidth = 0;
+ }
+
+ //Material RenderQueue
+ {
+ var itemPanel = UIUtility.CreatePanel("ShaderRenderQueuePanel", contentList.transform);
+ itemPanel.gameObject.AddComponent();
+ itemPanel.gameObject.AddComponent().padding = Padding;
+ itemPanel.color = ItemColor;
+
+ var label = UIUtility.CreateText("ShaderRenderQueueLabel", itemPanel.transform, "");
+ label.alignment = TextAnchor.MiddleLeft;
+ label.color = Color.black;
+ var labelLE = label.gameObject.AddComponent();
+ labelLE.preferredWidth = LabelWidth;
+ labelLE.flexibleWidth = LabelWidth;
+
+ InputField textBoxShaderRenderQueue = UIUtility.CreateInputField("ShaderRenderQueueInput", itemPanel.transform);
+ textBoxShaderRenderQueue.text = "0";
+ var textBoxShaderRenderQueueLE = textBoxShaderRenderQueue.gameObject.AddComponent();
+ textBoxShaderRenderQueueLE.preferredWidth = TextBoxWidth;
+ textBoxShaderRenderQueueLE.flexibleWidth = 0;
+
+ var reset = UIUtility.CreateButton($"ShaderRenderQueueResetButton", itemPanel.transform, "Reset");
+ var resetLE = reset.gameObject.AddComponent();
+ resetLE.preferredWidth = ResetButtonWidth;
+ resetLE.flexibleWidth = 0;
+ }
+
+ // Property Category
+ {
+ var itemPanel = UIUtility.CreatePanel("PropertyCategoryPanel", contentList.transform);
+ itemPanel.gameObject.AddComponent();
+ itemPanel.gameObject.AddComponent().padding = Padding;
+ itemPanel.color = CategoryColor;
+
+ var label = UIUtility.CreateText("PropertyCategoryLabel", itemPanel.transform, "");
+ label.alignment = TextAnchor.MiddleLeft;
+ label.color = Color.black;
+ var labelLE = label.gameObject.AddComponent();
+ labelLE.preferredWidth = LabelWidth;
+ labelLE.flexibleWidth = LabelWidth;
+ }
+
+ //Texture properties
+ {
+ var itemPanel = UIUtility.CreatePanel("TexturePanel", contentList.transform);
+ itemPanel.gameObject.AddComponent();
+ itemPanel.gameObject.AddComponent().padding = Padding;
+ itemPanel.color = ItemColor;
+
+ var label = UIUtility.CreateText("TextureLabel", itemPanel.transform, "");
+ label.alignment = TextAnchor.MiddleLeft;
+ label.color = Color.black;
+ var labelLE = label.gameObject.AddComponent();
+ labelLE.preferredWidth = LabelWidth;
+ labelLE.flexibleWidth = LabelWidth;
+
+ CreateInterpolableButton("SelectInterpolableTextureButton", itemPanel.transform);
+
+ Button exportButton = UIUtility.CreateButton($"TextureExportButton", itemPanel.transform, $"Export Texture");
+ var exportButtonLE = exportButton.gameObject.AddComponent();
+ exportButtonLE.preferredWidth = ButtonWidth;
+ exportButtonLE.flexibleWidth = 0;
+
+ Button importButton = UIUtility.CreateButton($"TextureImportButton", itemPanel.transform, $"Import Texture");
+ var importButtonLE = importButton.gameObject.AddComponent();
+ importButtonLE.preferredWidth = ButtonWidth;
+ importButtonLE.flexibleWidth = 0;
+
+ var reset = UIUtility.CreateButton($"TextureResetButton", itemPanel.transform, "Reset");
+ var resetLE = reset.gameObject.AddComponent();
+ resetLE.preferredWidth = ResetButtonWidth;
+ resetLE.flexibleWidth = 0;
+ }
+
+ //Offset and Scale
+ {
+ var itemPanel = UIUtility.CreatePanel("OffsetScalePanel", contentList.transform);
+ itemPanel.gameObject.AddComponent();
+ itemPanel.gameObject.AddComponent().padding = Padding;
+ itemPanel.color = ItemColor;
+
+ var label = UIUtility.CreateText("OffsetScaleLabel", itemPanel.transform, "");
+ label.alignment = TextAnchor.MiddleLeft;
+ label.color = Color.black;
+ var labelLE = label.gameObject.AddComponent();
+ labelLE.preferredWidth = LabelWidth;
+ labelLE.flexibleWidth = LabelWidth;
+
+ Text labelOffsetX = UIUtility.CreateText("OffsetXText", itemPanel.transform, "Offset X");
+ labelOffsetX.alignment = TextAnchor.MiddleLeft;
+ labelOffsetX.color = Color.black;
+ var labelOffsetXLE = labelOffsetX.gameObject.AddComponent();
+ labelOffsetXLE.preferredWidth = LabelXWidth;
+ labelOffsetXLE.flexibleWidth = 0;
+
+ InputField textBoxOffsetX = UIUtility.CreateInputField("OffsetXInput", itemPanel.transform);
+ textBoxOffsetX.text = "0";
+ var textBoxOffsetXLE = textBoxOffsetX.gameObject.AddComponent();
+ textBoxOffsetXLE.preferredWidth = TextBoxXYWidth;
+ textBoxOffsetXLE.flexibleWidth = 0;
+
+ Text labelOffsetY = UIUtility.CreateText("OffsetYText", itemPanel.transform, "Y");
+ labelOffsetY.alignment = TextAnchor.MiddleLeft;
+ labelOffsetY.color = Color.black;
+ var labelOffsetYLE = labelOffsetY.gameObject.AddComponent();
+ labelOffsetYLE.preferredWidth = LabelYWidth;
+ labelOffsetYLE.flexibleWidth = 0;
+
+ InputField textBoxOffsetY = UIUtility.CreateInputField("OffsetYInput", itemPanel.transform);
+ textBoxOffsetY.text = "0";
+ var textBoxOffsetYLE = textBoxOffsetY.gameObject.AddComponent();
+ textBoxOffsetYLE.preferredWidth = TextBoxXYWidth;
+ textBoxOffsetYLE.flexibleWidth = 0;
+
+ labelOffsetX.gameObject.AddComponent().Initialize(textBoxOffsetX, new[] { textBoxOffsetY });
+ labelOffsetY.gameObject.AddComponent().Initialize(textBoxOffsetY, new[] { textBoxOffsetX });
+
+ //Scale
+ Text labelScaleX = UIUtility.CreateText("ScaleXText", itemPanel.transform, "Scale X");
+ labelScaleX.alignment = TextAnchor.MiddleLeft;
+ labelScaleX.color = Color.black;
+ var labelScaleXLE = labelScaleX.gameObject.AddComponent();
+ labelScaleXLE.preferredWidth = LabelXWidth;
+ labelScaleXLE.flexibleWidth = 0;
+
+ InputField textBoxScaleX = UIUtility.CreateInputField("ScaleXInput", itemPanel.transform);
+ textBoxScaleX.text = "0";
+ var textBoxScaleXLE = textBoxScaleX.gameObject.AddComponent();
+ textBoxScaleXLE.preferredWidth = TextBoxXYWidth;
+ textBoxScaleXLE.flexibleWidth = 0;
+
+ Text labelScaleY = UIUtility.CreateText("ScaleYText", itemPanel.transform, "Y");
+ labelScaleY.alignment = TextAnchor.MiddleLeft;
+ labelScaleY.color = Color.black;
+ var labelScaleYLE = labelScaleY.gameObject.AddComponent